"use strict";

var _sliceInstanceProperty = require("@babel/runtime-corejs3/core-js-stable/instance/slice");
var _Array$from = require("@babel/runtime-corejs3/core-js-stable/array/from");
var _Symbol = require("@babel/runtime-corejs3/core-js-stable/symbol");
var _getIteratorMethod = require("@babel/runtime-corejs3/core-js/get-iterator-method");
var _Array$isArray = require("@babel/runtime-corejs3/core-js-stable/array/is-array");
var _Object$defineProperty = require("@babel/runtime-corejs3/core-js-stable/object/define-property");
var _interopRequireDefault = require("@babel/runtime-corejs3/helpers/interopRequireDefault");
_Object$defineProperty(exports, "__esModule", {
  value: true
});
exports["default"] = void 0;
var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime-corejs3/helpers/slicedToArray"));
var _forEach = _interopRequireDefault(require("@babel/runtime-corejs3/core-js-stable/instance/for-each"));
var _concat = _interopRequireDefault(require("@babel/runtime-corejs3/core-js-stable/instance/concat"));
var _indexOf = _interopRequireDefault(require("@babel/runtime-corejs3/core-js-stable/instance/index-of"));
function _createForOfIteratorHelper(r, e) { var t = "undefined" != typeof _Symbol && _getIteratorMethod(r) || r["@@iterator"]; if (!t) { if (_Array$isArray(r) || (t = _unsupportedIterableToArray(r)) || e && r && "number" == typeof r.length) { t && (r = t); var _n = 0, F = function F() {}; return { s: F, n: function n() { return _n >= r.length ? { done: !0 } : { done: !1, value: r[_n++] }; }, e: function e(r) { throw r; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var o, a = !0, u = !1; return { s: function s() { t = t.call(r); }, n: function n() { var r = t.next(); return a = r.done, r; }, e: function e(r) { u = !0, o = r; }, f: function f() { try { a || null == t["return"] || t["return"](); } finally { if (u) throw o; } } }; }
function _unsupportedIterableToArray(r, a) { if (r) { var _context4; if ("string" == typeof r) return _arrayLikeToArray(r, a); var t = _sliceInstanceProperty(_context4 = {}.toString.call(r)).call(_context4, 8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? _Array$from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }
function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }
/*!
 * XRegExp Unicode Base 5.1.2
 * <xregexp.com>
 * Steven Levithan (c) 2008-present MIT License
 */
var _default = exports["default"] = function _default(XRegExp) {
  /**
   * Adds base support for Unicode matching:
   * - Adds syntax `\p{..}` for matching Unicode tokens. Tokens can be inverted using `\P{..}` or
   *   `\p{^..}`. Token names ignore case, spaces, hyphens, and underscores. You can omit the
   *   braces for token names that are a single letter (e.g. `\pL` or `PL`).
   * - Adds flag A (astral), which enables 21-bit Unicode support.
   * - Adds the `XRegExp.addUnicodeData` method used by other addons to provide character data.
   *
   * Unicode Base relies on externally provided Unicode character data. Official addons are
   * available to provide data for Unicode categories, scripts, and properties.
   *
   * @requires XRegExp
   */

  // ==--------------------------==
  // Private stuff
  // ==--------------------------==

  // Storage for Unicode data
  var unicode = {};
  var unicodeTypes = {};

  // Reuse utils
  var dec = XRegExp._dec;
  var hex = XRegExp._hex;
  var pad4 = XRegExp._pad4;

  // Generates a token lookup name: lowercase, with hyphens, spaces, and underscores removed
  function normalize(name) {
    return name.replace(/[- _]+/g, '').toLowerCase();
  }

  // Gets the decimal code of a literal code unit, \xHH, \uHHHH, or a backslash-escaped literal
  function charCode(chr) {
    var esc = /^\\[xu](.+)/.exec(chr);
    return esc ? dec(esc[1]) : chr.charCodeAt(chr[0] === '\\' ? 1 : 0);
  }

  // Inverts a list of ordered BMP characters and ranges
  function invertBmp(range) {
    var output = '';
    var lastEnd = -1;
    (0, _forEach["default"])(XRegExp).call(XRegExp, range, /(\\x..|\\u....|\\?[\s\S])(?:-(\\x..|\\u....|\\?[\s\S]))?/, function (m) {
      var start = charCode(m[1]);
      if (start > lastEnd + 1) {
        output += "\\u".concat(pad4(hex(lastEnd + 1)));
        if (start > lastEnd + 2) {
          output += "-\\u".concat(pad4(hex(start - 1)));
        }
      }
      lastEnd = charCode(m[2] || m[1]);
    });
    if (lastEnd < 0xFFFF) {
      output += "\\u".concat(pad4(hex(lastEnd + 1)));
      if (lastEnd < 0xFFFE) {
        output += '-\\uFFFF';
      }
    }
    return output;
  }

  // Generates an inverted BMP range on first use
  function cacheInvertedBmp(slug) {
    var prop = 'b!';
    return unicode[slug][prop] || (unicode[slug][prop] = invertBmp(unicode[slug].bmp));
  }

  // Combines and optionally negates BMP and astral data
  function buildAstral(slug, isNegated) {
    var item = unicode[slug];
    var combined = '';
    if (item.bmp && !item.isBmpLast) {
      var _context;
      combined = (0, _concat["default"])(_context = "[".concat(item.bmp, "]")).call(_context, item.astral ? '|' : '');
    }
    if (item.astral) {
      combined += item.astral;
    }
    if (item.isBmpLast && item.bmp) {
      var _context2;
      combined += (0, _concat["default"])(_context2 = "".concat(item.astral ? '|' : '', "[")).call(_context2, item.bmp, "]");
    }

    // Astral Unicode tokens always match a code point, never a code unit
    return isNegated ? "(?:(?!".concat(combined, ")(?:[\uD800-\uDBFF][\uDC00-\uDFFF]|[\0-\uFFFF]))") : "(?:".concat(combined, ")");
  }

  // Builds a complete astral pattern on first use
  function cacheAstral(slug, isNegated) {
    var prop = isNegated ? 'a!' : 'a=';
    return unicode[slug][prop] || (unicode[slug][prop] = buildAstral(slug, isNegated));
  }

  // ==--------------------------==
  // Core functionality
  // ==--------------------------==

  /*
   * Add astral mode (flag A) and Unicode token syntax: `\p{..}`, `\P{..}`, `\p{^..}`, `\pC`.
   */
  XRegExp.addToken(
  // Use `*` instead of `+` to avoid capturing `^` as the token name in `\p{^}`
  /\\([pP])(?:{(\^?)(?:(\w+)=)?([^}]*)}|([A-Za-z]))/, function (match, scope, flags) {
    var ERR_DOUBLE_NEG = 'Invalid double negation ';
    var ERR_UNKNOWN_NAME = 'Unknown Unicode token ';
    var ERR_UNKNOWN_REF = 'Unicode token missing data ';
    var ERR_ASTRAL_ONLY = 'Astral mode required for Unicode token ';
    var ERR_ASTRAL_IN_CLASS = 'Astral mode does not support Unicode tokens within character classes';
    var _match = (0, _slicedToArray2["default"])(match, 6),
      fullToken = _match[0],
      pPrefix = _match[1],
      caretNegation = _match[2],
      typePrefix = _match[3],
      tokenName = _match[4],
      tokenSingleCharName = _match[5];
    // Negated via \P{..} or \p{^..}
    var isNegated = pPrefix === 'P' || !!caretNegation;
    // Switch from BMP (0-FFFF) to astral (0-10FFFF) mode via flag A
    var isAstralMode = (0, _indexOf["default"])(flags).call(flags, 'A') !== -1;
    // Token lookup name. Check `tokenSingleCharName` first to avoid passing `undefined`
    // via `\p{}`
    var slug = normalize(tokenSingleCharName || tokenName);
    // Token data object
    var item = unicode[slug];
    if (pPrefix === 'P' && caretNegation) {
      throw new SyntaxError(ERR_DOUBLE_NEG + fullToken);
    }
    if (!unicode.hasOwnProperty(slug)) {
      throw new SyntaxError(ERR_UNKNOWN_NAME + fullToken);
    }
    if (typePrefix) {
      if (!(unicodeTypes[typePrefix] && unicodeTypes[typePrefix][slug])) {
        throw new SyntaxError(ERR_UNKNOWN_NAME + fullToken);
      }
    }

    // Switch to the negated form of the referenced Unicode token
    if (item.inverseOf) {
      slug = normalize(item.inverseOf);
      if (!unicode.hasOwnProperty(slug)) {
        var _context3;
        throw new ReferenceError((0, _concat["default"])(_context3 = "".concat(ERR_UNKNOWN_REF + fullToken, " -> ")).call(_context3, item.inverseOf));
      }
      item = unicode[slug];
      isNegated = !isNegated;
    }
    if (!(item.bmp || isAstralMode)) {
      throw new SyntaxError(ERR_ASTRAL_ONLY + fullToken);
    }
    if (isAstralMode) {
      if (scope === 'class') {
        throw new SyntaxError(ERR_ASTRAL_IN_CLASS);
      }
      return cacheAstral(slug, isNegated);
    }
    return scope === 'class' ? isNegated ? cacheInvertedBmp(slug) : item.bmp : "".concat((isNegated ? '[^' : '[') + item.bmp, "]");
  }, {
    scope: 'all',
    optionalFlags: 'A',
    leadChar: '\\'
  });

  /**
   * Adds to the list of Unicode tokens that XRegExp regexes can match via `\p` or `\P`.
   *
   * @memberOf XRegExp
   * @param {Array} data Objects with named character ranges. Each object may have properties
   *   `name`, `alias`, `isBmpLast`, `inverseOf`, `bmp`, and `astral`. All but `name` are
   *   optional, although one of `bmp` or `astral` is required (unless `inverseOf` is set). If
   *   `astral` is absent, the `bmp` data is used for BMP and astral modes. If `bmp` is absent,
   *   the name errors in BMP mode but works in astral mode. If both `bmp` and `astral` are
   *   provided, the `bmp` data only is used in BMP mode, and the combination of `bmp` and
   *   `astral` data is used in astral mode. `isBmpLast` is needed when a token matches orphan
   *   high surrogates *and* uses surrogate pairs to match astral code points. The `bmp` and
   *   `astral` data should be a combination of literal characters and `\xHH` or `\uHHHH` escape
   *   sequences, with hyphens to create ranges. Any regex metacharacters in the data should be
   *   escaped, apart from range-creating hyphens. The `astral` data can additionally use
   *   character classes and alternation, and should use surrogate pairs to represent astral code
   *   points. `inverseOf` can be used to avoid duplicating character data if a Unicode token is
   *   defined as the exact inverse of another token.
   * @param {String} [typePrefix] Enables optionally using this type as a prefix for all of the
   *   provided Unicode tokens, e.g. if given `'Type'`, then `\p{TokenName}` can also be written
   *   as `\p{Type=TokenName}`.
   * @example
   *
   * // Basic use
   * XRegExp.addUnicodeData([{
   *   name: 'XDigit',
   *   alias: 'Hexadecimal',
   *   bmp: '0-9A-Fa-f'
   * }]);
   * XRegExp('\\p{XDigit}:\\p{Hexadecimal}+').test('0:3D'); // -> true
   */
  XRegExp.addUnicodeData = function (data, typePrefix) {
    var ERR_NO_NAME = 'Unicode token requires name';
    var ERR_NO_DATA = 'Unicode token has no character data ';
    if (typePrefix) {
      // Case sensitive to match ES2018
      unicodeTypes[typePrefix] = {};
    }
    var _iterator = _createForOfIteratorHelper(data),
      _step;
    try {
      for (_iterator.s(); !(_step = _iterator.n()).done;) {
        var item = _step.value;
        if (!item.name) {
          throw new Error(ERR_NO_NAME);
        }
        if (!(item.inverseOf || item.bmp || item.astral)) {
          throw new Error(ERR_NO_DATA + item.name);
        }
        var normalizedName = normalize(item.name);
        unicode[normalizedName] = item;
        if (typePrefix) {
          unicodeTypes[typePrefix][normalizedName] = true;
        }
        if (item.alias) {
          var normalizedAlias = normalize(item.alias);
          unicode[normalizedAlias] = item;
          if (typePrefix) {
            unicodeTypes[typePrefix][normalizedAlias] = true;
          }
        }
      }

      // Reset the pattern cache used by the `XRegExp` constructor, since the same pattern and
      // flags might now produce different results
    } catch (err) {
      _iterator.e(err);
    } finally {
      _iterator.f();
    }
    XRegExp.cache.flush('patterns');
  };

  /**
   * @ignore
   *
   * Return a reference to the internal Unicode definition structure for the given Unicode
   * Property if the given name is a legal Unicode Property for use in XRegExp `\p` or `\P` regex
   * constructs.
   *
   * @memberOf XRegExp
   * @param {String} name Name by which the Unicode Property may be recognized (case-insensitive),
   *   e.g. `'N'` or `'Number'`. The given name is matched against all registered Unicode
   *   Properties and Property Aliases.
   * @returns {Object} Reference to definition structure when the name matches a Unicode Property.
   *
   * @note
   * For more info on Unicode Properties, see also http://unicode.org/reports/tr18/#Categories.
   *
   * @note
   * This method is *not* part of the officially documented API and may change or be removed in
   * the future. It is meant for userland code that wishes to reuse the (large) internal Unicode
   * structures set up by XRegExp.
   */
  XRegExp._getUnicodeProperty = function (name) {
    var slug = normalize(name);
    return unicode[slug];
  };
};
module.exports = exports.default;