(self["webpackChunkbrowser_extension"] = self["webpackChunkbrowser_extension"] || []).push([[870],{

/***/ 97730:
/***/ ((module, exports, __webpack_require__) => {

var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_RESULT__;
/**
 * AdGuard Scriptlets
 * Version 1.12.1
 */

(function (factory) {
     true ? !(__WEBPACK_AMD_DEFINE_FACTORY__ = (factory),
		__WEBPACK_AMD_DEFINE_RESULT__ = (typeof __WEBPACK_AMD_DEFINE_FACTORY__ === 'function' ?
		(__WEBPACK_AMD_DEFINE_FACTORY__.call(exports, __webpack_require__, exports, module)) :
		__WEBPACK_AMD_DEFINE_FACTORY__),
		__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__)) :
    0;
})((function () {
    /**
     * Concat dependencies to scriptlet code
     *
     * @param scriptlet scriptlet or redirect function
     * @returns string view of scriptlet with attached dependencies
     */
    function attachDependencies(scriptlet) {
      var _scriptlet$injections = scriptlet.injections,
        injections = _scriptlet$injections === void 0 ? [] : _scriptlet$injections;
      return injections.reduce(function (accum, dep) {
        return "".concat(accum, "\n").concat(dep.toString());
      }, scriptlet.toString());
    }

    /**
     * Wraps a scriptlet call within an existing code block to ensure it executes only once per unique context.
     *
     * This function constructs a wrapper around the provided scriptlet function and its corresponding code block.
     * It uses a unique identifier to prevent the scriptlet from being executed multiple times in the same context.
     *
     * @param scriptlet - The scriptlet function to be executed.
     * @param code - The string representation of the scriptlet's code.
     * @returns A string that represents the wrapped scriptlet call, ensuring it executes only once per unique context.
     */
    function addCall(scriptlet, code) {
      return "\n    const flag = 'done';\n    const uniqueIdentifier = source.uniqueId + source.name + '_' + (Array.isArray(args) ? args.join('_') : '');\n    // Check if the scriptlet has already been executed using the unique identifier\n    if (source.uniqueId) {\n        if (Window.prototype.toString[uniqueIdentifier] === flag) { return; }\n    }\n    ".concat(code, "\n    const updatedArgs = args ? [].concat(source).concat(args) : [source];\n    try {\n        ").concat(scriptlet.name, ".apply(this, updatedArgs);\n        if (source.uniqueId) {\n            Object.defineProperty(Window.prototype.toString, uniqueIdentifier, {\n                value: flag,\n                enumerable: false,\n                writable: false,\n                configurable: false\n            });\n        }\n    } catch (e) {\n        console.log(e);\n    }");
    }

    /**
     * Wrap function into IIFE (Immediately invoked function expression)
     *
     * @example
     * const source = {
     *      args: ["aaa", "bbb"],
     *      name: 'noeval',
     * };
     * const code = "function noeval(source, args) { alert(source); } noeval.apply(this, args);"
     * const result = wrapInIIFE(source, code);
     *
     * // result
     * `(function(source, args) {
     *      function noeval(source) { alert(source); }
     *      noeval.apply(this, args);
     * )({"args": ["aaa", "bbb"], "name":"noeval"}, ["aaa", "bbb"])`
     * @param source - object with scriptlet properties
     * @param code - scriptlet source code with dependencies
     * @param redirect if function is redirect
     * @returns full scriptlet code
     */
    function passSourceAndProps(source, code) {
      var redirect = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
      var sourceString = JSON.stringify(source);
      var argsString = source.args ? "[".concat(source.args.map(function (arg) {
        return JSON.stringify(arg);
      }), "]") : undefined;
      var params = argsString ? "".concat(sourceString, ", ").concat(argsString) : sourceString;
      if (redirect) {
        return "(function(source, args){\n".concat(code, "\n})(").concat(params, ");");
      }
      return "(".concat(code, ")(").concat(params, ");");
    }

    /**
     * Wrap code in no name function
     *
     * @param code which must be wrapped
     * @returns wrapped code
     */
    function wrapInNonameFunc(code) {
      return "function(source, args){\n".concat(code, "\n}");
    }

    function _arrayWithHoles(arr) {
      if (Array.isArray(arr)) return arr;
    }

    function _iterableToArrayLimit(arr, i) {
      var _i = null == arr ? null : "undefined" != typeof Symbol && arr[Symbol.iterator] || arr["@@iterator"];
      if (null != _i) {
        var _s,
          _e,
          _x,
          _r,
          _arr = [],
          _n = !0,
          _d = !1;
        try {
          if (_x = (_i = _i.call(arr)).next, 0 === i) {
            if (Object(_i) !== _i) return;
            _n = !1;
          } else for (; !(_n = (_s = _x.call(_i)).done) && (_arr.push(_s.value), _arr.length !== i); _n = !0);
        } catch (err) {
          _d = !0, _e = err;
        } finally {
          try {
            if (!_n && null != _i["return"] && (_r = _i["return"](), Object(_r) !== _r)) return;
          } finally {
            if (_d) throw _e;
          }
        }
        return _arr;
      }
    }

    function _arrayLikeToArray$3(arr, len) {
      if (len == null || len > arr.length) len = arr.length;
      for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i];
      return arr2;
    }

    function _unsupportedIterableToArray$3(o, minLen) {
      if (!o) return;
      if (typeof o === "string") return _arrayLikeToArray$3(o, minLen);
      var n = Object.prototype.toString.call(o).slice(8, -1);
      if (n === "Object" && o.constructor) n = o.constructor.name;
      if (n === "Map" || n === "Set") return Array.from(o);
      if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray$3(o, minLen);
    }

    function _nonIterableRest() {
      throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
    }

    function _slicedToArray$1(arr, i) {
      return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray$3(arr, i) || _nonIterableRest();
    }

    function getDefaultExportFromCjs$1 (x) {
    	return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, 'default') ? x['default'] : x;
    }

    var debug$1 = typeof process === 'object' && process.env && process.env.NODE_DEBUG && /\bsemver\b/i.test(process.env.NODE_DEBUG) ? function () {
      for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
        args[_key] = arguments[_key];
      }
      return console.error('SEMVER', ...args);
    } : function () {};
    var debug_1 = debug$1;

    // Note: this is the semver.org version of the spec that it implements
    // Not necessarily the package version of this code.
    var SEMVER_SPEC_VERSION = '2.0.0';
    var MAX_LENGTH$1 = 256;
    var MAX_SAFE_INTEGER$1 = Number.MAX_SAFE_INTEGER || /* istanbul ignore next */9007199254740991;

    // Max safe segment length for coercion.
    var MAX_SAFE_COMPONENT_LENGTH = 16;

    // Max safe length for a build identifier. The max length minus 6 characters for
    // the shortest version with a build 0.0.0+BUILD.
    var MAX_SAFE_BUILD_LENGTH = MAX_LENGTH$1 - 6;
    var RELEASE_TYPES = ['major', 'premajor', 'minor', 'preminor', 'patch', 'prepatch', 'prerelease'];
    var constants = {
      MAX_LENGTH: MAX_LENGTH$1,
      MAX_SAFE_COMPONENT_LENGTH,
      MAX_SAFE_BUILD_LENGTH,
      MAX_SAFE_INTEGER: MAX_SAFE_INTEGER$1,
      RELEASE_TYPES,
      SEMVER_SPEC_VERSION,
      FLAG_INCLUDE_PRERELEASE: 1,
      FLAG_LOOSE: 2
    };

    var re$2 = {exports: {}};

    (function (module, exports) {
      var MAX_SAFE_COMPONENT_LENGTH = constants.MAX_SAFE_COMPONENT_LENGTH,
        MAX_SAFE_BUILD_LENGTH = constants.MAX_SAFE_BUILD_LENGTH,
        MAX_LENGTH = constants.MAX_LENGTH;
      var debug = debug_1;
      exports = module.exports = {};

      // The actual regexps go on exports.re
      var re = exports.re = [];
      var safeRe = exports.safeRe = [];
      var src = exports.src = [];
      var t = exports.t = {};
      var R = 0;
      var LETTERDASHNUMBER = '[a-zA-Z0-9-]';

      // Replace some greedy regex tokens to prevent regex dos issues. These regex are
      // used internally via the safeRe object since all inputs in this library get
      // normalized first to trim and collapse all extra whitespace. The original
      // regexes are exported for userland consumption and lower level usage. A
      // future breaking change could export the safer regex only with a note that
      // all input should have extra whitespace removed.
      var safeRegexReplacements = [['\\s', 1], ['\\d', MAX_LENGTH], [LETTERDASHNUMBER, MAX_SAFE_BUILD_LENGTH]];
      var makeSafeRegex = function makeSafeRegex(value) {
        for (var _i = 0, _safeRegexReplacement = safeRegexReplacements; _i < _safeRegexReplacement.length; _i++) {
          var _safeRegexReplacement2 = _slicedToArray$1(_safeRegexReplacement[_i], 2),
            token = _safeRegexReplacement2[0],
            max = _safeRegexReplacement2[1];
          value = value.split("".concat(token, "*")).join("".concat(token, "{0,").concat(max, "}")).split("".concat(token, "+")).join("".concat(token, "{1,").concat(max, "}"));
        }
        return value;
      };
      var createToken = function createToken(name, value, isGlobal) {
        var safe = makeSafeRegex(value);
        var index = R++;
        debug(name, index, value);
        t[name] = index;
        src[index] = value;
        re[index] = new RegExp(value, isGlobal ? 'g' : undefined);
        safeRe[index] = new RegExp(safe, isGlobal ? 'g' : undefined);
      };

      // The following Regular Expressions can be used for tokenizing,
      // validating, and parsing SemVer version strings.

      // ## Numeric Identifier
      // A single `0`, or a non-zero digit followed by zero or more digits.

      createToken('NUMERICIDENTIFIER', '0|[1-9]\\d*');
      createToken('NUMERICIDENTIFIERLOOSE', '\\d+');

      // ## Non-numeric Identifier
      // Zero or more digits, followed by a letter or hyphen, and then zero or
      // more letters, digits, or hyphens.

      createToken('NONNUMERICIDENTIFIER', "\\d*[a-zA-Z-]".concat(LETTERDASHNUMBER, "*"));

      // ## Main Version
      // Three dot-separated numeric identifiers.

      createToken('MAINVERSION', "(".concat(src[t.NUMERICIDENTIFIER], ")\\.") + "(".concat(src[t.NUMERICIDENTIFIER], ")\\.") + "(".concat(src[t.NUMERICIDENTIFIER], ")"));
      createToken('MAINVERSIONLOOSE', "(".concat(src[t.NUMERICIDENTIFIERLOOSE], ")\\.") + "(".concat(src[t.NUMERICIDENTIFIERLOOSE], ")\\.") + "(".concat(src[t.NUMERICIDENTIFIERLOOSE], ")"));

      // ## Pre-release Version Identifier
      // A numeric identifier, or a non-numeric identifier.

      createToken('PRERELEASEIDENTIFIER', "(?:".concat(src[t.NUMERICIDENTIFIER], "|").concat(src[t.NONNUMERICIDENTIFIER], ")"));
      createToken('PRERELEASEIDENTIFIERLOOSE', "(?:".concat(src[t.NUMERICIDENTIFIERLOOSE], "|").concat(src[t.NONNUMERICIDENTIFIER], ")"));

      // ## Pre-release Version
      // Hyphen, followed by one or more dot-separated pre-release version
      // identifiers.

      createToken('PRERELEASE', "(?:-(".concat(src[t.PRERELEASEIDENTIFIER], "(?:\\.").concat(src[t.PRERELEASEIDENTIFIER], ")*))"));
      createToken('PRERELEASELOOSE', "(?:-?(".concat(src[t.PRERELEASEIDENTIFIERLOOSE], "(?:\\.").concat(src[t.PRERELEASEIDENTIFIERLOOSE], ")*))"));

      // ## Build Metadata Identifier
      // Any combination of digits, letters, or hyphens.

      createToken('BUILDIDENTIFIER', "".concat(LETTERDASHNUMBER, "+"));

      // ## Build Metadata
      // Plus sign, followed by one or more period-separated build metadata
      // identifiers.

      createToken('BUILD', "(?:\\+(".concat(src[t.BUILDIDENTIFIER], "(?:\\.").concat(src[t.BUILDIDENTIFIER], ")*))"));

      // ## Full Version String
      // A main version, followed optionally by a pre-release version and
      // build metadata.

      // Note that the only major, minor, patch, and pre-release sections of
      // the version string are capturing groups.  The build metadata is not a
      // capturing group, because it should not ever be used in version
      // comparison.

      createToken('FULLPLAIN', "v?".concat(src[t.MAINVERSION]).concat(src[t.PRERELEASE], "?").concat(src[t.BUILD], "?"));
      createToken('FULL', "^".concat(src[t.FULLPLAIN], "$"));

      // like full, but allows v1.2.3 and =1.2.3, which people do sometimes.
      // also, 1.0.0alpha1 (prerelease without the hyphen) which is pretty
      // common in the npm registry.
      createToken('LOOSEPLAIN', "[v=\\s]*".concat(src[t.MAINVERSIONLOOSE]).concat(src[t.PRERELEASELOOSE], "?").concat(src[t.BUILD], "?"));
      createToken('LOOSE', "^".concat(src[t.LOOSEPLAIN], "$"));
      createToken('GTLT', '((?:<|>)?=?)');

      // Something like "2.*" or "1.2.x".
      // Note that "x.x" is a valid xRange identifer, meaning "any version"
      // Only the first item is strictly required.
      createToken('XRANGEIDENTIFIERLOOSE', "".concat(src[t.NUMERICIDENTIFIERLOOSE], "|x|X|\\*"));
      createToken('XRANGEIDENTIFIER', "".concat(src[t.NUMERICIDENTIFIER], "|x|X|\\*"));
      createToken('XRANGEPLAIN', "[v=\\s]*(".concat(src[t.XRANGEIDENTIFIER], ")") + "(?:\\.(".concat(src[t.XRANGEIDENTIFIER], ")") + "(?:\\.(".concat(src[t.XRANGEIDENTIFIER], ")") + "(?:".concat(src[t.PRERELEASE], ")?").concat(src[t.BUILD], "?") + ")?)?");
      createToken('XRANGEPLAINLOOSE', "[v=\\s]*(".concat(src[t.XRANGEIDENTIFIERLOOSE], ")") + "(?:\\.(".concat(src[t.XRANGEIDENTIFIERLOOSE], ")") + "(?:\\.(".concat(src[t.XRANGEIDENTIFIERLOOSE], ")") + "(?:".concat(src[t.PRERELEASELOOSE], ")?").concat(src[t.BUILD], "?") + ")?)?");
      createToken('XRANGE', "^".concat(src[t.GTLT], "\\s*").concat(src[t.XRANGEPLAIN], "$"));
      createToken('XRANGELOOSE', "^".concat(src[t.GTLT], "\\s*").concat(src[t.XRANGEPLAINLOOSE], "$"));

      // Coercion.
      // Extract anything that could conceivably be a part of a valid semver
      createToken('COERCEPLAIN', "".concat('(^|[^\\d])' + '(\\d{1,').concat(MAX_SAFE_COMPONENT_LENGTH, "})") + "(?:\\.(\\d{1,".concat(MAX_SAFE_COMPONENT_LENGTH, "}))?") + "(?:\\.(\\d{1,".concat(MAX_SAFE_COMPONENT_LENGTH, "}))?"));
      createToken('COERCE', "".concat(src[t.COERCEPLAIN], "(?:$|[^\\d])"));
      createToken('COERCEFULL', src[t.COERCEPLAIN] + "(?:".concat(src[t.PRERELEASE], ")?") + "(?:".concat(src[t.BUILD], ")?") + "(?:$|[^\\d])");
      createToken('COERCERTL', src[t.COERCE], true);
      createToken('COERCERTLFULL', src[t.COERCEFULL], true);

      // Tilde ranges.
      // Meaning is "reasonably at or greater than"
      createToken('LONETILDE', '(?:~>?)');
      createToken('TILDETRIM', "(\\s*)".concat(src[t.LONETILDE], "\\s+"), true);
      exports.tildeTrimReplace = '$1~';
      createToken('TILDE', "^".concat(src[t.LONETILDE]).concat(src[t.XRANGEPLAIN], "$"));
      createToken('TILDELOOSE', "^".concat(src[t.LONETILDE]).concat(src[t.XRANGEPLAINLOOSE], "$"));

      // Caret ranges.
      // Meaning is "at least and backwards compatible with"
      createToken('LONECARET', '(?:\\^)');
      createToken('CARETTRIM', "(\\s*)".concat(src[t.LONECARET], "\\s+"), true);
      exports.caretTrimReplace = '$1^';
      createToken('CARET', "^".concat(src[t.LONECARET]).concat(src[t.XRANGEPLAIN], "$"));
      createToken('CARETLOOSE', "^".concat(src[t.LONECARET]).concat(src[t.XRANGEPLAINLOOSE], "$"));

      // A simple gt/lt/eq thing, or just "" to indicate "any version"
      createToken('COMPARATORLOOSE', "^".concat(src[t.GTLT], "\\s*(").concat(src[t.LOOSEPLAIN], ")$|^$"));
      createToken('COMPARATOR', "^".concat(src[t.GTLT], "\\s*(").concat(src[t.FULLPLAIN], ")$|^$"));

      // An expression to strip any whitespace between the gtlt and the thing
      // it modifies, so that `> 1.2.3` ==> `>1.2.3`
      createToken('COMPARATORTRIM', "(\\s*)".concat(src[t.GTLT], "\\s*(").concat(src[t.LOOSEPLAIN], "|").concat(src[t.XRANGEPLAIN], ")"), true);
      exports.comparatorTrimReplace = '$1$2$3';

      // Something like `1.2.3 - 1.2.4`
      // Note that these all use the loose form, because they'll be
      // checked against either the strict or loose comparator form
      // later.
      createToken('HYPHENRANGE', "^\\s*(".concat(src[t.XRANGEPLAIN], ")") + "\\s+-\\s+" + "(".concat(src[t.XRANGEPLAIN], ")") + "\\s*$");
      createToken('HYPHENRANGELOOSE', "^\\s*(".concat(src[t.XRANGEPLAINLOOSE], ")") + "\\s+-\\s+" + "(".concat(src[t.XRANGEPLAINLOOSE], ")") + "\\s*$");

      // Star ranges basically just allow anything at all.
      createToken('STAR', '(<|>)?=?\\s*\\*');
      // >=0.0.0 is like a star
      createToken('GTE0', '^\\s*>=\\s*0\\.0\\.0\\s*$');
      createToken('GTE0PRE', '^\\s*>=\\s*0\\.0\\.0-0\\s*$');
    })(re$2, re$2.exports);
    var reExports = re$2.exports;

    // parse out just the options we care about
    var looseOption = Object.freeze({
      loose: true
    });
    var emptyOpts = Object.freeze({});
    var parseOptions$1 = function parseOptions(options) {
      if (!options) {
        return emptyOpts;
      }
      if (typeof options !== 'object') {
        return looseOption;
      }
      return options;
    };
    var parseOptions_1 = parseOptions$1;

    var numeric = /^[0-9]+$/;
    var compareIdentifiers$1 = function compareIdentifiers(a, b) {
      var anum = numeric.test(a);
      var bnum = numeric.test(b);
      if (anum && bnum) {
        a = +a;
        b = +b;
      }
      return a === b ? 0 : anum && !bnum ? -1 : bnum && !anum ? 1 : a < b ? -1 : 1;
    };
    var rcompareIdentifiers = function rcompareIdentifiers(a, b) {
      return compareIdentifiers$1(b, a);
    };
    var identifiers = {
      compareIdentifiers: compareIdentifiers$1,
      rcompareIdentifiers
    };

    var debug = debug_1;
    var MAX_LENGTH = constants.MAX_LENGTH,
      MAX_SAFE_INTEGER = constants.MAX_SAFE_INTEGER;
    var re$1 = reExports.safeRe,
      t$1 = reExports.t;
    var parseOptions = parseOptions_1;
    var compareIdentifiers = identifiers.compareIdentifiers;
    let SemVer$2 = class SemVer {
      constructor(version, options) {
        options = parseOptions(options);
        if (version instanceof SemVer) {
          if (version.loose === !!options.loose && version.includePrerelease === !!options.includePrerelease) {
            return version;
          } else {
            version = version.version;
          }
        } else if (typeof version !== 'string') {
          throw new TypeError("Invalid version. Must be a string. Got type \"".concat(typeof version, "\"."));
        }
        if (version.length > MAX_LENGTH) {
          throw new TypeError("version is longer than ".concat(MAX_LENGTH, " characters"));
        }
        debug('SemVer', version, options);
        this.options = options;
        this.loose = !!options.loose;
        // this isn't actually relevant for versions, but keep it so that we
        // don't run into trouble passing this.options around.
        this.includePrerelease = !!options.includePrerelease;
        var m = version.trim().match(options.loose ? re$1[t$1.LOOSE] : re$1[t$1.FULL]);
        if (!m) {
          throw new TypeError("Invalid Version: ".concat(version));
        }
        this.raw = version;

        // these are actually numbers
        this.major = +m[1];
        this.minor = +m[2];
        this.patch = +m[3];
        if (this.major > MAX_SAFE_INTEGER || this.major < 0) {
          throw new TypeError('Invalid major version');
        }
        if (this.minor > MAX_SAFE_INTEGER || this.minor < 0) {
          throw new TypeError('Invalid minor version');
        }
        if (this.patch > MAX_SAFE_INTEGER || this.patch < 0) {
          throw new TypeError('Invalid patch version');
        }

        // numberify any prerelease numeric ids
        if (!m[4]) {
          this.prerelease = [];
        } else {
          this.prerelease = m[4].split('.').map(function (id) {
            if (/^[0-9]+$/.test(id)) {
              var num = +id;
              if (num >= 0 && num < MAX_SAFE_INTEGER) {
                return num;
              }
            }
            return id;
          });
        }
        this.build = m[5] ? m[5].split('.') : [];
        this.format();
      }
      format() {
        this.version = "".concat(this.major, ".").concat(this.minor, ".").concat(this.patch);
        if (this.prerelease.length) {
          this.version += "-".concat(this.prerelease.join('.'));
        }
        return this.version;
      }
      toString() {
        return this.version;
      }
      compare(other) {
        debug('SemVer.compare', this.version, this.options, other);
        if (!(other instanceof SemVer)) {
          if (typeof other === 'string' && other === this.version) {
            return 0;
          }
          other = new SemVer(other, this.options);
        }
        if (other.version === this.version) {
          return 0;
        }
        return this.compareMain(other) || this.comparePre(other);
      }
      compareMain(other) {
        if (!(other instanceof SemVer)) {
          other = new SemVer(other, this.options);
        }
        return compareIdentifiers(this.major, other.major) || compareIdentifiers(this.minor, other.minor) || compareIdentifiers(this.patch, other.patch);
      }
      comparePre(other) {
        if (!(other instanceof SemVer)) {
          other = new SemVer(other, this.options);
        }

        // NOT having a prerelease is > having one
        if (this.prerelease.length && !other.prerelease.length) {
          return -1;
        } else if (!this.prerelease.length && other.prerelease.length) {
          return 1;
        } else if (!this.prerelease.length && !other.prerelease.length) {
          return 0;
        }
        var i = 0;
        do {
          var a = this.prerelease[i];
          var b = other.prerelease[i];
          debug('prerelease compare', i, a, b);
          if (a === undefined && b === undefined) {
            return 0;
          } else if (b === undefined) {
            return 1;
          } else if (a === undefined) {
            return -1;
          } else if (a === b) {
            continue;
          } else {
            return compareIdentifiers(a, b);
          }
        } while (++i);
      }
      compareBuild(other) {
        if (!(other instanceof SemVer)) {
          other = new SemVer(other, this.options);
        }
        var i = 0;
        do {
          var a = this.build[i];
          var b = other.build[i];
          debug('build compare', i, a, b);
          if (a === undefined && b === undefined) {
            return 0;
          } else if (b === undefined) {
            return 1;
          } else if (a === undefined) {
            return -1;
          } else if (a === b) {
            continue;
          } else {
            return compareIdentifiers(a, b);
          }
        } while (++i);
      }

      // preminor will bump the version up to the next minor release, and immediately
      // down to pre-release. premajor and prepatch work the same way.
      inc(release, identifier, identifierBase) {
        switch (release) {
          case 'premajor':
            this.prerelease.length = 0;
            this.patch = 0;
            this.minor = 0;
            this.major++;
            this.inc('pre', identifier, identifierBase);
            break;
          case 'preminor':
            this.prerelease.length = 0;
            this.patch = 0;
            this.minor++;
            this.inc('pre', identifier, identifierBase);
            break;
          case 'prepatch':
            // If this is already a prerelease, it will bump to the next version
            // drop any prereleases that might already exist, since they are not
            // relevant at this point.
            this.prerelease.length = 0;
            this.inc('patch', identifier, identifierBase);
            this.inc('pre', identifier, identifierBase);
            break;
          // If the input is a non-prerelease version, this acts the same as
          // prepatch.
          case 'prerelease':
            if (this.prerelease.length === 0) {
              this.inc('patch', identifier, identifierBase);
            }
            this.inc('pre', identifier, identifierBase);
            break;
          case 'major':
            // If this is a pre-major version, bump up to the same major version.
            // Otherwise increment major.
            // 1.0.0-5 bumps to 1.0.0
            // 1.1.0 bumps to 2.0.0
            if (this.minor !== 0 || this.patch !== 0 || this.prerelease.length === 0) {
              this.major++;
            }
            this.minor = 0;
            this.patch = 0;
            this.prerelease = [];
            break;
          case 'minor':
            // If this is a pre-minor version, bump up to the same minor version.
            // Otherwise increment minor.
            // 1.2.0-5 bumps to 1.2.0
            // 1.2.1 bumps to 1.3.0
            if (this.patch !== 0 || this.prerelease.length === 0) {
              this.minor++;
            }
            this.patch = 0;
            this.prerelease = [];
            break;
          case 'patch':
            // If this is not a pre-release version, it will increment the patch.
            // If it is a pre-release it will bump up to the same patch version.
            // 1.2.0-5 patches to 1.2.0
            // 1.2.0 patches to 1.2.1
            if (this.prerelease.length === 0) {
              this.patch++;
            }
            this.prerelease = [];
            break;
          // This probably shouldn't be used publicly.
          // 1.0.0 'pre' would become 1.0.0-0 which is the wrong direction.
          case 'pre':
            {
              var base = Number(identifierBase) ? 1 : 0;
              if (!identifier && identifierBase === false) {
                throw new Error('invalid increment argument: identifier is empty');
              }
              if (this.prerelease.length === 0) {
                this.prerelease = [base];
              } else {
                var i = this.prerelease.length;
                while (--i >= 0) {
                  if (typeof this.prerelease[i] === 'number') {
                    this.prerelease[i]++;
                    i = -2;
                  }
                }
                if (i === -1) {
                  // didn't increment anything
                  if (identifier === this.prerelease.join('.') && identifierBase === false) {
                    throw new Error('invalid increment argument: identifier already exists');
                  }
                  this.prerelease.push(base);
                }
              }
              if (identifier) {
                // 1.2.0-beta.1 bumps to 1.2.0-beta.2,
                // 1.2.0-beta.fooblz or 1.2.0-beta bumps to 1.2.0-beta.0
                var prerelease = [identifier, base];
                if (identifierBase === false) {
                  prerelease = [identifier];
                }
                if (compareIdentifiers(this.prerelease[0], identifier) === 0) {
                  if (isNaN(this.prerelease[1])) {
                    this.prerelease = prerelease;
                  }
                } else {
                  this.prerelease = prerelease;
                }
              }
              break;
            }
          default:
            throw new Error("invalid increment argument: ".concat(release));
        }
        this.raw = this.format();
        if (this.build.length) {
          this.raw += "+".concat(this.build.join('.'));
        }
        return this;
      }
    };
    var semver = SemVer$2;

    var SemVer$1 = semver;
    var parse$4 = function parse(version, options) {
      var throwErrors = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
      if (version instanceof SemVer$1) {
        return version;
      }
      try {
        return new SemVer$1(version, options);
      } catch (er) {
        if (!throwErrors) {
          return null;
        }
        throw er;
      }
    };
    var parse_1 = parse$4;

    var parse$3 = parse_1;
    var valid = function valid(version, options) {
      var v = parse$3(version, options);
      return v ? v.version : null;
    };
    var valid_1 = valid;
    var valid$1 = /*@__PURE__*/getDefaultExportFromCjs$1(valid_1);

    var SemVer = semver;
    var parse$2 = parse_1;
    var re = reExports.safeRe,
      t = reExports.t;
    var coerce$1 = function coerce(version, options) {
      if (version instanceof SemVer) {
        return version;
      }
      if (typeof version === 'number') {
        version = String(version);
      }
      if (typeof version !== 'string') {
        return null;
      }
      options = options || {};
      var match = null;
      if (!options.rtl) {
        match = version.match(options.includePrerelease ? re[t.COERCEFULL] : re[t.COERCE]);
      } else {
        // Find the right-most coercible string that does not share
        // a terminus with a more left-ward coercible string.
        // Eg, '1.2.3.4' wants to coerce '2.3.4', not '3.4' or '4'
        // With includePrerelease option set, '1.2.3.4-rc' wants to coerce '2.3.4-rc', not '2.3.4'
        //
        // Walk through the string checking with a /g regexp
        // Manually set the index so as to pick up overlapping matches.
        // Stop when we get a match that ends at the string end, since no
        // coercible string can be more right-ward without the same terminus.
        var coerceRtlRegex = options.includePrerelease ? re[t.COERCERTLFULL] : re[t.COERCERTL];
        var next;
        while ((next = coerceRtlRegex.exec(version)) && (!match || match.index + match[0].length !== version.length)) {
          if (!match || next.index + next[0].length !== match.index + match[0].length) {
            match = next;
          }
          coerceRtlRegex.lastIndex = next.index + next[1].length + next[2].length;
        }
        // leave it in a clean state
        coerceRtlRegex.lastIndex = -1;
      }
      if (match === null) {
        return null;
      }
      var major = match[2];
      var minor = match[3] || '0';
      var patch = match[4] || '0';
      var prerelease = options.includePrerelease && match[5] ? "-".concat(match[5]) : '';
      var build = options.includePrerelease && match[6] ? "+".concat(match[6]) : '';
      return parse$2("".concat(major, ".").concat(minor, ".").concat(patch).concat(prerelease).concat(build), options);
    };
    var coerce_1 = coerce$1;
    var coerce$2 = /*@__PURE__*/getDefaultExportFromCjs$1(coerce_1);

    // This is a generated file. Do not edit.
    var Space_Separator = /[\u1680\u2000-\u200A\u202F\u205F\u3000]/;
    var ID_Start = /[\xAA\xB5\xBA\xC0-\xD6\xD8-\xF6\xF8-\u02C1\u02C6-\u02D1\u02E0-\u02E4\u02EC\u02EE\u0370-\u0374\u0376\u0377\u037A-\u037D\u037F\u0386\u0388-\u038A\u038C\u038E-\u03A1\u03A3-\u03F5\u03F7-\u0481\u048A-\u052F\u0531-\u0556\u0559\u0561-\u0587\u05D0-\u05EA\u05F0-\u05F2\u0620-\u064A\u066E\u066F\u0671-\u06D3\u06D5\u06E5\u06E6\u06EE\u06EF\u06FA-\u06FC\u06FF\u0710\u0712-\u072F\u074D-\u07A5\u07B1\u07CA-\u07EA\u07F4\u07F5\u07FA\u0800-\u0815\u081A\u0824\u0828\u0840-\u0858\u0860-\u086A\u08A0-\u08B4\u08B6-\u08BD\u0904-\u0939\u093D\u0950\u0958-\u0961\u0971-\u0980\u0985-\u098C\u098F\u0990\u0993-\u09A8\u09AA-\u09B0\u09B2\u09B6-\u09B9\u09BD\u09CE\u09DC\u09DD\u09DF-\u09E1\u09F0\u09F1\u09FC\u0A05-\u0A0A\u0A0F\u0A10\u0A13-\u0A28\u0A2A-\u0A30\u0A32\u0A33\u0A35\u0A36\u0A38\u0A39\u0A59-\u0A5C\u0A5E\u0A72-\u0A74\u0A85-\u0A8D\u0A8F-\u0A91\u0A93-\u0AA8\u0AAA-\u0AB0\u0AB2\u0AB3\u0AB5-\u0AB9\u0ABD\u0AD0\u0AE0\u0AE1\u0AF9\u0B05-\u0B0C\u0B0F\u0B10\u0B13-\u0B28\u0B2A-\u0B30\u0B32\u0B33\u0B35-\u0B39\u0B3D\u0B5C\u0B5D\u0B5F-\u0B61\u0B71\u0B83\u0B85-\u0B8A\u0B8E-\u0B90\u0B92-\u0B95\u0B99\u0B9A\u0B9C\u0B9E\u0B9F\u0BA3\u0BA4\u0BA8-\u0BAA\u0BAE-\u0BB9\u0BD0\u0C05-\u0C0C\u0C0E-\u0C10\u0C12-\u0C28\u0C2A-\u0C39\u0C3D\u0C58-\u0C5A\u0C60\u0C61\u0C80\u0C85-\u0C8C\u0C8E-\u0C90\u0C92-\u0CA8\u0CAA-\u0CB3\u0CB5-\u0CB9\u0CBD\u0CDE\u0CE0\u0CE1\u0CF1\u0CF2\u0D05-\u0D0C\u0D0E-\u0D10\u0D12-\u0D3A\u0D3D\u0D4E\u0D54-\u0D56\u0D5F-\u0D61\u0D7A-\u0D7F\u0D85-\u0D96\u0D9A-\u0DB1\u0DB3-\u0DBB\u0DBD\u0DC0-\u0DC6\u0E01-\u0E30\u0E32\u0E33\u0E40-\u0E46\u0E81\u0E82\u0E84\u0E87\u0E88\u0E8A\u0E8D\u0E94-\u0E97\u0E99-\u0E9F\u0EA1-\u0EA3\u0EA5\u0EA7\u0EAA\u0EAB\u0EAD-\u0EB0\u0EB2\u0EB3\u0EBD\u0EC0-\u0EC4\u0EC6\u0EDC-\u0EDF\u0F00\u0F40-\u0F47\u0F49-\u0F6C\u0F88-\u0F8C\u1000-\u102A\u103F\u1050-\u1055\u105A-\u105D\u1061\u1065\u1066\u106E-\u1070\u1075-\u1081\u108E\u10A0-\u10C5\u10C7\u10CD\u10D0-\u10FA\u10FC-\u1248\u124A-\u124D\u1250-\u1256\u1258\u125A-\u125D\u1260-\u1288\u128A-\u128D\u1290-\u12B0\u12B2-\u12B5\u12B8-\u12BE\u12C0\u12C2-\u12C5\u12C8-\u12D6\u12D8-\u1310\u1312-\u1315\u1318-\u135A\u1380-\u138F\u13A0-\u13F5\u13F8-\u13FD\u1401-\u166C\u166F-\u167F\u1681-\u169A\u16A0-\u16EA\u16EE-\u16F8\u1700-\u170C\u170E-\u1711\u1720-\u1731\u1740-\u1751\u1760-\u176C\u176E-\u1770\u1780-\u17B3\u17D7\u17DC\u1820-\u1877\u1880-\u1884\u1887-\u18A8\u18AA\u18B0-\u18F5\u1900-\u191E\u1950-\u196D\u1970-\u1974\u1980-\u19AB\u19B0-\u19C9\u1A00-\u1A16\u1A20-\u1A54\u1AA7\u1B05-\u1B33\u1B45-\u1B4B\u1B83-\u1BA0\u1BAE\u1BAF\u1BBA-\u1BE5\u1C00-\u1C23\u1C4D-\u1C4F\u1C5A-\u1C7D\u1C80-\u1C88\u1CE9-\u1CEC\u1CEE-\u1CF1\u1CF5\u1CF6\u1D00-\u1DBF\u1E00-\u1F15\u1F18-\u1F1D\u1F20-\u1F45\u1F48-\u1F4D\u1F50-\u1F57\u1F59\u1F5B\u1F5D\u1F5F-\u1F7D\u1F80-\u1FB4\u1FB6-\u1FBC\u1FBE\u1FC2-\u1FC4\u1FC6-\u1FCC\u1FD0-\u1FD3\u1FD6-\u1FDB\u1FE0-\u1FEC\u1FF2-\u1FF4\u1FF6-\u1FFC\u2071\u207F\u2090-\u209C\u2102\u2107\u210A-\u2113\u2115\u2119-\u211D\u2124\u2126\u2128\u212A-\u212D\u212F-\u2139\u213C-\u213F\u2145-\u2149\u214E\u2160-\u2188\u2C00-\u2C2E\u2C30-\u2C5E\u2C60-\u2CE4\u2CEB-\u2CEE\u2CF2\u2CF3\u2D00-\u2D25\u2D27\u2D2D\u2D30-\u2D67\u2D6F\u2D80-\u2D96\u2DA0-\u2DA6\u2DA8-\u2DAE\u2DB0-\u2DB6\u2DB8-\u2DBE\u2DC0-\u2DC6\u2DC8-\u2DCE\u2DD0-\u2DD6\u2DD8-\u2DDE\u2E2F\u3005-\u3007\u3021-\u3029\u3031-\u3035\u3038-\u303C\u3041-\u3096\u309D-\u309F\u30A1-\u30FA\u30FC-\u30FF\u3105-\u312E\u3131-\u318E\u31A0-\u31BA\u31F0-\u31FF\u3400-\u4DB5\u4E00-\u9FEA\uA000-\uA48C\uA4D0-\uA4FD\uA500-\uA60C\uA610-\uA61F\uA62A\uA62B\uA640-\uA66E\uA67F-\uA69D\uA6A0-\uA6EF\uA717-\uA71F\uA722-\uA788\uA78B-\uA7AE\uA7B0-\uA7B7\uA7F7-\uA801\uA803-\uA805\uA807-\uA80A\uA80C-\uA822\uA840-\uA873\uA882-\uA8B3\uA8F2-\uA8F7\uA8FB\uA8FD\uA90A-\uA925\uA930-\uA946\uA960-\uA97C\uA984-\uA9B2\uA9CF\uA9E0-\uA9E4\uA9E6-\uA9EF\uA9FA-\uA9FE\uAA00-\uAA28\uAA40-\uAA42\uAA44-\uAA4B\uAA60-\uAA76\uAA7A\uAA7E-\uAAAF\uAAB1\uAAB5\uAAB6\uAAB9-\uAABD\uAAC0\uAAC2\uAADB-\uAADD\uAAE0-\uAAEA\uAAF2-\uAAF4\uAB01-\uAB06\uAB09-\uAB0E\uAB11-\uAB16\uAB20-\uAB26\uAB28-\uAB2E\uAB30-\uAB5A\uAB5C-\uAB65\uAB70-\uABE2\uAC00-\uD7A3\uD7B0-\uD7C6\uD7CB-\uD7FB\uF900-\uFA6D\uFA70-\uFAD9\uFB00-\uFB06\uFB13-\uFB17\uFB1D\uFB1F-\uFB28\uFB2A-\uFB36\uFB38-\uFB3C\uFB3E\uFB40\uFB41\uFB43\uFB44\uFB46-\uFBB1\uFBD3-\uFD3D\uFD50-\uFD8F\uFD92-\uFDC7\uFDF0-\uFDFB\uFE70-\uFE74\uFE76-\uFEFC\uFF21-\uFF3A\uFF41-\uFF5A\uFF66-\uFFBE\uFFC2-\uFFC7\uFFCA-\uFFCF\uFFD2-\uFFD7\uFFDA-\uFFDC]|\uD800[\uDC00-\uDC0B\uDC0D-\uDC26\uDC28-\uDC3A\uDC3C\uDC3D\uDC3F-\uDC4D\uDC50-\uDC5D\uDC80-\uDCFA\uDD40-\uDD74\uDE80-\uDE9C\uDEA0-\uDED0\uDF00-\uDF1F\uDF2D-\uDF4A\uDF50-\uDF75\uDF80-\uDF9D\uDFA0-\uDFC3\uDFC8-\uDFCF\uDFD1-\uDFD5]|\uD801[\uDC00-\uDC9D\uDCB0-\uDCD3\uDCD8-\uDCFB\uDD00-\uDD27\uDD30-\uDD63\uDE00-\uDF36\uDF40-\uDF55\uDF60-\uDF67]|\uD802[\uDC00-\uDC05\uDC08\uDC0A-\uDC35\uDC37\uDC38\uDC3C\uDC3F-\uDC55\uDC60-\uDC76\uDC80-\uDC9E\uDCE0-\uDCF2\uDCF4\uDCF5\uDD00-\uDD15\uDD20-\uDD39\uDD80-\uDDB7\uDDBE\uDDBF\uDE00\uDE10-\uDE13\uDE15-\uDE17\uDE19-\uDE33\uDE60-\uDE7C\uDE80-\uDE9C\uDEC0-\uDEC7\uDEC9-\uDEE4\uDF00-\uDF35\uDF40-\uDF55\uDF60-\uDF72\uDF80-\uDF91]|\uD803[\uDC00-\uDC48\uDC80-\uDCB2\uDCC0-\uDCF2]|\uD804[\uDC03-\uDC37\uDC83-\uDCAF\uDCD0-\uDCE8\uDD03-\uDD26\uDD50-\uDD72\uDD76\uDD83-\uDDB2\uDDC1-\uDDC4\uDDDA\uDDDC\uDE00-\uDE11\uDE13-\uDE2B\uDE80-\uDE86\uDE88\uDE8A-\uDE8D\uDE8F-\uDE9D\uDE9F-\uDEA8\uDEB0-\uDEDE\uDF05-\uDF0C\uDF0F\uDF10\uDF13-\uDF28\uDF2A-\uDF30\uDF32\uDF33\uDF35-\uDF39\uDF3D\uDF50\uDF5D-\uDF61]|\uD805[\uDC00-\uDC34\uDC47-\uDC4A\uDC80-\uDCAF\uDCC4\uDCC5\uDCC7\uDD80-\uDDAE\uDDD8-\uDDDB\uDE00-\uDE2F\uDE44\uDE80-\uDEAA\uDF00-\uDF19]|\uD806[\uDCA0-\uDCDF\uDCFF\uDE00\uDE0B-\uDE32\uDE3A\uDE50\uDE5C-\uDE83\uDE86-\uDE89\uDEC0-\uDEF8]|\uD807[\uDC00-\uDC08\uDC0A-\uDC2E\uDC40\uDC72-\uDC8F\uDD00-\uDD06\uDD08\uDD09\uDD0B-\uDD30\uDD46]|\uD808[\uDC00-\uDF99]|\uD809[\uDC00-\uDC6E\uDC80-\uDD43]|[\uD80C\uD81C-\uD820\uD840-\uD868\uD86A-\uD86C\uD86F-\uD872\uD874-\uD879][\uDC00-\uDFFF]|\uD80D[\uDC00-\uDC2E]|\uD811[\uDC00-\uDE46]|\uD81A[\uDC00-\uDE38\uDE40-\uDE5E\uDED0-\uDEED\uDF00-\uDF2F\uDF40-\uDF43\uDF63-\uDF77\uDF7D-\uDF8F]|\uD81B[\uDF00-\uDF44\uDF50\uDF93-\uDF9F\uDFE0\uDFE1]|\uD821[\uDC00-\uDFEC]|\uD822[\uDC00-\uDEF2]|\uD82C[\uDC00-\uDD1E\uDD70-\uDEFB]|\uD82F[\uDC00-\uDC6A\uDC70-\uDC7C\uDC80-\uDC88\uDC90-\uDC99]|\uD835[\uDC00-\uDC54\uDC56-\uDC9C\uDC9E\uDC9F\uDCA2\uDCA5\uDCA6\uDCA9-\uDCAC\uDCAE-\uDCB9\uDCBB\uDCBD-\uDCC3\uDCC5-\uDD05\uDD07-\uDD0A\uDD0D-\uDD14\uDD16-\uDD1C\uDD1E-\uDD39\uDD3B-\uDD3E\uDD40-\uDD44\uDD46\uDD4A-\uDD50\uDD52-\uDEA5\uDEA8-\uDEC0\uDEC2-\uDEDA\uDEDC-\uDEFA\uDEFC-\uDF14\uDF16-\uDF34\uDF36-\uDF4E\uDF50-\uDF6E\uDF70-\uDF88\uDF8A-\uDFA8\uDFAA-\uDFC2\uDFC4-\uDFCB]|\uD83A[\uDC00-\uDCC4\uDD00-\uDD43]|\uD83B[\uDE00-\uDE03\uDE05-\uDE1F\uDE21\uDE22\uDE24\uDE27\uDE29-\uDE32\uDE34-\uDE37\uDE39\uDE3B\uDE42\uDE47\uDE49\uDE4B\uDE4D-\uDE4F\uDE51\uDE52\uDE54\uDE57\uDE59\uDE5B\uDE5D\uDE5F\uDE61\uDE62\uDE64\uDE67-\uDE6A\uDE6C-\uDE72\uDE74-\uDE77\uDE79-\uDE7C\uDE7E\uDE80-\uDE89\uDE8B-\uDE9B\uDEA1-\uDEA3\uDEA5-\uDEA9\uDEAB-\uDEBB]|\uD869[\uDC00-\uDED6\uDF00-\uDFFF]|\uD86D[\uDC00-\uDF34\uDF40-\uDFFF]|\uD86E[\uDC00-\uDC1D\uDC20-\uDFFF]|\uD873[\uDC00-\uDEA1\uDEB0-\uDFFF]|\uD87A[\uDC00-\uDFE0]|\uD87E[\uDC00-\uDE1D]/;
    var ID_Continue = /[\xAA\xB5\xBA\xC0-\xD6\xD8-\xF6\xF8-\u02C1\u02C6-\u02D1\u02E0-\u02E4\u02EC\u02EE\u0300-\u0374\u0376\u0377\u037A-\u037D\u037F\u0386\u0388-\u038A\u038C\u038E-\u03A1\u03A3-\u03F5\u03F7-\u0481\u0483-\u0487\u048A-\u052F\u0531-\u0556\u0559\u0561-\u0587\u0591-\u05BD\u05BF\u05C1\u05C2\u05C4\u05C5\u05C7\u05D0-\u05EA\u05F0-\u05F2\u0610-\u061A\u0620-\u0669\u066E-\u06D3\u06D5-\u06DC\u06DF-\u06E8\u06EA-\u06FC\u06FF\u0710-\u074A\u074D-\u07B1\u07C0-\u07F5\u07FA\u0800-\u082D\u0840-\u085B\u0860-\u086A\u08A0-\u08B4\u08B6-\u08BD\u08D4-\u08E1\u08E3-\u0963\u0966-\u096F\u0971-\u0983\u0985-\u098C\u098F\u0990\u0993-\u09A8\u09AA-\u09B0\u09B2\u09B6-\u09B9\u09BC-\u09C4\u09C7\u09C8\u09CB-\u09CE\u09D7\u09DC\u09DD\u09DF-\u09E3\u09E6-\u09F1\u09FC\u0A01-\u0A03\u0A05-\u0A0A\u0A0F\u0A10\u0A13-\u0A28\u0A2A-\u0A30\u0A32\u0A33\u0A35\u0A36\u0A38\u0A39\u0A3C\u0A3E-\u0A42\u0A47\u0A48\u0A4B-\u0A4D\u0A51\u0A59-\u0A5C\u0A5E\u0A66-\u0A75\u0A81-\u0A83\u0A85-\u0A8D\u0A8F-\u0A91\u0A93-\u0AA8\u0AAA-\u0AB0\u0AB2\u0AB3\u0AB5-\u0AB9\u0ABC-\u0AC5\u0AC7-\u0AC9\u0ACB-\u0ACD\u0AD0\u0AE0-\u0AE3\u0AE6-\u0AEF\u0AF9-\u0AFF\u0B01-\u0B03\u0B05-\u0B0C\u0B0F\u0B10\u0B13-\u0B28\u0B2A-\u0B30\u0B32\u0B33\u0B35-\u0B39\u0B3C-\u0B44\u0B47\u0B48\u0B4B-\u0B4D\u0B56\u0B57\u0B5C\u0B5D\u0B5F-\u0B63\u0B66-\u0B6F\u0B71\u0B82\u0B83\u0B85-\u0B8A\u0B8E-\u0B90\u0B92-\u0B95\u0B99\u0B9A\u0B9C\u0B9E\u0B9F\u0BA3\u0BA4\u0BA8-\u0BAA\u0BAE-\u0BB9\u0BBE-\u0BC2\u0BC6-\u0BC8\u0BCA-\u0BCD\u0BD0\u0BD7\u0BE6-\u0BEF\u0C00-\u0C03\u0C05-\u0C0C\u0C0E-\u0C10\u0C12-\u0C28\u0C2A-\u0C39\u0C3D-\u0C44\u0C46-\u0C48\u0C4A-\u0C4D\u0C55\u0C56\u0C58-\u0C5A\u0C60-\u0C63\u0C66-\u0C6F\u0C80-\u0C83\u0C85-\u0C8C\u0C8E-\u0C90\u0C92-\u0CA8\u0CAA-\u0CB3\u0CB5-\u0CB9\u0CBC-\u0CC4\u0CC6-\u0CC8\u0CCA-\u0CCD\u0CD5\u0CD6\u0CDE\u0CE0-\u0CE3\u0CE6-\u0CEF\u0CF1\u0CF2\u0D00-\u0D03\u0D05-\u0D0C\u0D0E-\u0D10\u0D12-\u0D44\u0D46-\u0D48\u0D4A-\u0D4E\u0D54-\u0D57\u0D5F-\u0D63\u0D66-\u0D6F\u0D7A-\u0D7F\u0D82\u0D83\u0D85-\u0D96\u0D9A-\u0DB1\u0DB3-\u0DBB\u0DBD\u0DC0-\u0DC6\u0DCA\u0DCF-\u0DD4\u0DD6\u0DD8-\u0DDF\u0DE6-\u0DEF\u0DF2\u0DF3\u0E01-\u0E3A\u0E40-\u0E4E\u0E50-\u0E59\u0E81\u0E82\u0E84\u0E87\u0E88\u0E8A\u0E8D\u0E94-\u0E97\u0E99-\u0E9F\u0EA1-\u0EA3\u0EA5\u0EA7\u0EAA\u0EAB\u0EAD-\u0EB9\u0EBB-\u0EBD\u0EC0-\u0EC4\u0EC6\u0EC8-\u0ECD\u0ED0-\u0ED9\u0EDC-\u0EDF\u0F00\u0F18\u0F19\u0F20-\u0F29\u0F35\u0F37\u0F39\u0F3E-\u0F47\u0F49-\u0F6C\u0F71-\u0F84\u0F86-\u0F97\u0F99-\u0FBC\u0FC6\u1000-\u1049\u1050-\u109D\u10A0-\u10C5\u10C7\u10CD\u10D0-\u10FA\u10FC-\u1248\u124A-\u124D\u1250-\u1256\u1258\u125A-\u125D\u1260-\u1288\u128A-\u128D\u1290-\u12B0\u12B2-\u12B5\u12B8-\u12BE\u12C0\u12C2-\u12C5\u12C8-\u12D6\u12D8-\u1310\u1312-\u1315\u1318-\u135A\u135D-\u135F\u1380-\u138F\u13A0-\u13F5\u13F8-\u13FD\u1401-\u166C\u166F-\u167F\u1681-\u169A\u16A0-\u16EA\u16EE-\u16F8\u1700-\u170C\u170E-\u1714\u1720-\u1734\u1740-\u1753\u1760-\u176C\u176E-\u1770\u1772\u1773\u1780-\u17D3\u17D7\u17DC\u17DD\u17E0-\u17E9\u180B-\u180D\u1810-\u1819\u1820-\u1877\u1880-\u18AA\u18B0-\u18F5\u1900-\u191E\u1920-\u192B\u1930-\u193B\u1946-\u196D\u1970-\u1974\u1980-\u19AB\u19B0-\u19C9\u19D0-\u19D9\u1A00-\u1A1B\u1A20-\u1A5E\u1A60-\u1A7C\u1A7F-\u1A89\u1A90-\u1A99\u1AA7\u1AB0-\u1ABD\u1B00-\u1B4B\u1B50-\u1B59\u1B6B-\u1B73\u1B80-\u1BF3\u1C00-\u1C37\u1C40-\u1C49\u1C4D-\u1C7D\u1C80-\u1C88\u1CD0-\u1CD2\u1CD4-\u1CF9\u1D00-\u1DF9\u1DFB-\u1F15\u1F18-\u1F1D\u1F20-\u1F45\u1F48-\u1F4D\u1F50-\u1F57\u1F59\u1F5B\u1F5D\u1F5F-\u1F7D\u1F80-\u1FB4\u1FB6-\u1FBC\u1FBE\u1FC2-\u1FC4\u1FC6-\u1FCC\u1FD0-\u1FD3\u1FD6-\u1FDB\u1FE0-\u1FEC\u1FF2-\u1FF4\u1FF6-\u1FFC\u203F\u2040\u2054\u2071\u207F\u2090-\u209C\u20D0-\u20DC\u20E1\u20E5-\u20F0\u2102\u2107\u210A-\u2113\u2115\u2119-\u211D\u2124\u2126\u2128\u212A-\u212D\u212F-\u2139\u213C-\u213F\u2145-\u2149\u214E\u2160-\u2188\u2C00-\u2C2E\u2C30-\u2C5E\u2C60-\u2CE4\u2CEB-\u2CF3\u2D00-\u2D25\u2D27\u2D2D\u2D30-\u2D67\u2D6F\u2D7F-\u2D96\u2DA0-\u2DA6\u2DA8-\u2DAE\u2DB0-\u2DB6\u2DB8-\u2DBE\u2DC0-\u2DC6\u2DC8-\u2DCE\u2DD0-\u2DD6\u2DD8-\u2DDE\u2DE0-\u2DFF\u2E2F\u3005-\u3007\u3021-\u302F\u3031-\u3035\u3038-\u303C\u3041-\u3096\u3099\u309A\u309D-\u309F\u30A1-\u30FA\u30FC-\u30FF\u3105-\u312E\u3131-\u318E\u31A0-\u31BA\u31F0-\u31FF\u3400-\u4DB5\u4E00-\u9FEA\uA000-\uA48C\uA4D0-\uA4FD\uA500-\uA60C\uA610-\uA62B\uA640-\uA66F\uA674-\uA67D\uA67F-\uA6F1\uA717-\uA71F\uA722-\uA788\uA78B-\uA7AE\uA7B0-\uA7B7\uA7F7-\uA827\uA840-\uA873\uA880-\uA8C5\uA8D0-\uA8D9\uA8E0-\uA8F7\uA8FB\uA8FD\uA900-\uA92D\uA930-\uA953\uA960-\uA97C\uA980-\uA9C0\uA9CF-\uA9D9\uA9E0-\uA9FE\uAA00-\uAA36\uAA40-\uAA4D\uAA50-\uAA59\uAA60-\uAA76\uAA7A-\uAAC2\uAADB-\uAADD\uAAE0-\uAAEF\uAAF2-\uAAF6\uAB01-\uAB06\uAB09-\uAB0E\uAB11-\uAB16\uAB20-\uAB26\uAB28-\uAB2E\uAB30-\uAB5A\uAB5C-\uAB65\uAB70-\uABEA\uABEC\uABED\uABF0-\uABF9\uAC00-\uD7A3\uD7B0-\uD7C6\uD7CB-\uD7FB\uF900-\uFA6D\uFA70-\uFAD9\uFB00-\uFB06\uFB13-\uFB17\uFB1D-\uFB28\uFB2A-\uFB36\uFB38-\uFB3C\uFB3E\uFB40\uFB41\uFB43\uFB44\uFB46-\uFBB1\uFBD3-\uFD3D\uFD50-\uFD8F\uFD92-\uFDC7\uFDF0-\uFDFB\uFE00-\uFE0F\uFE20-\uFE2F\uFE33\uFE34\uFE4D-\uFE4F\uFE70-\uFE74\uFE76-\uFEFC\uFF10-\uFF19\uFF21-\uFF3A\uFF3F\uFF41-\uFF5A\uFF66-\uFFBE\uFFC2-\uFFC7\uFFCA-\uFFCF\uFFD2-\uFFD7\uFFDA-\uFFDC]|\uD800[\uDC00-\uDC0B\uDC0D-\uDC26\uDC28-\uDC3A\uDC3C\uDC3D\uDC3F-\uDC4D\uDC50-\uDC5D\uDC80-\uDCFA\uDD40-\uDD74\uDDFD\uDE80-\uDE9C\uDEA0-\uDED0\uDEE0\uDF00-\uDF1F\uDF2D-\uDF4A\uDF50-\uDF7A\uDF80-\uDF9D\uDFA0-\uDFC3\uDFC8-\uDFCF\uDFD1-\uDFD5]|\uD801[\uDC00-\uDC9D\uDCA0-\uDCA9\uDCB0-\uDCD3\uDCD8-\uDCFB\uDD00-\uDD27\uDD30-\uDD63\uDE00-\uDF36\uDF40-\uDF55\uDF60-\uDF67]|\uD802[\uDC00-\uDC05\uDC08\uDC0A-\uDC35\uDC37\uDC38\uDC3C\uDC3F-\uDC55\uDC60-\uDC76\uDC80-\uDC9E\uDCE0-\uDCF2\uDCF4\uDCF5\uDD00-\uDD15\uDD20-\uDD39\uDD80-\uDDB7\uDDBE\uDDBF\uDE00-\uDE03\uDE05\uDE06\uDE0C-\uDE13\uDE15-\uDE17\uDE19-\uDE33\uDE38-\uDE3A\uDE3F\uDE60-\uDE7C\uDE80-\uDE9C\uDEC0-\uDEC7\uDEC9-\uDEE6\uDF00-\uDF35\uDF40-\uDF55\uDF60-\uDF72\uDF80-\uDF91]|\uD803[\uDC00-\uDC48\uDC80-\uDCB2\uDCC0-\uDCF2]|\uD804[\uDC00-\uDC46\uDC66-\uDC6F\uDC7F-\uDCBA\uDCD0-\uDCE8\uDCF0-\uDCF9\uDD00-\uDD34\uDD36-\uDD3F\uDD50-\uDD73\uDD76\uDD80-\uDDC4\uDDCA-\uDDCC\uDDD0-\uDDDA\uDDDC\uDE00-\uDE11\uDE13-\uDE37\uDE3E\uDE80-\uDE86\uDE88\uDE8A-\uDE8D\uDE8F-\uDE9D\uDE9F-\uDEA8\uDEB0-\uDEEA\uDEF0-\uDEF9\uDF00-\uDF03\uDF05-\uDF0C\uDF0F\uDF10\uDF13-\uDF28\uDF2A-\uDF30\uDF32\uDF33\uDF35-\uDF39\uDF3C-\uDF44\uDF47\uDF48\uDF4B-\uDF4D\uDF50\uDF57\uDF5D-\uDF63\uDF66-\uDF6C\uDF70-\uDF74]|\uD805[\uDC00-\uDC4A\uDC50-\uDC59\uDC80-\uDCC5\uDCC7\uDCD0-\uDCD9\uDD80-\uDDB5\uDDB8-\uDDC0\uDDD8-\uDDDD\uDE00-\uDE40\uDE44\uDE50-\uDE59\uDE80-\uDEB7\uDEC0-\uDEC9\uDF00-\uDF19\uDF1D-\uDF2B\uDF30-\uDF39]|\uD806[\uDCA0-\uDCE9\uDCFF\uDE00-\uDE3E\uDE47\uDE50-\uDE83\uDE86-\uDE99\uDEC0-\uDEF8]|\uD807[\uDC00-\uDC08\uDC0A-\uDC36\uDC38-\uDC40\uDC50-\uDC59\uDC72-\uDC8F\uDC92-\uDCA7\uDCA9-\uDCB6\uDD00-\uDD06\uDD08\uDD09\uDD0B-\uDD36\uDD3A\uDD3C\uDD3D\uDD3F-\uDD47\uDD50-\uDD59]|\uD808[\uDC00-\uDF99]|\uD809[\uDC00-\uDC6E\uDC80-\uDD43]|[\uD80C\uD81C-\uD820\uD840-\uD868\uD86A-\uD86C\uD86F-\uD872\uD874-\uD879][\uDC00-\uDFFF]|\uD80D[\uDC00-\uDC2E]|\uD811[\uDC00-\uDE46]|\uD81A[\uDC00-\uDE38\uDE40-\uDE5E\uDE60-\uDE69\uDED0-\uDEED\uDEF0-\uDEF4\uDF00-\uDF36\uDF40-\uDF43\uDF50-\uDF59\uDF63-\uDF77\uDF7D-\uDF8F]|\uD81B[\uDF00-\uDF44\uDF50-\uDF7E\uDF8F-\uDF9F\uDFE0\uDFE1]|\uD821[\uDC00-\uDFEC]|\uD822[\uDC00-\uDEF2]|\uD82C[\uDC00-\uDD1E\uDD70-\uDEFB]|\uD82F[\uDC00-\uDC6A\uDC70-\uDC7C\uDC80-\uDC88\uDC90-\uDC99\uDC9D\uDC9E]|\uD834[\uDD65-\uDD69\uDD6D-\uDD72\uDD7B-\uDD82\uDD85-\uDD8B\uDDAA-\uDDAD\uDE42-\uDE44]|\uD835[\uDC00-\uDC54\uDC56-\uDC9C\uDC9E\uDC9F\uDCA2\uDCA5\uDCA6\uDCA9-\uDCAC\uDCAE-\uDCB9\uDCBB\uDCBD-\uDCC3\uDCC5-\uDD05\uDD07-\uDD0A\uDD0D-\uDD14\uDD16-\uDD1C\uDD1E-\uDD39\uDD3B-\uDD3E\uDD40-\uDD44\uDD46\uDD4A-\uDD50\uDD52-\uDEA5\uDEA8-\uDEC0\uDEC2-\uDEDA\uDEDC-\uDEFA\uDEFC-\uDF14\uDF16-\uDF34\uDF36-\uDF4E\uDF50-\uDF6E\uDF70-\uDF88\uDF8A-\uDFA8\uDFAA-\uDFC2\uDFC4-\uDFCB\uDFCE-\uDFFF]|\uD836[\uDE00-\uDE36\uDE3B-\uDE6C\uDE75\uDE84\uDE9B-\uDE9F\uDEA1-\uDEAF]|\uD838[\uDC00-\uDC06\uDC08-\uDC18\uDC1B-\uDC21\uDC23\uDC24\uDC26-\uDC2A]|\uD83A[\uDC00-\uDCC4\uDCD0-\uDCD6\uDD00-\uDD4A\uDD50-\uDD59]|\uD83B[\uDE00-\uDE03\uDE05-\uDE1F\uDE21\uDE22\uDE24\uDE27\uDE29-\uDE32\uDE34-\uDE37\uDE39\uDE3B\uDE42\uDE47\uDE49\uDE4B\uDE4D-\uDE4F\uDE51\uDE52\uDE54\uDE57\uDE59\uDE5B\uDE5D\uDE5F\uDE61\uDE62\uDE64\uDE67-\uDE6A\uDE6C-\uDE72\uDE74-\uDE77\uDE79-\uDE7C\uDE7E\uDE80-\uDE89\uDE8B-\uDE9B\uDEA1-\uDEA3\uDEA5-\uDEA9\uDEAB-\uDEBB]|\uD869[\uDC00-\uDED6\uDF00-\uDFFF]|\uD86D[\uDC00-\uDF34\uDF40-\uDFFF]|\uD86E[\uDC00-\uDC1D\uDC20-\uDFFF]|\uD873[\uDC00-\uDEA1\uDEB0-\uDFFF]|\uD87A[\uDC00-\uDFE0]|\uD87E[\uDC00-\uDE1D]|\uDB40[\uDD00-\uDDEF]/;

    var unicode = {
    	Space_Separator: Space_Separator,
    	ID_Start: ID_Start,
    	ID_Continue: ID_Continue
    };

    var util$1 = {
        isSpaceSeparator (c) {
            return typeof c === 'string' && unicode.Space_Separator.test(c)
        },

        isIdStartChar (c) {
            return typeof c === 'string' && (
                (c >= 'a' && c <= 'z') ||
            (c >= 'A' && c <= 'Z') ||
            (c === '$') || (c === '_') ||
            unicode.ID_Start.test(c)
            )
        },

        isIdContinueChar (c) {
            return typeof c === 'string' && (
                (c >= 'a' && c <= 'z') ||
            (c >= 'A' && c <= 'Z') ||
            (c >= '0' && c <= '9') ||
            (c === '$') || (c === '_') ||
            (c === '\u200C') || (c === '\u200D') ||
            unicode.ID_Continue.test(c)
            )
        },

        isDigit (c) {
            return typeof c === 'string' && /[0-9]/.test(c)
        },

        isHexDigit (c) {
            return typeof c === 'string' && /[0-9A-Fa-f]/.test(c)
        },
    };

    let source;
    let parseState;
    let stack;
    let pos;
    let line;
    let column;
    let token;
    let key;
    let root;

    var parse$1 = function parse (text, reviver) {
        source = String(text);
        parseState = 'start';
        stack = [];
        pos = 0;
        line = 1;
        column = 0;
        token = undefined;
        key = undefined;
        root = undefined;

        do {
            token = lex();

            // This code is unreachable.
            // if (!parseStates[parseState]) {
            //     throw invalidParseState()
            // }

            parseStates[parseState]();
        } while (token.type !== 'eof')

        if (typeof reviver === 'function') {
            return internalize({'': root}, '', reviver)
        }

        return root
    };

    function internalize (holder, name, reviver) {
        const value = holder[name];
        if (value != null && typeof value === 'object') {
            if (Array.isArray(value)) {
                for (let i = 0; i < value.length; i++) {
                    const key = String(i);
                    const replacement = internalize(value, key, reviver);
                    if (replacement === undefined) {
                        delete value[key];
                    } else {
                        Object.defineProperty(value, key, {
                            value: replacement,
                            writable: true,
                            enumerable: true,
                            configurable: true,
                        });
                    }
                }
            } else {
                for (const key in value) {
                    const replacement = internalize(value, key, reviver);
                    if (replacement === undefined) {
                        delete value[key];
                    } else {
                        Object.defineProperty(value, key, {
                            value: replacement,
                            writable: true,
                            enumerable: true,
                            configurable: true,
                        });
                    }
                }
            }
        }

        return reviver.call(holder, name, value)
    }

    let lexState;
    let buffer;
    let doubleQuote;
    let sign;
    let c;

    function lex () {
        lexState = 'default';
        buffer = '';
        doubleQuote = false;
        sign = 1;

        for (;;) {
            c = peek();

            // This code is unreachable.
            // if (!lexStates[lexState]) {
            //     throw invalidLexState(lexState)
            // }

            const token = lexStates[lexState]();
            if (token) {
                return token
            }
        }
    }

    function peek () {
        if (source[pos]) {
            return String.fromCodePoint(source.codePointAt(pos))
        }
    }

    function read () {
        const c = peek();

        if (c === '\n') {
            line++;
            column = 0;
        } else if (c) {
            column += c.length;
        } else {
            column++;
        }

        if (c) {
            pos += c.length;
        }

        return c
    }

    const lexStates = {
        default () {
            switch (c) {
            case '\t':
            case '\v':
            case '\f':
            case ' ':
            case '\u00A0':
            case '\uFEFF':
            case '\n':
            case '\r':
            case '\u2028':
            case '\u2029':
                read();
                return

            case '/':
                read();
                lexState = 'comment';
                return

            case undefined:
                read();
                return newToken('eof')
            }

            if (util$1.isSpaceSeparator(c)) {
                read();
                return
            }

            // This code is unreachable.
            // if (!lexStates[parseState]) {
            //     throw invalidLexState(parseState)
            // }

            return lexStates[parseState]()
        },

        comment () {
            switch (c) {
            case '*':
                read();
                lexState = 'multiLineComment';
                return

            case '/':
                read();
                lexState = 'singleLineComment';
                return
            }

            throw invalidChar(read())
        },

        multiLineComment () {
            switch (c) {
            case '*':
                read();
                lexState = 'multiLineCommentAsterisk';
                return

            case undefined:
                throw invalidChar(read())
            }

            read();
        },

        multiLineCommentAsterisk () {
            switch (c) {
            case '*':
                read();
                return

            case '/':
                read();
                lexState = 'default';
                return

            case undefined:
                throw invalidChar(read())
            }

            read();
            lexState = 'multiLineComment';
        },

        singleLineComment () {
            switch (c) {
            case '\n':
            case '\r':
            case '\u2028':
            case '\u2029':
                read();
                lexState = 'default';
                return

            case undefined:
                read();
                return newToken('eof')
            }

            read();
        },

        value () {
            switch (c) {
            case '{':
            case '[':
                return newToken('punctuator', read())

            case 'n':
                read();
                literal('ull');
                return newToken('null', null)

            case 't':
                read();
                literal('rue');
                return newToken('boolean', true)

            case 'f':
                read();
                literal('alse');
                return newToken('boolean', false)

            case '-':
            case '+':
                if (read() === '-') {
                    sign = -1;
                }

                lexState = 'sign';
                return

            case '.':
                buffer = read();
                lexState = 'decimalPointLeading';
                return

            case '0':
                buffer = read();
                lexState = 'zero';
                return

            case '1':
            case '2':
            case '3':
            case '4':
            case '5':
            case '6':
            case '7':
            case '8':
            case '9':
                buffer = read();
                lexState = 'decimalInteger';
                return

            case 'I':
                read();
                literal('nfinity');
                return newToken('numeric', Infinity)

            case 'N':
                read();
                literal('aN');
                return newToken('numeric', NaN)

            case '"':
            case "'":
                doubleQuote = (read() === '"');
                buffer = '';
                lexState = 'string';
                return
            }

            throw invalidChar(read())
        },

        identifierNameStartEscape () {
            if (c !== 'u') {
                throw invalidChar(read())
            }

            read();
            const u = unicodeEscape();
            switch (u) {
            case '$':
            case '_':
                break

            default:
                if (!util$1.isIdStartChar(u)) {
                    throw invalidIdentifier()
                }

                break
            }

            buffer += u;
            lexState = 'identifierName';
        },

        identifierName () {
            switch (c) {
            case '$':
            case '_':
            case '\u200C':
            case '\u200D':
                buffer += read();
                return

            case '\\':
                read();
                lexState = 'identifierNameEscape';
                return
            }

            if (util$1.isIdContinueChar(c)) {
                buffer += read();
                return
            }

            return newToken('identifier', buffer)
        },

        identifierNameEscape () {
            if (c !== 'u') {
                throw invalidChar(read())
            }

            read();
            const u = unicodeEscape();
            switch (u) {
            case '$':
            case '_':
            case '\u200C':
            case '\u200D':
                break

            default:
                if (!util$1.isIdContinueChar(u)) {
                    throw invalidIdentifier()
                }

                break
            }

            buffer += u;
            lexState = 'identifierName';
        },

        sign () {
            switch (c) {
            case '.':
                buffer = read();
                lexState = 'decimalPointLeading';
                return

            case '0':
                buffer = read();
                lexState = 'zero';
                return

            case '1':
            case '2':
            case '3':
            case '4':
            case '5':
            case '6':
            case '7':
            case '8':
            case '9':
                buffer = read();
                lexState = 'decimalInteger';
                return

            case 'I':
                read();
                literal('nfinity');
                return newToken('numeric', sign * Infinity)

            case 'N':
                read();
                literal('aN');
                return newToken('numeric', NaN)
            }

            throw invalidChar(read())
        },

        zero () {
            switch (c) {
            case '.':
                buffer += read();
                lexState = 'decimalPoint';
                return

            case 'e':
            case 'E':
                buffer += read();
                lexState = 'decimalExponent';
                return

            case 'x':
            case 'X':
                buffer += read();
                lexState = 'hexadecimal';
                return
            }

            return newToken('numeric', sign * 0)
        },

        decimalInteger () {
            switch (c) {
            case '.':
                buffer += read();
                lexState = 'decimalPoint';
                return

            case 'e':
            case 'E':
                buffer += read();
                lexState = 'decimalExponent';
                return
            }

            if (util$1.isDigit(c)) {
                buffer += read();
                return
            }

            return newToken('numeric', sign * Number(buffer))
        },

        decimalPointLeading () {
            if (util$1.isDigit(c)) {
                buffer += read();
                lexState = 'decimalFraction';
                return
            }

            throw invalidChar(read())
        },

        decimalPoint () {
            switch (c) {
            case 'e':
            case 'E':
                buffer += read();
                lexState = 'decimalExponent';
                return
            }

            if (util$1.isDigit(c)) {
                buffer += read();
                lexState = 'decimalFraction';
                return
            }

            return newToken('numeric', sign * Number(buffer))
        },

        decimalFraction () {
            switch (c) {
            case 'e':
            case 'E':
                buffer += read();
                lexState = 'decimalExponent';
                return
            }

            if (util$1.isDigit(c)) {
                buffer += read();
                return
            }

            return newToken('numeric', sign * Number(buffer))
        },

        decimalExponent () {
            switch (c) {
            case '+':
            case '-':
                buffer += read();
                lexState = 'decimalExponentSign';
                return
            }

            if (util$1.isDigit(c)) {
                buffer += read();
                lexState = 'decimalExponentInteger';
                return
            }

            throw invalidChar(read())
        },

        decimalExponentSign () {
            if (util$1.isDigit(c)) {
                buffer += read();
                lexState = 'decimalExponentInteger';
                return
            }

            throw invalidChar(read())
        },

        decimalExponentInteger () {
            if (util$1.isDigit(c)) {
                buffer += read();
                return
            }

            return newToken('numeric', sign * Number(buffer))
        },

        hexadecimal () {
            if (util$1.isHexDigit(c)) {
                buffer += read();
                lexState = 'hexadecimalInteger';
                return
            }

            throw invalidChar(read())
        },

        hexadecimalInteger () {
            if (util$1.isHexDigit(c)) {
                buffer += read();
                return
            }

            return newToken('numeric', sign * Number(buffer))
        },

        string () {
            switch (c) {
            case '\\':
                read();
                buffer += escape();
                return

            case '"':
                if (doubleQuote) {
                    read();
                    return newToken('string', buffer)
                }

                buffer += read();
                return

            case "'":
                if (!doubleQuote) {
                    read();
                    return newToken('string', buffer)
                }

                buffer += read();
                return

            case '\n':
            case '\r':
                throw invalidChar(read())

            case '\u2028':
            case '\u2029':
                separatorChar(c);
                break

            case undefined:
                throw invalidChar(read())
            }

            buffer += read();
        },

        start () {
            switch (c) {
            case '{':
            case '[':
                return newToken('punctuator', read())

            // This code is unreachable since the default lexState handles eof.
            // case undefined:
            //     return newToken('eof')
            }

            lexState = 'value';
        },

        beforePropertyName () {
            switch (c) {
            case '$':
            case '_':
                buffer = read();
                lexState = 'identifierName';
                return

            case '\\':
                read();
                lexState = 'identifierNameStartEscape';
                return

            case '}':
                return newToken('punctuator', read())

            case '"':
            case "'":
                doubleQuote = (read() === '"');
                lexState = 'string';
                return
            }

            if (util$1.isIdStartChar(c)) {
                buffer += read();
                lexState = 'identifierName';
                return
            }

            throw invalidChar(read())
        },

        afterPropertyName () {
            if (c === ':') {
                return newToken('punctuator', read())
            }

            throw invalidChar(read())
        },

        beforePropertyValue () {
            lexState = 'value';
        },

        afterPropertyValue () {
            switch (c) {
            case ',':
            case '}':
                return newToken('punctuator', read())
            }

            throw invalidChar(read())
        },

        beforeArrayValue () {
            if (c === ']') {
                return newToken('punctuator', read())
            }

            lexState = 'value';
        },

        afterArrayValue () {
            switch (c) {
            case ',':
            case ']':
                return newToken('punctuator', read())
            }

            throw invalidChar(read())
        },

        end () {
            // This code is unreachable since it's handled by the default lexState.
            // if (c === undefined) {
            //     read()
            //     return newToken('eof')
            // }

            throw invalidChar(read())
        },
    };

    function newToken (type, value) {
        return {
            type,
            value,
            line,
            column,
        }
    }

    function literal (s) {
        for (const c of s) {
            const p = peek();

            if (p !== c) {
                throw invalidChar(read())
            }

            read();
        }
    }

    function escape () {
        const c = peek();
        switch (c) {
        case 'b':
            read();
            return '\b'

        case 'f':
            read();
            return '\f'

        case 'n':
            read();
            return '\n'

        case 'r':
            read();
            return '\r'

        case 't':
            read();
            return '\t'

        case 'v':
            read();
            return '\v'

        case '0':
            read();
            if (util$1.isDigit(peek())) {
                throw invalidChar(read())
            }

            return '\0'

        case 'x':
            read();
            return hexEscape()

        case 'u':
            read();
            return unicodeEscape()

        case '\n':
        case '\u2028':
        case '\u2029':
            read();
            return ''

        case '\r':
            read();
            if (peek() === '\n') {
                read();
            }

            return ''

        case '1':
        case '2':
        case '3':
        case '4':
        case '5':
        case '6':
        case '7':
        case '8':
        case '9':
            throw invalidChar(read())

        case undefined:
            throw invalidChar(read())
        }

        return read()
    }

    function hexEscape () {
        let buffer = '';
        let c = peek();

        if (!util$1.isHexDigit(c)) {
            throw invalidChar(read())
        }

        buffer += read();

        c = peek();
        if (!util$1.isHexDigit(c)) {
            throw invalidChar(read())
        }

        buffer += read();

        return String.fromCodePoint(parseInt(buffer, 16))
    }

    function unicodeEscape () {
        let buffer = '';
        let count = 4;

        while (count-- > 0) {
            const c = peek();
            if (!util$1.isHexDigit(c)) {
                throw invalidChar(read())
            }

            buffer += read();
        }

        return String.fromCodePoint(parseInt(buffer, 16))
    }

    const parseStates = {
        start () {
            if (token.type === 'eof') {
                throw invalidEOF()
            }

            push();
        },

        beforePropertyName () {
            switch (token.type) {
            case 'identifier':
            case 'string':
                key = token.value;
                parseState = 'afterPropertyName';
                return

            case 'punctuator':
                // This code is unreachable since it's handled by the lexState.
                // if (token.value !== '}') {
                //     throw invalidToken()
                // }

                pop();
                return

            case 'eof':
                throw invalidEOF()
            }

            // This code is unreachable since it's handled by the lexState.
            // throw invalidToken()
        },

        afterPropertyName () {
            // This code is unreachable since it's handled by the lexState.
            // if (token.type !== 'punctuator' || token.value !== ':') {
            //     throw invalidToken()
            // }

            if (token.type === 'eof') {
                throw invalidEOF()
            }

            parseState = 'beforePropertyValue';
        },

        beforePropertyValue () {
            if (token.type === 'eof') {
                throw invalidEOF()
            }

            push();
        },

        beforeArrayValue () {
            if (token.type === 'eof') {
                throw invalidEOF()
            }

            if (token.type === 'punctuator' && token.value === ']') {
                pop();
                return
            }

            push();
        },

        afterPropertyValue () {
            // This code is unreachable since it's handled by the lexState.
            // if (token.type !== 'punctuator') {
            //     throw invalidToken()
            // }

            if (token.type === 'eof') {
                throw invalidEOF()
            }

            switch (token.value) {
            case ',':
                parseState = 'beforePropertyName';
                return

            case '}':
                pop();
            }

            // This code is unreachable since it's handled by the lexState.
            // throw invalidToken()
        },

        afterArrayValue () {
            // This code is unreachable since it's handled by the lexState.
            // if (token.type !== 'punctuator') {
            //     throw invalidToken()
            // }

            if (token.type === 'eof') {
                throw invalidEOF()
            }

            switch (token.value) {
            case ',':
                parseState = 'beforeArrayValue';
                return

            case ']':
                pop();
            }

            // This code is unreachable since it's handled by the lexState.
            // throw invalidToken()
        },

        end () {
            // This code is unreachable since it's handled by the lexState.
            // if (token.type !== 'eof') {
            //     throw invalidToken()
            // }
        },
    };

    function push () {
        let value;

        switch (token.type) {
        case 'punctuator':
            switch (token.value) {
            case '{':
                value = {};
                break

            case '[':
                value = [];
                break
            }

            break

        case 'null':
        case 'boolean':
        case 'numeric':
        case 'string':
            value = token.value;
            break

        // This code is unreachable.
        // default:
        //     throw invalidToken()
        }

        if (root === undefined) {
            root = value;
        } else {
            const parent = stack[stack.length - 1];
            if (Array.isArray(parent)) {
                parent.push(value);
            } else {
                Object.defineProperty(parent, key, {
                    value,
                    writable: true,
                    enumerable: true,
                    configurable: true,
                });
            }
        }

        if (value !== null && typeof value === 'object') {
            stack.push(value);

            if (Array.isArray(value)) {
                parseState = 'beforeArrayValue';
            } else {
                parseState = 'beforePropertyName';
            }
        } else {
            const current = stack[stack.length - 1];
            if (current == null) {
                parseState = 'end';
            } else if (Array.isArray(current)) {
                parseState = 'afterArrayValue';
            } else {
                parseState = 'afterPropertyValue';
            }
        }
    }

    function pop () {
        stack.pop();

        const current = stack[stack.length - 1];
        if (current == null) {
            parseState = 'end';
        } else if (Array.isArray(current)) {
            parseState = 'afterArrayValue';
        } else {
            parseState = 'afterPropertyValue';
        }
    }

    // This code is unreachable.
    // function invalidParseState () {
    //     return new Error(`JSON5: invalid parse state '${parseState}'`)
    // }

    // This code is unreachable.
    // function invalidLexState (state) {
    //     return new Error(`JSON5: invalid lex state '${state}'`)
    // }

    function invalidChar (c) {
        if (c === undefined) {
            return syntaxError(`JSON5: invalid end of input at ${line}:${column}`)
        }

        return syntaxError(`JSON5: invalid character '${formatChar(c)}' at ${line}:${column}`)
    }

    function invalidEOF () {
        return syntaxError(`JSON5: invalid end of input at ${line}:${column}`)
    }

    // This code is unreachable.
    // function invalidToken () {
    //     if (token.type === 'eof') {
    //         return syntaxError(`JSON5: invalid end of input at ${line}:${column}`)
    //     }

    //     const c = String.fromCodePoint(token.value.codePointAt(0))
    //     return syntaxError(`JSON5: invalid character '${formatChar(c)}' at ${line}:${column}`)
    // }

    function invalidIdentifier () {
        column -= 5;
        return syntaxError(`JSON5: invalid identifier character at ${line}:${column}`)
    }

    function separatorChar (c) {
        console.warn(`JSON5: '${formatChar(c)}' in strings is not valid ECMAScript; consider escaping`);
    }

    function formatChar (c) {
        const replacements = {
            "'": "\\'",
            '"': '\\"',
            '\\': '\\\\',
            '\b': '\\b',
            '\f': '\\f',
            '\n': '\\n',
            '\r': '\\r',
            '\t': '\\t',
            '\v': '\\v',
            '\0': '\\0',
            '\u2028': '\\u2028',
            '\u2029': '\\u2029',
        };

        if (replacements[c]) {
            return replacements[c]
        }

        if (c < ' ') {
            const hexString = c.charCodeAt(0).toString(16);
            return '\\x' + ('00' + hexString).substring(hexString.length)
        }

        return c
    }

    function syntaxError (message) {
        const err = new SyntaxError(message);
        err.lineNumber = line;
        err.columnNumber = column;
        return err
    }

    var stringify = function stringify (value, replacer, space) {
        const stack = [];
        let indent = '';
        let propertyList;
        let replacerFunc;
        let gap = '';
        let quote;

        if (
            replacer != null &&
            typeof replacer === 'object' &&
            !Array.isArray(replacer)
        ) {
            space = replacer.space;
            quote = replacer.quote;
            replacer = replacer.replacer;
        }

        if (typeof replacer === 'function') {
            replacerFunc = replacer;
        } else if (Array.isArray(replacer)) {
            propertyList = [];
            for (const v of replacer) {
                let item;

                if (typeof v === 'string') {
                    item = v;
                } else if (
                    typeof v === 'number' ||
                    v instanceof String ||
                    v instanceof Number
                ) {
                    item = String(v);
                }

                if (item !== undefined && propertyList.indexOf(item) < 0) {
                    propertyList.push(item);
                }
            }
        }

        if (space instanceof Number) {
            space = Number(space);
        } else if (space instanceof String) {
            space = String(space);
        }

        if (typeof space === 'number') {
            if (space > 0) {
                space = Math.min(10, Math.floor(space));
                gap = '          '.substr(0, space);
            }
        } else if (typeof space === 'string') {
            gap = space.substr(0, 10);
        }

        return serializeProperty('', {'': value})

        function serializeProperty (key, holder) {
            let value = holder[key];
            if (value != null) {
                if (typeof value.toJSON5 === 'function') {
                    value = value.toJSON5(key);
                } else if (typeof value.toJSON === 'function') {
                    value = value.toJSON(key);
                }
            }

            if (replacerFunc) {
                value = replacerFunc.call(holder, key, value);
            }

            if (value instanceof Number) {
                value = Number(value);
            } else if (value instanceof String) {
                value = String(value);
            } else if (value instanceof Boolean) {
                value = value.valueOf();
            }

            switch (value) {
            case null: return 'null'
            case true: return 'true'
            case false: return 'false'
            }

            if (typeof value === 'string') {
                return quoteString(value)
            }

            if (typeof value === 'number') {
                return String(value)
            }

            if (typeof value === 'object') {
                return Array.isArray(value) ? serializeArray(value) : serializeObject(value)
            }

            return undefined
        }

        function quoteString (value) {
            const quotes = {
                "'": 0.1,
                '"': 0.2,
            };

            const replacements = {
                "'": "\\'",
                '"': '\\"',
                '\\': '\\\\',
                '\b': '\\b',
                '\f': '\\f',
                '\n': '\\n',
                '\r': '\\r',
                '\t': '\\t',
                '\v': '\\v',
                '\0': '\\0',
                '\u2028': '\\u2028',
                '\u2029': '\\u2029',
            };

            let product = '';

            for (let i = 0; i < value.length; i++) {
                const c = value[i];
                switch (c) {
                case "'":
                case '"':
                    quotes[c]++;
                    product += c;
                    continue

                case '\0':
                    if (util$1.isDigit(value[i + 1])) {
                        product += '\\x00';
                        continue
                    }
                }

                if (replacements[c]) {
                    product += replacements[c];
                    continue
                }

                if (c < ' ') {
                    let hexString = c.charCodeAt(0).toString(16);
                    product += '\\x' + ('00' + hexString).substring(hexString.length);
                    continue
                }

                product += c;
            }

            const quoteChar = quote || Object.keys(quotes).reduce((a, b) => (quotes[a] < quotes[b]) ? a : b);

            product = product.replace(new RegExp(quoteChar, 'g'), replacements[quoteChar]);

            return quoteChar + product + quoteChar
        }

        function serializeObject (value) {
            if (stack.indexOf(value) >= 0) {
                throw TypeError('Converting circular structure to JSON5')
            }

            stack.push(value);

            let stepback = indent;
            indent = indent + gap;

            let keys = propertyList || Object.keys(value);
            let partial = [];
            for (const key of keys) {
                const propertyString = serializeProperty(key, value);
                if (propertyString !== undefined) {
                    let member = serializeKey(key) + ':';
                    if (gap !== '') {
                        member += ' ';
                    }
                    member += propertyString;
                    partial.push(member);
                }
            }

            let final;
            if (partial.length === 0) {
                final = '{}';
            } else {
                let properties;
                if (gap === '') {
                    properties = partial.join(',');
                    final = '{' + properties + '}';
                } else {
                    let separator = ',\n' + indent;
                    properties = partial.join(separator);
                    final = '{\n' + indent + properties + ',\n' + stepback + '}';
                }
            }

            stack.pop();
            indent = stepback;
            return final
        }

        function serializeKey (key) {
            if (key.length === 0) {
                return quoteString(key)
            }

            const firstChar = String.fromCodePoint(key.codePointAt(0));
            if (!util$1.isIdStartChar(firstChar)) {
                return quoteString(key)
            }

            for (let i = firstChar.length; i < key.length; i++) {
                if (!util$1.isIdContinueChar(String.fromCodePoint(key.codePointAt(i)))) {
                    return quoteString(key)
                }
            }

            return key
        }

        function serializeArray (value) {
            if (stack.indexOf(value) >= 0) {
                throw TypeError('Converting circular structure to JSON5')
            }

            stack.push(value);

            let stepback = indent;
            indent = indent + gap;

            let partial = [];
            for (let i = 0; i < value.length; i++) {
                const propertyString = serializeProperty(String(i), value);
                partial.push((propertyString !== undefined) ? propertyString : 'null');
            }

            let final;
            if (partial.length === 0) {
                final = '[]';
            } else {
                if (gap === '') {
                    let properties = partial.join(',');
                    final = '[' + properties + ']';
                } else {
                    let separator = ',\n' + indent;
                    let properties = partial.join(separator);
                    final = '[\n' + indent + properties + ',\n' + stepback + ']';
                }
            }

            stack.pop();
            indent = stepback;
            return final
        }
    };

    const JSON5 = {
        parse: parse$1,
        stringify,
    };

    var lib = JSON5;

    var sprintf = {};

    /* global window, exports, define */
    (function (exports) {
      !function () {

        var re = {
          not_string: /[^s]/,
          not_bool: /[^t]/,
          not_type: /[^T]/,
          not_primitive: /[^v]/,
          number: /[diefg]/,
          numeric_arg: /[bcdiefguxX]/,
          json: /[j]/,
          not_json: /[^j]/,
          text: /^[^\x25]+/,
          modulo: /^\x25{2}/,
          placeholder: /^\x25(?:([1-9]\d*)\$|\(([^)]+)\))?(\+)?(0|'[^$])?(-)?(\d+)?(?:\.(\d+))?([b-gijostTuvxX])/,
          key: /^([a-z_][a-z_\d]*)/i,
          key_access: /^\.([a-z_][a-z_\d]*)/i,
          index_access: /^\[(\d+)\]/,
          sign: /^[+-]/
        };
        function sprintf(key) {
          // `arguments` is not an array, but should be fine for this call
          return sprintf_format(sprintf_parse(key), arguments);
        }
        function vsprintf(fmt, argv) {
          return sprintf.apply(null, [fmt].concat(argv || []));
        }
        function sprintf_format(parse_tree, argv) {
          var cursor = 1,
            tree_length = parse_tree.length,
            arg,
            output = '',
            i,
            k,
            ph,
            pad,
            pad_character,
            pad_length,
            is_positive,
            sign;
          for (i = 0; i < tree_length; i++) {
            if (typeof parse_tree[i] === 'string') {
              output += parse_tree[i];
            } else if (typeof parse_tree[i] === 'object') {
              ph = parse_tree[i]; // convenience purposes only
              if (ph.keys) {
                // keyword argument
                arg = argv[cursor];
                for (k = 0; k < ph.keys.length; k++) {
                  if (arg == undefined) {
                    throw new Error(sprintf('[sprintf] Cannot access property "%s" of undefined value "%s"', ph.keys[k], ph.keys[k - 1]));
                  }
                  arg = arg[ph.keys[k]];
                }
              } else if (ph.param_no) {
                // positional argument (explicit)
                arg = argv[ph.param_no];
              } else {
                // positional argument (implicit)
                arg = argv[cursor++];
              }
              if (re.not_type.test(ph.type) && re.not_primitive.test(ph.type) && arg instanceof Function) {
                arg = arg();
              }
              if (re.numeric_arg.test(ph.type) && typeof arg !== 'number' && isNaN(arg)) {
                throw new TypeError(sprintf('[sprintf] expecting number but found %T', arg));
              }
              if (re.number.test(ph.type)) {
                is_positive = arg >= 0;
              }
              switch (ph.type) {
                case 'b':
                  arg = parseInt(arg, 10).toString(2);
                  break;
                case 'c':
                  arg = String.fromCharCode(parseInt(arg, 10));
                  break;
                case 'd':
                case 'i':
                  arg = parseInt(arg, 10);
                  break;
                case 'j':
                  arg = JSON.stringify(arg, null, ph.width ? parseInt(ph.width) : 0);
                  break;
                case 'e':
                  arg = ph.precision ? parseFloat(arg).toExponential(ph.precision) : parseFloat(arg).toExponential();
                  break;
                case 'f':
                  arg = ph.precision ? parseFloat(arg).toFixed(ph.precision) : parseFloat(arg);
                  break;
                case 'g':
                  arg = ph.precision ? String(Number(arg.toPrecision(ph.precision))) : parseFloat(arg);
                  break;
                case 'o':
                  arg = (parseInt(arg, 10) >>> 0).toString(8);
                  break;
                case 's':
                  arg = String(arg);
                  arg = ph.precision ? arg.substring(0, ph.precision) : arg;
                  break;
                case 't':
                  arg = String(!!arg);
                  arg = ph.precision ? arg.substring(0, ph.precision) : arg;
                  break;
                case 'T':
                  arg = Object.prototype.toString.call(arg).slice(8, -1).toLowerCase();
                  arg = ph.precision ? arg.substring(0, ph.precision) : arg;
                  break;
                case 'u':
                  arg = parseInt(arg, 10) >>> 0;
                  break;
                case 'v':
                  arg = arg.valueOf();
                  arg = ph.precision ? arg.substring(0, ph.precision) : arg;
                  break;
                case 'x':
                  arg = (parseInt(arg, 10) >>> 0).toString(16);
                  break;
                case 'X':
                  arg = (parseInt(arg, 10) >>> 0).toString(16).toUpperCase();
                  break;
              }
              if (re.json.test(ph.type)) {
                output += arg;
              } else {
                if (re.number.test(ph.type) && (!is_positive || ph.sign)) {
                  sign = is_positive ? '+' : '-';
                  arg = arg.toString().replace(re.sign, '');
                } else {
                  sign = '';
                }
                pad_character = ph.pad_char ? ph.pad_char === '0' ? '0' : ph.pad_char.charAt(1) : ' ';
                pad_length = ph.width - (sign + arg).length;
                pad = ph.width ? pad_length > 0 ? pad_character.repeat(pad_length) : '' : '';
                output += ph.align ? sign + arg + pad : pad_character === '0' ? sign + pad + arg : pad + sign + arg;
              }
            }
          }
          return output;
        }
        var sprintf_cache = Object.create(null);
        function sprintf_parse(fmt) {
          if (sprintf_cache[fmt]) {
            return sprintf_cache[fmt];
          }
          var _fmt = fmt,
            match,
            parse_tree = [],
            arg_names = 0;
          while (_fmt) {
            if ((match = re.text.exec(_fmt)) !== null) {
              parse_tree.push(match[0]);
            } else if ((match = re.modulo.exec(_fmt)) !== null) {
              parse_tree.push('%');
            } else if ((match = re.placeholder.exec(_fmt)) !== null) {
              if (match[2]) {
                arg_names |= 1;
                var field_list = [],
                  replacement_field = match[2],
                  field_match = [];
                if ((field_match = re.key.exec(replacement_field)) !== null) {
                  field_list.push(field_match[1]);
                  while ((replacement_field = replacement_field.substring(field_match[0].length)) !== '') {
                    if ((field_match = re.key_access.exec(replacement_field)) !== null) {
                      field_list.push(field_match[1]);
                    } else if ((field_match = re.index_access.exec(replacement_field)) !== null) {
                      field_list.push(field_match[1]);
                    } else {
                      throw new SyntaxError('[sprintf] failed to parse named argument key');
                    }
                  }
                } else {
                  throw new SyntaxError('[sprintf] failed to parse named argument key');
                }
                match[2] = field_list;
              } else {
                arg_names |= 2;
              }
              if (arg_names === 3) {
                throw new Error('[sprintf] mixing positional and named placeholders is not (yet) supported');
              }
              parse_tree.push({
                placeholder: match[0],
                param_no: match[1],
                keys: match[2],
                sign: match[3],
                pad_char: match[4],
                align: match[5],
                width: match[6],
                precision: match[7],
                type: match[8]
              });
            } else {
              throw new SyntaxError('[sprintf] unexpected placeholder');
            }
            _fmt = _fmt.substring(match[0].length);
          }
          return sprintf_cache[fmt] = parse_tree;
        }

        /**
         * export to either browser or node.js
         */
        /* eslint-disable quote-props */
        {
          exports['sprintf'] = sprintf;
          exports['vsprintf'] = vsprintf;
        }
        if (typeof window !== 'undefined') {
          window['sprintf'] = sprintf;
          window['vsprintf'] = vsprintf;
        }
        /* eslint-enable quote-props */
      }(); // eslint-disable-line 
    })(sprintf);

    /*
     * CSSTokenizer v1.1.1 (build date: Thu, 19 Sep 2024 13:23:31 GMT)
     * (c) 2024 Adguard Software Ltd.
     * Released under the MIT license
     * https://github.com/AdguardTeam/tsurlfilter/tree/master/packages/css-tokenizer#readme
     */
    /**
     * @file Implementation of CSS Syntax Module Level 3 tokenizer definitions (§ 4.2.)
     *
     * @see {@link https://www.w3.org/TR/css-syntax-3/#tokenizer-definitions}
     */
    /**
     * Check if code point code is between two code points
     *
     * @param code Code point to check
     * @param min Minimum code point
     * @param max Maximum code point
     * @returns `true` if code point is between `min` and `max`, `false` otherwise
     * @note Boundaries are inclusive
     * @note This function is used instead of `code >= min && code <= max` because TypeScript doesn't allow to compare
     * `number | undefined` with `number` (even though it's perfectly valid in JavaScript)
     */
    function isBetween(code, min, max) {
        // eslint-disable-next-line @typescript-eslint/ban-ts-comment
        // @ts-ignore 18048
        return code >= min && code <= max;
    }
    /**
     * Check if code point code is greater than or equal to other code point
     *
     * @param code Code point to check
     * @param min Minimum code point
     * @returns `true` if code point is greater than or equal to `min`, `false` otherwise
     * @note This function is used instead of `code >= min` because TypeScript doesn't allow to compare
     * `number | undefined` with `number` (even though it's perfectly valid in JavaScript)
     */
    function isGreaterThanOrEqual(code, min) {
        // eslint-disable-next-line @typescript-eslint/ban-ts-comment
        // @ts-ignore 18048
        return code >= min;
    }
    /**
     * Check if character code is a digit
     *
     * @param code Character code
     * @returns `true` if character code is a digit, `false` otherwise
     * @see {@link https://www.w3.org/TR/css-syntax-3/#digit}
     */
    function isDigit(code) {
        // A code point between U+0030 DIGIT ZERO (0) and U+0039 DIGIT NINE (9) inclusive.
        return isBetween(code, 48 /* CodePoint.DigitZero */, 57 /* CodePoint.DigitNine */);
    }
    /**
     * Check if character code is a hex digit
     *
     * @param code Character code
     * @returns `true` if character code is a hex digit, `false` otherwise
     * @see {@link https://www.w3.org/TR/css-syntax-3/#hex-digit}
     */
    function isHexDigit(code) {
        // A digit, or a code point between U+0041 LATIN CAPITAL LETTER A (A) and U+0046 LATIN CAPITAL LETTER F (F)
        // inclusive, or a code point between U+0061 LATIN SMALL LETTER A (a) and U+0066 LATIN SMALL LETTER F (f) inclusive.
        return isDigit(code) // 0-9
            || isBetween(code, 65 /* CodePoint.LatinCapitalLetterA */, 70 /* CodePoint.LatinCapitalLetterF */) // A-F
            || isBetween(code, 97 /* CodePoint.LatinSmallLetterA */, 102 /* CodePoint.LatinSmallLetterF */); // a-f
    }
    /**
     * Check if character code is an uppercase letter
     *
     * @param code Character code
     * @returns `true` if character code is an uppercase letter, `false` otherwise
     * @see {@link https://www.w3.org/TR/css-syntax-3/#uppercase-letter}
     */
    function isUppercaseLetter(code) {
        // A code point between U+0041 LATIN CAPITAL LETTER A (A) and U+005A LATIN CAPITAL LETTER Z (Z) inclusive.
        return isBetween(code, 65 /* CodePoint.LatinCapitalLetterA */, 90 /* CodePoint.LatinCapitalLetterZ */); // A-Z
    }
    /**
     * Check if character code is a lowercase letter
     *
     * @param code Character code
     * @returns `true` if character code is a lowercase letter, `false` otherwise
     * @see {@link https://www.w3.org/TR/css-syntax-3/#lowercase-letter}
     */
    function isLowercaseLetter(code) {
        // A code point between U+0061 LATIN SMALL LETTER A (a) and U+007A LATIN SMALL LETTER Z (z) inclusive.
        return isBetween(code, 97 /* CodePoint.LatinSmallLetterA */, 122 /* CodePoint.LatinSmallLetterZ */); // a-z
    }
    /**
     * Check if character code is a letter
     *
     * @param code Character code
     * @returns `true` if character code is a letter, `false` otherwise
     * @see {@link https://www.w3.org/TR/css-syntax-3/#letter}
     */
    function isLetter(code) {
        // An uppercase letter or a lowercase letter.
        return isUppercaseLetter(code) || isLowercaseLetter(code); // A-Z or a-z
    }
    /**
     * Check if character code is a non-ASCII code point
     *
     * @param code Character code
     * @returns `true` if character code is a non-ASCII code point, `false` otherwise
     * @see {@link https://www.w3.org/TR/css-syntax-3/#non-ascii-code-point}
     */
    function isNonAsciiCodePoint(code) {
        // A code point with a value equal to or greater than U+0080 <control>.
        return isGreaterThanOrEqual(code, 128 /* CodePoint.ControlCharacterStart */);
    }
    /**
     * Check if character code is a name code point
     *
     * @param code Character code
     * @returns `true` if character code is a name start code point, `false` otherwise
     * @see {@link https://www.w3.org/TR/css-syntax-3/#ident-start-code-point}
     */
    function isIdentStartCodePoint(code) {
        // A letter, a non-ASCII code point, or U+005F LOW LINE (_).
        return isLetter(code) || isNonAsciiCodePoint(code) || code === 95 /* CodePoint.LowLine */;
    }
    /**
     * Check if character code is a name code point
     *
     * @param code Character code
     * @returns `true` if character code is a name code point, `false` otherwise
     * @see {@link https://www.w3.org/TR/css-syntax-3/#ident-code-point}
     */
    function isIdentCodePoint(code) {
        // An ident-start code point, a digit, or U+002D HYPHEN-MINUS (-).
        return isIdentStartCodePoint(code) || isDigit(code) || code === 45 /* CodePoint.HyphenMinus */;
    }
    /**
     * Check if character code is a non-printable code point
     *
     * @param code Character code
     * @returns `true` if character code is a non-printable code point, `false` otherwise
     * @see {@link https://www.w3.org/TR/css-syntax-3/#non-printable-code-point}
     */
    function isNonPrintableCodePoint(code) {
        // A code point between U+0000 NULL and U+0008 BACKSPACE inclusive, or U+000B LINE TABULATION, or a code point
        // between U+000E SHIFT OUT and U+001F INFORMATION SEPARATOR ONE inclusive, or U+007F DELETE.
        return isBetween(code, 0 /* CodePoint.Null */, 8 /* CodePoint.Backspace */)
            || code === 11 /* CodePoint.LineTabulation */
            || isBetween(code, 14 /* CodePoint.ShiftOut */, 31 /* CodePoint.InformationSeparatorOne */)
            || code === 127 /* CodePoint.Delete */;
    }
    /**
     * Check if character code is a newline
     *
     * @param code Character code
     * @returns `true` if character code is a newline, `false` otherwise
     * @see {@link https://www.w3.org/TR/css-syntax-3/#newline}
     */
    function isNewline(code) {
        // U+000A LINE FEED. Note that U+000D CARRIAGE RETURN and U+000C FORM FEED are not included in this definition, as
        // they are converted to U+000A LINE FEED during preprocessing.
        return code === 10 /* CodePoint.LineFeed */ || code === 13 /* CodePoint.CarriageReturn */ || code === 12 /* CodePoint.FormFeed */;
    }
    /**
     * Check if character code is a whitespace
     *
     * @param code Character code
     * @returns `true` if character code is a whitespace, `false` otherwise
     * @see {@link https://www.w3.org/TR/css-syntax-3/#whitespace}
     */
    function isWhitespace$1(code) {
        // A newline, U+0009 CHARACTER TABULATION, or U+0020 SPACE.
        return isNewline(code) || code === 9 /* CodePoint.CharacterTabulation */ || code === 32 /* CodePoint.Space */;
    }
    // TODO: Uncomment when needed, maybe useful in the future
    // /**
    //  * Check if character code is a valid identifier sequence code point
    //  *
    //  * @param code Character code
    //  * @returns `true` if character code is a valid identifier sequence code point, `false` otherwise
    //  * @see {@link https://www.w3.org/TR/css-syntax-3/#ident-sequence}
    //  * @note The part of an <at-keyword-token> after the "@", the part of a <hash-token> (with the "id" type flag) after
    //  * the "#", the part of a <function-token> before the "(", and the unit of a <dimension-token> are all ident
    //  * sequences.
    //  */
    // export function isIdentSequence(code: number): boolean {
    //     // A sequence of code points that has the same syntax as an <ident-token>.
    // eslint-disable-next-line max-len
    //     return isIdentStartCodePoint(code) || isDigit(code) || code === CodePoint.HyphenMinus || code === CodePoint.LowLine;
    // }
    /**
     * Check if character code is a BOM (Byte Order Mark)
     *
     * @param code Character code to check
     * @returns `true` if character code is a BOM, `false` otherwise
     */
    function isBOM(code) {
        return code === 65279 /* CodePoint.Utf16BeBom */ || code === 65534 /* CodePoint.Utf16LeBom */;
    }
    /**
     * § 4.3.8. Check if two code points are a valid escape
     *
     * @param a First code point
     * @param b Second code point
     * @returns `true` if the code points are a valid escape, `false` otherwise
     * @see {@link https://www.w3.org/TR/css-syntax-3/#starts-with-a-valid-escape}
     * @note This algorithm will not consume any additional code point.
     */
    const checkForValidEscape = (a, b) => {
        // If the first code point is not U+005C REVERSE SOLIDUS (\), return false.
        if (a !== 92 /* CodePoint.ReverseSolidus */) {
            return false;
        }
        // Otherwise, if the second code point is a newline, return false.
        // Otherwise, return true.
        return !isNewline(b);
    };
    /**
     * § 4.3.9. Check if three code points would start an ident sequence
     *
     * @param a First code point
     * @param b Second code point
     * @param c Third code point
     * @returns `true` if the next code points would start an identifier, `false` otherwise
     * @see {@link https://www.w3.org/TR/css-syntax-3/#would-start-an-identifier}
     * @note This algorithm will not consume any additional code points.
     */
    const checkForIdentStart = (a, b, c) => {
        // Look at the first code point:
        // U+002D HYPHEN-MINUS
        if (a === 45 /* CodePoint.HyphenMinus */) {
            // If the second code point is an ident-start code point or a U+002D HYPHEN-MINUS,
            // or the second and third code points are a valid escape, return true. Otherwise, return false.
            return isIdentStartCodePoint(b) || b === 45 /* CodePoint.HyphenMinus */ || checkForValidEscape(b, c);
        }
        // ident-start code point
        if (isIdentStartCodePoint(a)) {
            // Return true.
            return true;
        }
        // U+005C REVERSE SOLIDUS (\)
        if (a === 92 /* CodePoint.ReverseSolidus */) {
            // If the first and second code points are a valid escape, return true. Otherwise, return false.
            return checkForValidEscape(a, b);
        }
        // anything else
        // Return false.
        return false;
    };
    /**
     * § 4.3.10. Check if three code points would start a number
     *
     * @param a First code point
     * @param b Second code point
     * @param c Third code point
     * @returns `true` if the next code points would start a number, `false` otherwise
     * @see {@link https://www.w3.org/TR/css-syntax-3/#starts-with-a-number}
     * @note This algorithm will not consume any additional code points.
     */
    const checkForNumberStart = (a, b, c) => {
        // Look at the first code point:
        // U+002B PLUS SIGN (+)
        // U+002D HYPHEN-MINUS (-)
        if (a === 43 /* CodePoint.PlusSign */ || a === 45 /* CodePoint.HyphenMinus */) {
            // If the second code point is a digit, return true.
            if (isDigit(b)) {
                return true;
            }
            // Otherwise, if the second code point is a U+002E FULL STOP (.) and the third code point is a digit, return
            // true.
            // Otherwise, return false.
            return b === 46 /* CodePoint.FullStop */ && isDigit(c);
        }
        // U+002E FULL STOP (.)
        if (a === 46 /* CodePoint.FullStop */) {
            // If the second code point is a digit, return true. Otherwise, return false.
            return isDigit(b);
        }
        // digit
        // Return true.
        // anything else
        // Return false.
        return isDigit(a);
    };

    /* eslint-disable no-bitwise */
    /**
     * @file Hashing functions based on the djb2 algorithm
     *
     * @see {@link http://www.cse.yorku.ca/~oz/hash.html}
     * @see {@link https://gist.github.com/eplawless/52813b1d8ad9af510d85?permalink_comment_id=3367765#gistcomment-3367765}
     * @todo If we need it, we can create case-sensitive versions of these functions
     */
    /**
     * Make a unique hash from the given array of code points
     *
     * @param arr Reference to the array of code points
     * @param start Start index
     * @param end End index
     * @returns Hash of the given array of code points
     * @note Case-insensitive (we use it just for function names which are case-insensitive)
     */
    function getCodePointsArrayHash(arr, start, end) {
        let hash = 5381;
        for (let i = start; i < end; i += 1) {
            hash = hash * 33 ^ (arr[i] | 0x20);
        }
        return hash >>> 0;
    }

    /**
     * @file Tokenizer context
     */
    /**
     * Context of the tokenizer which is shared between all the functions
     */
    class TokenizerContext {
        /**
         * Cached source length
         */
        length;
        /**
         * Reference to the `onToken` callback function
         */
        onToken;
        /**
         * Reference to the `onError` callback function
         */
        onError;
        /**
         * Unicode code points of the source string
         *
         * @note The last code point is always EOF ("imaginary" code point)
         * @note Using `!` is safe here because the `preprocess` function always sets the codes in the constructor
         * @note We need a signed 32-bit integer array, because the code points are 21-bit integers + imaginary code points
         * are negative numbers
         */
        codes;
        /**
         * Actual position in the source string
         */
        cursor;
        /**
         * Custom function handlers to handle special functions, like Extended CSS's pseudo selectors
         */
        customFunctionHandlers;
        /**
         * Constructs a new tokenizer context instance
         *
         * @param source Source string
         * @param onToken Callback function to call when a token is found
         * @param onError Callback function to call when a parsing error occurs
         * @param functionHandlers Custom function handlers to handle special functions, like Extended CSS's pseudo
         * selectors
         */
        constructor(source, onToken, onError, functionHandlers) {
            // Set the source and offset
            // this.source = source;
            this.length = source.length;
            this.preprocess(source);
            // Ignore BOM character if present
            this.cursor = isBOM(this.codes[0]) ? 1 : 0;
            // Set the callback functions
            this.onToken = onToken;
            this.onError = onError;
            // Register custom function handlers, if any
            if (functionHandlers) {
                this.customFunctionHandlers = new Map();
                for (const [hash, handler] of functionHandlers) {
                    this.customFunctionHandlers.set(hash, handler);
                }
            }
        }
        /**
         * § 3.3. Preprocessing the input stream
         *
         * @param source Source string to preprocess
         * @see {@link https://www.w3.org/TR/css-syntax-3/#input-preprocessing}
         */
        preprocess(source) {
            const len = source.length;
            this.codes = new Int32Array(len + 1); // add +1 slot for the EOF "code point"
            // TODO: Uncomment when needed - actually, we don't convert the CRLF to LF to keep the original source positions
            // // The input stream consists of the filtered code points pushed into it as the input byte stream is decoded.
            // for (let i = 0; i < len; i += 1) {
            //     const code = source.charCodeAt(i);
            //     // To filter code points from a stream of (unfiltered) code points input:
            //     switch (code) {
            //         // Replace any U+000D CARRIAGE RETURN (CR) code points, U+000C FORM FEED (FF) code points, or pairs
            //         // of U+000D CARRIAGE RETURN (CR) followed by U+000A LINE FEED (LF) in input by a single
            //         // U+000A LINE FEED (LF) code point.
            //         case CodePoint.CarriageReturn:
            //             if (source.charCodeAt(i + 1) === CodePoint.LineFeed) {
            //                 this.codes[i] = CodePoint.LineFeed;
            //                 // Skip the next code point
            //                 i += 1;
            //                 break;
            //             }
            //             this.codes[i] = CodePoint.LineFeed;
            //             break;
            //         case CodePoint.FormFeed:
            //             this.codes[i] = CodePoint.LineFeed;
            //             break;
            //         // Replace any U+0000 NULL or surrogate code points in input with U+FFFD REPLACEMENT CHARACTER (�).
            //         case CodePoint.Null:
            //             this.codes[i] = CodePoint.ReplacementCharacter;
            //             break;
            //         default:
            //             this.codes[i] = code;
            //             break;
            //     }
            // }
            // Everything what we need here is to transform the ASCII source to Unicode code points as fast as possible
            for (let i = 0; i < len; i += 1) {
                this.codes[i] = source.charCodeAt(i);
            }
            // Set last code point to EOF (this way we can use it in switch-case statements, which are faster than if-else
            // or classic lookup tables)
            // See https://stackoverflow.com/a/37955539
            this.codes[len] = -1 /* ImaginaryCodePoint.Eof */;
        }
        /**
         * Gets the corresponding custom function handler for the given function name hash
         *
         * @param hash Function name hash
         * @returns Corresponding custom function handler or `undefined` if not found
         */
        getFunctionHandler(hash) {
            return this.customFunctionHandlers?.get(hash);
        }
        /**
         * Checks if the custom function handler is registered for the given function name hash
         *
         * @param hash Custom function name hash
         * @returns `true` if the custom function handler is registered, `false` otherwise
         */
        hasFunctionHandler(hash) {
            return this.customFunctionHandlers?.has(hash) ?? false;
        }
        /**
         * Returns the current offset
         *
         * @returns Current offset
         */
        get offset() {
            return this.cursor;
        }
        /**
         * Returns the code point at the current offset
         *
         * @returns Code point at the current offset
         */
        get code() {
            return this.codes[this.offset];
        }
        /**
         * Returns the code point at the previous offset
         *
         * @returns Code point at the previous offset or `undefined` if the offset is out of bounds
         */
        get prevCode() {
            return this.codes[this.offset - 1];
        }
        /**
         * Returns the code point at the next offset
         *
         * @returns Code point at the next offset or `undefined` if the offset is out of bounds
         */
        get nextCode() {
            return this.codes[this.offset + 1];
        }
        /**
         * Returns the code point at the given relative offset
         *
         * @param relativeOffset Relative offset
         * @returns Code point at the relative offset or `undefined` if the offset is out of bounds
         * @note Relative offset compared to the current offset. 1 means the next code point, -1 means the previous code
         * point, 2 means the code point after the next code point, etc.
         */
        getRelativeCode(relativeOffset) {
            return this.codes[this.offset + relativeOffset];
        }
        /**
         * Check if the current offset is at the end of the source (or past it)
         *
         * @returns `true` if the current offset is at the end of the source, `false` otherwise
         */
        isEof() {
            return this.offset >= this.length;
        }
        /**
         * Check if the next code point is EOF
         *
         * @returns `true` if the next code point is EOF, `false` otherwise
         */
        isNextEof() {
            return this.cursor + 1 === this.length;
        }
        /**
         * Check if the current offset is less than or equal to the end of the source
         *
         * @returns `true` if the current offset is less than or equal to the end of the source, `false` otherwise
         */
        isLessThanEqualToEof() {
            return this.offset <= this.length;
        }
        /**
         * Consumes the given number of code points
         *
         * @param n Number of code points to consume (default: 1)
         * @note Negative numbers are allowed (they will move the cursor backwards)
         * @note No protection against out of bounds for performance reasons
         */
        consumeCodePoint(n = 1) {
            this.cursor += n;
        }
        /**
         * Finds the next non-whitespace code point and returns it
         *
         * @returns Next non-whitespace code point or EOF imaginary code point if the rest of the source is whitespace
         */
        getNextNonWsCode() {
            let i = this.cursor;
            while (i < this.length && isWhitespace$1(this.codes[i])) {
                i += 1;
            }
            return this.codes[i];
        }
        /**
         * Consumes the whitespace code points
         */
        consumeWhitespace() {
            while (this.code && isWhitespace$1(this.code)) {
                this.consumeCodePoint();
            }
        }
        /**
         * Consumes a single whitespace code point, if the current code point is a whitespace
         */
        consumeSingleWhitespace() {
            if (isWhitespace$1(this.code)) {
                // special case: consume CRLF as a single whitespace
                this.cursor += this.code === 13 /* CodePoint.CarriageReturn */ && this.nextCode === 10 /* CodePoint.LineFeed */ ? 2 : 1;
            }
        }
        /**
         * Consumes everything until the end of the comment (or the end of the source)
         */
        consumeUntilCommentEnd() {
            // search for the end of the comment or reach the end of the source
            while (this.cursor < this.length) {
                // check if the current code point is a *
                if (this.code === 42 /* CodePoint.Asterisk */ && this.nextCode === 47 /* CodePoint.Solidus */) {
                    // consume '*/' and exit the loop
                    this.cursor += 2;
                    break;
                }
                // consume the current code point, it seems it's a part of the comment
                this.cursor += 1;
            }
        }
        /**
         * Consumes a single-character token (trivial token) and reports it via the `onToken` callback
         *
         * @param tokenType Token type to report
         */
        consumeTrivialToken(tokenType) {
            // eslint-disable-next-line no-plusplus
            this.onToken(tokenType, this.cursor, ++this.cursor);
        }
        /**
         * Calculates the hash of the fragment from the given start offset to the current offset. This is useful to
         * fast-check function names.
         *
         * @param start Start offset
         * @returns Calculated hash
         */
        getHashFrom(start) {
            return getCodePointsArrayHash(this.codes, start, this.cursor);
        }
    }

    /**
     * @file Possible CSS token types, as defined in the CSS Syntax Module Level 3.
     *
     * ! Strictly follows the spec.
     *
     * @see {@link https://www.w3.org/TR/css-syntax-3/#tokenization}
     */
    var TokenType$1;
    (function (TokenType) {
        TokenType[TokenType["Eof"] = 0] = "Eof";
        TokenType[TokenType["Ident"] = 1] = "Ident";
        TokenType[TokenType["Function"] = 2] = "Function";
        TokenType[TokenType["AtKeyword"] = 3] = "AtKeyword";
        TokenType[TokenType["Hash"] = 4] = "Hash";
        TokenType[TokenType["String"] = 5] = "String";
        TokenType[TokenType["BadString"] = 6] = "BadString";
        TokenType[TokenType["Url"] = 7] = "Url";
        TokenType[TokenType["BadUrl"] = 8] = "BadUrl";
        TokenType[TokenType["Delim"] = 9] = "Delim";
        TokenType[TokenType["Number"] = 10] = "Number";
        TokenType[TokenType["Percentage"] = 11] = "Percentage";
        TokenType[TokenType["Dimension"] = 12] = "Dimension";
        TokenType[TokenType["Whitespace"] = 13] = "Whitespace";
        TokenType[TokenType["Cdo"] = 14] = "Cdo";
        TokenType[TokenType["Cdc"] = 15] = "Cdc";
        TokenType[TokenType["Colon"] = 16] = "Colon";
        TokenType[TokenType["Semicolon"] = 17] = "Semicolon";
        TokenType[TokenType["Comma"] = 18] = "Comma";
        TokenType[TokenType["OpenSquareBracket"] = 19] = "OpenSquareBracket";
        TokenType[TokenType["CloseSquareBracket"] = 20] = "CloseSquareBracket";
        TokenType[TokenType["OpenParenthesis"] = 21] = "OpenParenthesis";
        TokenType[TokenType["CloseParenthesis"] = 22] = "CloseParenthesis";
        TokenType[TokenType["OpenCurlyBracket"] = 23] = "OpenCurlyBracket";
        TokenType[TokenType["CloseCurlyBracket"] = 24] = "CloseCurlyBracket";
        TokenType[TokenType["Comment"] = 25] = "Comment";
    })(TokenType$1 || (TokenType$1 = {}));

    /**
     * @file CSS token names
     */
    const UNKNOWN_TOKEN_NAME = 'unknown';
    /**
     * Pairs of token types and their base names
     */
    const TOKEN_NAMES = Object.freeze({
        [TokenType$1.Eof]: 'eof',
        [TokenType$1.Ident]: 'ident',
        [TokenType$1.Function]: 'function',
        [TokenType$1.AtKeyword]: 'at-keyword',
        [TokenType$1.Hash]: 'hash',
        [TokenType$1.String]: 'string',
        [TokenType$1.BadString]: 'bad-string',
        [TokenType$1.Url]: 'url',
        [TokenType$1.BadUrl]: 'bad-url',
        [TokenType$1.Delim]: 'delim',
        [TokenType$1.Number]: 'number',
        [TokenType$1.Percentage]: 'percentage',
        [TokenType$1.Dimension]: 'dimension',
        [TokenType$1.Whitespace]: 'whitespace',
        [TokenType$1.Cdo]: 'CDO',
        [TokenType$1.Cdc]: 'CDC',
        [TokenType$1.Colon]: 'colon',
        [TokenType$1.Semicolon]: 'semicolon',
        [TokenType$1.Comma]: 'comma',
        [TokenType$1.OpenSquareBracket]: '[',
        [TokenType$1.CloseSquareBracket]: ']',
        [TokenType$1.OpenParenthesis]: '(',
        [TokenType$1.CloseParenthesis]: ')',
        [TokenType$1.OpenCurlyBracket]: '{',
        [TokenType$1.CloseCurlyBracket]: '}',
        [TokenType$1.Comment]: 'comment',
    });
    /**
     * Get base token name by token type
     *
     * @param type Token type
     *
     * @example
     * ```ts
     * getBaseTokenName(TokenType.Ident); // 'ident'
     * getBaseTokenName(-1); // 'unknown'
     * ```
     *
     * @returns Base token name or 'unknown' if token type is unknown
     */
    const getBaseTokenName = (type) => {
        return TOKEN_NAMES[type] ?? UNKNOWN_TOKEN_NAME;
    };
    /**
     * Get formatted token name by token type
     *
     * @param type Token type
     *
     * @example
     * ```ts
     * getFormattedTokenName(TokenType.Ident); // '<ident-token>'
     * getFormattedTokenName(-1); // '<unknown-token>'
     * ```
     *
     * @returns Formatted token name or `'<unknown-token>'` if token type is unknown
     */
    const getFormattedTokenName = (type) => {
        return `<${getBaseTokenName(type)}-token>`;
    };

    /**
     * @file Tokenizing logic for escaped code points
     */
    const MAX_HEX_DIGITS = 6;
    /**
     * § 4.3.7. Consume an escaped code point
     *
     * @param context Reference to the tokenizer context instance
     * @see {@link https://www.w3.org/TR/css-syntax-3/#consume-escaped-code-point}
     */
    const consumeEscapedCodePoint = (context) => {
        // It assumes that the U+005C REVERSE SOLIDUS (\) has already been consumed and that the next input code point has
        // already been verified to be part of a valid escape.
        // Consume the next input code point.
        context.consumeCodePoint();
        // hex digit
        if (isHexDigit(context.code)) {
            // Consume as many hex digits as possible, but no more than 5. Note that this means 1-6 hex digits have been
            // consumed in total. If the next input code point is whitespace, consume it as well. Interpret the hex digits
            // as a hexadecimal number.
            let consumedHexDigits = 0;
            while (isHexDigit(context.code) && consumedHexDigits <= MAX_HEX_DIGITS) {
                context.consumeCodePoint();
                consumedHexDigits += 1;
            }
            // If the next input code point is whitespace, consume it as well.
            context.consumeSingleWhitespace();
            // If this number is zero, or is for a surrogate, or is greater than the maximum allowed code point,
            // return U+FFFD REPLACEMENT CHARACTER (�).
            // Otherwise, return the code point with that value.
            // TODO: Implement surrogate check
        }
        // EOF
        // This is a parse error. Return U+FFFD REPLACEMENT CHARACTER (�).
        if (context.isEof()) {
            context.onError("Unexpected end of file while parsing escaped code point." /* ErrorMessage.UnexpectedEofInEscaped */, context.offset, context.offset);
        }
        // anything else
        // Return the current input code point.
    };

    /**
     * @file Tokenizing logic for ident sequences
     */
    /**
     * § 4.3.11. Consume an ident sequence
     *
     * Consume an ident sequence from a stream of code points. It returns a string containing the largest name that can be
     * formed from adjacent code points in the stream, starting from the first.
     *
     * @param context Reference to the tokenizer context instance
     * @see {@link https://www.w3.org/TR/css-syntax-3/#consume-name}
     * @note This algorithm does not do the verification of the first few code points that are necessary to ensure the
     * returned code points would constitute an <ident-token>. If that is the intended use, ensure that the stream
     * starts with an ident sequence before calling this algorithm.
     */
    const consumeIndentSequence = (context) => {
        // Let result initially be an empty string.
        // Repeatedly consume the next input code point from the stream:
        while (!context.isEof()) {
            // ident code point
            if (isIdentCodePoint(context.code)) {
                // Append the code point to result.
                context.consumeCodePoint();
                continue;
            }
            // the stream starts with a valid escape
            if (checkForValidEscape(context.code, context.nextCode)) {
                // Consume an escaped code point. Append the returned code point to result.
                context.consumeCodePoint();
                consumeEscapedCodePoint(context);
                continue;
            }
            // anything else
            // Reconsume the current input code point. Return result.
            return;
        }
    };

    /**
     * @file Tokenizing logic for URLs
     */
    /**
     * § 4.3.14. Consume the remnants of a bad url
     *
     * Consume the remnants of a bad url from a stream of code points, "cleaning up" after the tokenizer realizes that it’s
     * in the middle of a <bad-url-token> rather than a <url-token>. It returns nothing; its sole use is to consume enough
     * of the input stream to reach a recovery point where normal tokenizing can resume.
     *
     * @param context Tokenizer context
     * @see {@link https://www.w3.org/TR/css-syntax-3/#consume-remnants-of-bad-url}
     */
    function consumeBadUrlRemnants(context) {
        // Repeatedly consume the next input code point from the stream:
        // eslint-disable-next-line no-constant-condition
        for (; !context.isEof(); context.consumeCodePoint()) {
            // U+0029 RIGHT PARENTHESIS ())
            if (context.code === 41 /* CodePoint.RightParenthesis */) {
                // Don’t forget to consume it.
                context.consumeCodePoint();
                return;
            }
            // the input stream starts with a valid escape
            if (checkForValidEscape(context.getRelativeCode(1), context.getRelativeCode(2))) {
                // Consume an escaped code point. This allows an escaped right parenthesis ("\)") to be encountered
                // without ending the <bad-url-token>. This is otherwise identical to the "anything else" clause.
                context.consumeCodePoint();
                consumeEscapedCodePoint(context);
                continue;
            }
            // anything else
            // Do nothing.
        }
    }
    /**
     * Helper function for consuming a bad url token.
     *
     * @param context Tokenizer context
     * @param start Token start offset
     * @see {@link https://www.w3.org/TR/css-syntax-3/#consume-remnants-of-bad-url}
     */
    function consumeBadUrlToken(context, start) {
        consumeBadUrlRemnants(context);
        context.onToken(TokenType$1.BadUrl, start, context.offset);
    }
    /**
     * § 4.3.6. Consume a url token
     *
     * Consume a url token from a stream of code points. It returns either a <url-token> or a <bad-url-token>.
     *
     * @param context Reference to the tokenizer context instance
     * @param start Token start offset
     * @see {@link https://www.w3.org/TR/css-syntax-3/#consume-url-token}
     * @note This algorithm assumes that the initial "url(" has already been consumed. This algorithm also assumes that
     * it’s being called to consume an "unquoted" value, like url(foo). A quoted value, like url("foo"), is parsed as a
     * <function-token>. Consume an ident-like token automatically handles this distinction; this algorithm shouldn’t be
     * called directly otherwise.
     */
    const consumeUrlToken = (context, start) => {
        // Initially create a <url-token> with its value set to the empty string.
        // Consume as much whitespace as possible.
        while (isWhitespace$1(context.code)) {
            context.consumeCodePoint();
        }
        // Repeatedly consume the next input code point from the stream:
        // eslint-disable-next-line no-constant-condition
        while (context.offset <= context.length) {
            // TODO: Use switch-case here, but need to resolve non-printable code points first
            // U+0029 RIGHT PARENTHESIS ())
            if (context.code === 41 /* CodePoint.RightParenthesis */) {
                // Consume it.
                context.consumeCodePoint();
                // Return the <url-token>.
                context.onToken(TokenType$1.Url, start, context.offset);
                return;
            }
            // EOF
            if (context.isEof()) {
                // This is a parse error. Return the <url-token>.
                context.onToken(TokenType$1.Url, start, context.offset);
                context.onError("Unexpected end of file while parsing URL." /* ErrorMessage.UnexpectedEofInUrl */, start, context.offset);
                return;
            }
            // whitespace
            if (isWhitespace$1(context.code)) {
                // Consume as much whitespace as possible. If the next input code point is U+0029 RIGHT PARENTHESIS ())
                // or EOF, consume it and return the <url-token> (if EOF was encountered, this is a parse error);
                // otherwise, consume the remnants of a bad url, create a <bad-url-token>, and return it.
                while (isWhitespace$1(context.code)) {
                    context.consumeCodePoint();
                }
                if (context.code === 41 /* CodePoint.RightParenthesis */ || context.isEof()) {
                    context.consumeCodePoint();
                    context.onToken(TokenType$1.Url, start, context.offset);
                    context.onError("Unexpected end of file while parsing URL." /* ErrorMessage.UnexpectedEofInUrl */, start, context.offset);
                    return;
                }
                context.onError("Unexpected character in URL." /* ErrorMessage.UnexpectedCharInUrl */, start, context.offset);
                consumeBadUrlToken(context, start);
                return;
            }
            // U+0022 QUOTATION MARK (")
            // U+0027 APOSTROPHE (')
            // U+0028 LEFT PARENTHESIS (()
            // non-printable code point
            if (context.code === 34 /* CodePoint.QuotationMark */
                || context.code === 39 /* CodePoint.Apostrophe */
                || context.code === 40 /* CodePoint.LeftParenthesis */
                || isNonPrintableCodePoint(context.code)) {
                // This is a parse error. Consume the remnants of a bad url, create a <bad-url-token>, and return it.
                context.onError("Unexpected character in URL." /* ErrorMessage.UnexpectedCharInUrl */, start, context.offset);
                consumeBadUrlToken(context, start);
                return;
            }
            // U+005C REVERSE SOLIDUS (\)
            if (context.code === 92 /* CodePoint.ReverseSolidus */) {
                // If the stream starts with a valid escape, consume an escaped code point and append the returned code
                // point to the <url-token>’s value.
                if (checkForValidEscape(context.code, context.nextCode)) {
                    // Consume reversed solidus, then consume escaped code point
                    context.consumeCodePoint();
                    consumeEscapedCodePoint(context);
                    continue;
                }
                // Otherwise, this is a parse error. Consume the remnants of a bad url, create a <bad-url-token>, and
                // return it.
                context.onError("Unexpected character in URL." /* ErrorMessage.UnexpectedCharInUrl */, start, context.offset);
                consumeBadUrlToken(context, start);
                return;
            }
            // anything else
            // Append the current input code point to the <url-token>’s value.
            context.consumeCodePoint();
        }
    };

    /**
     * @file Tokenizing logic for ident-like tokens
     */
    const URL_FUNCTION_HASH = 193422222; // getStringHash('url')
    /**
     * § 4.3.4. Consume an ident-like token
     *
     * Consume an ident-like token from a stream of code points. It returns an <ident-token>, <function-token>, <url-token>,
     * or <bad-url-token>.
     *
     * @param context Reference to the tokenizer context instance
     * @see {@link https://www.w3.org/TR/css-syntax-3/#consume-an-ident-like-token}
     * @note We extended the algorithm to allow custom function handlers, but the tokenizer still strictly follows the spec.
     */
    const consumeIdentLikeToken = (context) => {
        // Consume an ident sequence, and let string be the result.
        const start = context.offset;
        consumeIndentSequence(context);
        // If the ident sequence is followed by U+0028 LEFT PARENTHESIS ((), consume it as a function:
        if (context.code === 40 /* CodePoint.LeftParenthesis */) {
            // First, store the function’s name hash
            const fnHash = context.getHashFrom(start);
            // Consume the opening parenthesis.
            context.consumeCodePoint();
            // URL
            if (fnHash === URL_FUNCTION_HASH) {
                // While the next two input code points are whitespace, consume the next input code point
                // If the next one or two input code points are U+0022 QUOTATION MARK ("), U+0027 APOSTROPHE ('), or
                // whitespace followed by U+0022 QUOTATION MARK (") or U+0027 APOSTROPHE ('), then create a <function-token>
                // with its value set to string and return it.
                // ! Different from the spec, but technically it is enough to check the next non-whitespace code point
                const nextNonWsCode = context.getNextNonWsCode();
                if (nextNonWsCode === 34 /* CodePoint.QuotationMark */ || nextNonWsCode === 39 /* CodePoint.Apostrophe */) {
                    context.onToken(TokenType$1.Function, start, context.offset);
                    return;
                }
                // Otherwise, consume a url token, and return it.
                consumeUrlToken(context, start);
                return;
            }
            // This is a good time to call custom function handlers, if any.
            // ! This is not part of the spec, but it's a good way to extend the tokenizer and if you didn't added any
            // ! custom function handler, it will not affect the tokenizer in any way, it still strictly follows the spec.
            // For performance reasons, we use `has` and `get` separately to avoid declaring a new variable every time here
            if (context.hasFunctionHandler(fnHash)) {
                // Return the <function-token>.
                context.onToken(TokenType$1.Function, start, context.offset);
                // Consume the function body
                // It's safe to call the handler directly because we already checked if it exists
                // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
                context.getFunctionHandler(fnHash)(context);
                return;
            }
            // Otherwise, if the next input code point is U+0028 LEFT PARENTHESIS ((), consume it. Create a <function-token>
            // with its value set to string and return it.
            context.onToken(TokenType$1.Function, start, context.offset);
            return;
        }
        // Otherwise, create an <ident-token> with its value set to string and return it.
        context.onToken(TokenType$1.Ident, start, context.offset);
    };

    /**
     * @file Tokenizing logic for numbers
     */
    /**
     * § 4.3.12. Consume a number
     *
     * Consume a number from a stream of code points. It returns a numeric value, and a type which is either "integer" or
     * "number".
     *
     * @param context Reference to the tokenizer context instance
     * @note This algorithm does not do the verification of the first few code points that are necessary to ensure a number
     * can be obtained from the stream. Ensure that the stream starts with a number before calling this algorithm.
     * @see {@link https://www.w3.org/TR/css-syntax-3/#consume-number}
     * @todo Uncomment type/repr handling if needed - currently we don't need them, and they're not used for performance
     * reasons
     */
    const consumeNumber = (context) => {
        // Execute the following steps in order:
        // 1. Initially set type to "integer". Let repr be the empty string.
        // TODO: Uncomment type/repr handling if needed
        // let type = NumberType.Integer;
        // const repr: string[] = [];
        // 2. If the next input code point is U+002B PLUS SIGN (+) or U+002D HYPHEN-MINUS (-), consume it and append it
        // to repr.
        if (context.code === 43 /* CodePoint.PlusSign */ || context.code === 45 /* CodePoint.HyphenMinus */) {
            context.consumeCodePoint();
            // TODO: Append to repr
        }
        // 3. While the next input code point is a digit, consume it and append it to repr.
        while (isDigit(context.code)) {
            context.consumeCodePoint();
            // TODO: Append to repr
        }
        // 4. If the next 2 input code points are U+002E FULL STOP (.) followed by a digit, then:
        if (context.code === 46 /* CodePoint.FullStop */ && isDigit(context.nextCode)) {
            // 1. Consume them.
            context.consumeCodePoint(2);
            // 2.Append them to repr
            // TODO: Append to repr
            // 3. Set type to "number".
            // type = NumberType.Number;
            // 4. While the next input code point is a digit, consume it and append it to repr.
            while (isDigit(context.code)) {
                context.consumeCodePoint();
                // TODO: Append to repr
            }
        }
        // 5. If the next 2 or 3 input code points are U+0045 LATIN CAPITAL LETTER E (E) or U+0065 LATIN SMALL LETTER E
        // (e) ...
        if ((context.code === 69 /* CodePoint.LatinCapitalLetterE */ || context.code === 101 /* CodePoint.LatinSmallLetterE */)) {
            // ... optionally followed by U+002D HYPHEN-MINUS (-) or U+002B PLUS SIGN (+)
            // Note: we split this into two if statements to avoid declaring a shift variable for the sign
            if ((context.nextCode === 45 /* CodePoint.HyphenMinus */ || context.nextCode === 43 /* CodePoint.PlusSign */)
                && isDigit(context.getRelativeCode(2))) {
                // 1. Consume them.
                context.consumeCodePoint(3); // e, sign, digit
                // 2. Append them to repr.
                // TODO: Append to repr
                // 3. Set type to "number".
                // TODO: Set type
                // 4. While the next input code point is a digit, consume it and append it to repr.
                while (isDigit(context.code)) {
                    context.consumeCodePoint();
                    // TODO: Append to repr
                }
            }
            else if (isDigit(context.nextCode)) {
                // ... followed by a digit, then:
                // 1. Consume them.
                context.consumeCodePoint(2); // e, digit
                // 2. Append them to repr.
                // TODO: Append to repr
                // 3. Set type to "number".
                // TODO: Set type
                // 4. While the next input code point is a digit, consume it and append it to repr.
                while (isDigit(context.code)) {
                    context.consumeCodePoint();
                    // TODO: Append to repr
                }
            }
        }
        // 6. Convert repr to a number, and set the value to the returned value.
        // TODO: Convert repr to a number
        // const value = Number(repr.join(''));
        // 7. Return value and type.
        // TODO: Uncomment type handling if needed
        // return [value, type];
    };

    /**
     * @file Tokenizing logic for numeric tokens
     */
    /**
     * § 4.3.3. Consume a numeric token
     *
     * Consume a numeric token from a stream of code points. It returns either a <number-token>, <percentage-token>, or
     * <dimension-token>.
     *
     * @param context Reference to the tokenizer context instance
     * @see {@link https://www.w3.org/TR/css-syntax-3/#consume-numeric-token}
     */
    const consumeNumericToken = (context) => {
        const start = context.offset;
        // Consume a number and let number be the result.
        consumeNumber(context);
        // If the next 3 input code points would start an ident sequence, then:
        if (checkForIdentStart(context.code, context.nextCode, context.getRelativeCode(2))) {
            // 1. Create a <dimension-token> with the same value and type flag as number, and a unit set initially to
            // the empty string.
            // 2. Consume an ident sequence. Set the <dimension-token>’s unit to the returned value.
            consumeIndentSequence(context);
            // 3. Return the <dimension-token>.
            context.onToken(TokenType$1.Dimension, start, context.offset);
            return;
        }
        // Otherwise, if the next input code point is U+0025 PERCENTAGE SIGN (%), consume it. Create a
        // <percentage-token> with the same value as number, and return it.
        if (context.code === 37 /* CodePoint.PercentageSign */) {
            context.consumeCodePoint();
            context.onToken(TokenType$1.Percentage, start, context.offset);
            return;
        }
        // Otherwise, create a <number-token> with the same value and type flag as number, and return it.
        context.onToken(TokenType$1.Number, start, context.offset);
    };

    /**
     * @file Tokenizing logic for strings
     */
    /**
     * § 4.3.5. Consume a string token
     *
     * Consume a string token from a stream of code points. It returns either a <string-token> or <bad-string-token>.
     *
     * @param context Reference to the tokenizer context instance
     * @see {@link https://www.w3.org/TR/css-syntax-3/#consume-string-token}
     */
    const consumeStringToken = (context) => {
        // This algorithm may be called with an ending code point, which denotes the code point that ends the string.
        // If an ending code point is not specified, the current input code point is used.
        const endingCodePoint = context.code;
        // Initially create a <string-token> with its value set to the empty string.
        const start = context.offset;
        // Consume opening character
        context.consumeCodePoint();
        // Repeatedly consume the next input code point from the stream:
        // eslint-disable-next-line no-constant-condition
        while (context.isLessThanEqualToEof()) {
            switch (context.code) {
                // ending code point
                case endingCodePoint:
                    // Consume it
                    context.consumeCodePoint();
                    // Return the <string-token>.
                    context.onToken(TokenType$1.String, start, context.offset);
                    return;
                // EOF
                case -1 /* ImaginaryCodePoint.Eof */:
                    // This is a parse error. Return the <string-token>.
                    context.onToken(TokenType$1.String, start, context.offset);
                    context.onError("Unexpected end of file while parsing string token." /* ErrorMessage.UnexpectedEofInString */, start, context.offset);
                    return;
                // newline
                case 13 /* CodePoint.CarriageReturn */:
                case 10 /* CodePoint.LineFeed */:
                case 12 /* CodePoint.FormFeed */:
                    // Special case: CRLF is 2 code points
                    if (context.code === 13 /* CodePoint.CarriageReturn */ && context.nextCode === 10 /* CodePoint.LineFeed */) {
                        // Do an extra consume
                        context.consumeCodePoint(1);
                    }
                    context.consumeCodePoint(1);
                    // This is a parse error. Reconsume the current input code point, create a <bad-string-token>, and
                    // return it.
                    context.onToken(TokenType$1.BadString, start, context.offset);
                    context.onError("Unexpected newline while parsing string token." /* ErrorMessage.UnexpectedNewlineInString */, start, context.offset);
                    return;
                // U+005C REVERSE SOLIDUS (\)
                case 92 /* CodePoint.ReverseSolidus */:
                    // If the next input code point is EOF, do nothing.
                    if (context.isNextEof()) {
                        context.consumeCodePoint();
                        context.onToken(TokenType$1.String, start, context.offset);
                        context.onError("Unexpected end of file while parsing string token." /* ErrorMessage.UnexpectedEofInString */, start, context.offset);
                        return;
                    }
                    // Otherwise, if the next input code point is a newline, consume it.
                    if (isNewline(context.nextCode)) {
                        context.consumeCodePoint(2);
                        break;
                    }
                    // Otherwise, (the stream starts with a valid escape) consume an escaped code point and append the
                    // returned code point to the <string-token>’s value.
                    if (checkForValidEscape(context.code, context.nextCode)) {
                        context.consumeCodePoint();
                        consumeEscapedCodePoint(context);
                    }
                    break;
                // anything else
                default:
                    // Append the current input code point to the <string-token>’s value.
                    context.consumeCodePoint();
            }
        }
    };

    /**
     * @file Tokenizing logic for whitespace
     */
    /**
     * § 4.3.1. Consume a token (whitespace)
     *
     * @see {@link https://www.w3.org/TR/css-syntax-3/#consume-token}
     * @param context Reference to the tokenizer context instance
     */
    const consumeWhitespaceToken = (context) => {
        // Consume as much whitespace as possible. Return a <whitespace-token>.
        const start = context.offset;
        context.consumeWhitespace();
        context.onToken(TokenType$1.Whitespace, start, context.offset);
    };

    /**
     * @file CSS tokenizer that strictly follows the CSS Syntax Module Level 3 specification
     *
     * @see {@link https://www.w3.org/TR/css-syntax-3/#tokenization}
     */
    /**
     * CSS tokenizer function
     *
     * @param source Source code to tokenize
     * @param onToken Tokenizer callback which is called for each token found in source code
     * @param onError Error callback which is called when a parsing error is found (optional)
     * @param functionHandlers Custom function handlers (optional)
     */
    const tokenize = (source, onToken, onError = () => { }, functionHandlers) => {
        // Create tokenizer context
        const context = new TokenizerContext(source, onToken, onError, functionHandlers);
        // Repeatedly consume the next input code point from the stream:
        while (!context.isEof()) {
            switch (context.code) {
                // According to the spec, these are all whitespace code points:
                case 9 /* CodePoint.CharacterTabulation */:
                case 32 /* CodePoint.Space */:
                case 10 /* CodePoint.LineFeed */:
                case 12 /* CodePoint.FormFeed */:
                case 13 /* CodePoint.CarriageReturn */:
                    // Consume as much whitespace as possible. Return a <whitespace-token>.
                    consumeWhitespaceToken(context);
                    break;
                // Digit
                case 48 /* CodePoint.DigitZero */:
                case 49 /* CodePoint.DigitOne */:
                case 50 /* CodePoint.DigitTwo */:
                case 51 /* CodePoint.DigitThree */:
                case 52 /* CodePoint.DigitFour */:
                case 53 /* CodePoint.DigitFive */:
                case 54 /* CodePoint.DigitSix */:
                case 55 /* CodePoint.DigitSeven */:
                case 56 /* CodePoint.DigitEight */:
                case 57 /* CodePoint.DigitNine */:
                    consumeNumericToken(context);
                    break;
                case 40 /* CodePoint.LeftParenthesis */:
                    context.consumeTrivialToken(TokenType$1.OpenParenthesis);
                    break;
                case 41 /* CodePoint.RightParenthesis */:
                    context.consumeTrivialToken(TokenType$1.CloseParenthesis);
                    break;
                case 44 /* CodePoint.Comma */:
                    context.consumeTrivialToken(TokenType$1.Comma);
                    break;
                case 58 /* CodePoint.Colon */:
                    context.consumeTrivialToken(TokenType$1.Colon);
                    break;
                case 59 /* CodePoint.SemiColon */:
                    context.consumeTrivialToken(TokenType$1.Semicolon);
                    break;
                case 91 /* CodePoint.LeftSquareBracket */:
                    context.consumeTrivialToken(TokenType$1.OpenSquareBracket);
                    break;
                case 93 /* CodePoint.RightSquareBracket */:
                    context.consumeTrivialToken(TokenType$1.CloseSquareBracket);
                    break;
                case 123 /* CodePoint.LeftCurlyBracket */:
                    context.consumeTrivialToken(TokenType$1.OpenCurlyBracket);
                    break;
                case 125 /* CodePoint.RightCurlyBracket */:
                    context.consumeTrivialToken(TokenType$1.CloseCurlyBracket);
                    break;
                case 39 /* CodePoint.Apostrophe */:
                case 34 /* CodePoint.QuotationMark */:
                    // Consume a string token and return it.
                    consumeStringToken(context);
                    break;
                case 35 /* CodePoint.NumberSign */:
                    // If the next input code point is an ident code point or the next two input code points are a
                    // valid escape, then:
                    if (isIdentCodePoint(context.getRelativeCode(1))
                        || checkForValidEscape(context.getRelativeCode(1), context.getRelativeCode(2))) {
                        const start = context.offset;
                        // 1. Create a <hash-token>.
                        // 2. If the next 3 input code points would start an ident sequence, set the <hash-token>’s
                        // type flag to "id".
                        // TODO: Uncomment when needed
                        // const props = {
                        //     typeFlag: checkForIdentStart(
                        //         context.getRelativeCode(1),
                        //         context.getRelativeCode(2),
                        //         context.getRelativeCode(3),
                        //     ) ? 'id' : 'unrestricted',
                        // };
                        // Consume an ident sequence, and set the <hash-token>’s value to the returned string.
                        context.consumeCodePoint();
                        consumeIndentSequence(context);
                        // 4. Return the <hash-token>.
                        // TODO: Uncomment when needed
                        // context.onToken(TokenType.Hash, start, context.offset, props);
                        context.onToken(TokenType$1.Hash, start, context.offset);
                        break;
                    }
                    // Otherwise, return a <delim-token> with its value set to the current input code point.
                    context.consumeTrivialToken(TokenType$1.Delim);
                    break;
                case 43 /* CodePoint.PlusSign */:
                    // If the input stream starts with a number, reconsume the current input code point, consume a
                    // numeric token, and return it.
                    if (checkForNumberStart(context.code, context.getRelativeCode(1), context.getRelativeCode(2))) {
                        consumeNumericToken(context);
                        break;
                    }
                    // Otherwise, return a <delim-token> with its value set to the current input code point.
                    context.consumeTrivialToken(TokenType$1.Delim);
                    break;
                case 45 /* CodePoint.HyphenMinus */:
                    // If the input stream starts with a number, reconsume the current input code point, consume a
                    // numeric token, and return it.
                    if (checkForNumberStart(context.code, context.getRelativeCode(1), context.getRelativeCode(2))) {
                        consumeNumericToken(context);
                        break;
                    }
                    // Otherwise, if the next 2 input code points are U+002D HYPHEN-MINUS U+003E GREATER-THAN SIGN
                    // (>), consume them and return a <CDC-token>.
                    if (context.getRelativeCode(1) === 45 /* CodePoint.HyphenMinus */
                        && context.getRelativeCode(2) === 62 /* CodePoint.GreaterThanSign */) {
                        context.consumeCodePoint(3);
                        context.onToken(TokenType$1.Cdc, context.offset - 3, context.offset);
                        break;
                    }
                    // Otherwise, if the input stream starts with an ident sequence, reconsume the current input
                    // code point, consume an ident-like token, and return it.
                    if (checkForIdentStart(context.code, context.getRelativeCode(1), context.getRelativeCode(2))) {
                        consumeIdentLikeToken(context);
                        break;
                    }
                    // Otherwise, return a <delim-token> with its value set to the current input code point.
                    context.consumeTrivialToken(TokenType$1.Delim);
                    break;
                case 46 /* CodePoint.FullStop */:
                    // If the input stream starts with a number, reconsume the current input code point, consume a
                    // numeric token, and return it.
                    if (checkForNumberStart(context.code, context.getRelativeCode(1), context.getRelativeCode(2))) {
                        consumeNumericToken(context);
                        break;
                    }
                    // Otherwise, return a <delim-token> with its value set to the current input code point.
                    context.consumeTrivialToken(TokenType$1.Delim);
                    break;
                case 60 /* CodePoint.LessThanSign */:
                    // If the next 3 input code points are U+0021 EXCLAMATION MARK U+002D HYPHEN-MINUS U+002D
                    // HYPHEN-MINUS (!--), consume them and return a <CDO-token>.
                    if (context.getRelativeCode(1) === 33 /* CodePoint.ExclamationMark */
                        && context.getRelativeCode(2) === 45 /* CodePoint.HyphenMinus */
                        && context.getRelativeCode(3) === 45 /* CodePoint.HyphenMinus */) {
                        context.consumeCodePoint(4);
                        context.onToken(TokenType$1.Cdo, context.offset - 4, context.offset);
                        break;
                    }
                    // Otherwise, return a <delim-token> with its value set to the current input code point.
                    context.consumeTrivialToken(TokenType$1.Delim);
                    break;
                case 64 /* CodePoint.CommercialAt */:
                    // If the next 3 input code points would start an ident sequence, consume an ident sequence,
                    // create an <at-keyword-token> with its value set to the returned value, and return it.
                    if (checkForIdentStart(context.getRelativeCode(1), context.getRelativeCode(2), context.getRelativeCode(3))) {
                        const start = context.offset;
                        // Consume commercial at character
                        context.consumeCodePoint();
                        // Consume ident sequence after commercial at character
                        consumeIndentSequence(context);
                        context.onToken(TokenType$1.AtKeyword, start, context.offset);
                        break;
                    }
                    // Otherwise, return a <delim-token> with its value set to the current input code point.
                    context.consumeTrivialToken(TokenType$1.Delim);
                    break;
                case 92 /* CodePoint.ReverseSolidus */:
                    // If the input stream starts with a valid escape, reconsume the current input code point,
                    // consume an ident-like token, and return it.
                    if (checkForValidEscape(context.code, context.getRelativeCode(1))) {
                        consumeIdentLikeToken(context);
                        break;
                    }
                    // Otherwise, this is a parse error. Return a <delim-token> with its value set to the current
                    // input code point.
                    context.consumeTrivialToken(TokenType$1.Delim);
                    context.onError("Invalid escape sequence." /* ErrorMessage.InvalidEscapeSequence */, context.offset - 1, context.offset);
                    break;
                case 47 /* CodePoint.Solidus */:
                    // If the next two input code point are U+002F SOLIDUS (/) followed by a U+002A ASTERISK (*),
                    // If the preceding paragraph ended by consuming an EOF code point, this is a parse error.
                    if (context.getRelativeCode(1) === 42 /* CodePoint.Asterisk */) {
                        const start = context.offset;
                        // Consume U+002F SOLIDUS (/) and U+002A ASTERISK (*)
                        context.consumeCodePoint(2);
                        // consume them and all following code points up to and including the first U+002A ASTERISK
                        // (*) followed by a U+002F SOLIDUS (/), or up to an EOF code point. Return to the start of
                        // this step.
                        context.consumeUntilCommentEnd();
                        if (context.isEof()) {
                            context.onError("Unterminated comment." /* ErrorMessage.UnterminatedComment */, start, context.length - 2);
                        }
                        context.onToken(TokenType$1.Comment, start, context.offset);
                        break;
                    }
                    // Otherwise, return a <delim-token> with its value set to the current input code point.
                    context.consumeTrivialToken(TokenType$1.Delim);
                    break;
                // anything else
                default:
                    // Can't be optimized because of the control threshold
                    if (isIdentStartCodePoint(context.code)) {
                        // Reconsume the current input code point, consume an ident-like token, and return it.
                        consumeIdentLikeToken(context);
                        break;
                    }
                    // Return a <delim-token> with its value set to the current input code point.
                    context.consumeTrivialToken(TokenType$1.Delim);
            }
        }
    };

    /**
     * @file Custom tokenizing logic for Extended CSS's pseudo-classes
     */
    /**
     * Generic handler for the Extended CSS's pseudo-classes
     *
     * @param context Reference to the tokenizer context instance
     */
    const handleRegularExtendedCssPseudo = (context) => {
        // Save the current offset, because we will need it later
        const start = context.offset;
        // Consume as much whitespace as possible
        context.consumeWhitespace();
        // If the first non-whitespace code point is an apostrophe or a quotation mark, it means that we are dealing
        // with a string parameter.
        // In this case, we simply abort the custom handler here, and let the standard tokenizer handle the string and
        // everything that comes after it as specified in the spec.
        // This behavior is similar to the standard CSS's url() function, it is also handled differently if its parameter
        // is a string.
        if (context.code === 39 /* CodePoint.Apostrophe */ || context.code === 34 /* CodePoint.QuotationMark */) {
            // Report whitespace tokens (if any)
            // It is important to report them, because we already consumed them - and the report is faster here than
            // a re-consume
            if (context.offset > start) {
                context.onToken(TokenType$1.Whitespace, start, context.offset);
            }
            // We simply abort the custom handler
            return;
        }
        // Otherwise, we need to find the closing parenthesis based on the parenthesis balance
        // Parenthesis balance: 1, because we start after the opening parenthesis:
        // :contains(param)
        //           ^ we starts from here, so we already have 1 open parenthesis
        let balance = 1;
        // Don't forget to report already consumed whitespace chars as delim-tokens (if any)
        // Note: we handle the parameter characters as delim-tokens, this is why we don't need to report them here
        // as whitespace-tokens
        for (let i = start; i < context.offset; i += 1) {
            context.onToken(TokenType$1.Delim, i, i + 1);
        }
        // Consume until we find the closing parenthesis or we reach the end of the source
        while (!context.isEof()) {
            if (context.code === 40 /* CodePoint.LeftParenthesis */ && context.prevCode !== 92 /* CodePoint.ReverseSolidus */) {
                // If we find an unescaped opening parenthesis, we increase the balance
                balance += 1;
            }
            else if (context.code === 41 /* CodePoint.RightParenthesis */ && context.prevCode !== 92 /* CodePoint.ReverseSolidus */) {
                // If we find an unescaped closing parenthesis, we decrease the balance
                balance -= 1;
                // If the balance is 0, it means that we found the closing parenthesis
                if (balance === 0) {
                    break;
                }
            }
            // Consume the current character as a delim-token
            context.consumeTrivialToken(TokenType$1.Delim);
        }
    };

    /**
     * @file Custom tokenizing logic for Extended CSS's `:xpath()` pseudo-class
     * @note `:xpath()` is a bit tricky, because it can contain unescaped parentheses inside strings in the XPath
     * expression.
     */
    /**
     * Handler for the Extended CSS's `:xpath()` pseudo-class
     *
     * @param context Reference to the tokenizer context instance
     */
    const handleXpathExtendedCssPseudo = (context) => {
        // Save the current offset, because we will need it later
        const start = context.offset;
        // Consume as much whitespace as possible
        context.consumeWhitespace();
        // If the first non-whitespace code point is an apostrophe or a quotation mark, it means that we are dealing
        // with a string parameter.
        // In this case, we simply abort the custom handler here, and let the standard tokenizer handle the string and
        // everything that comes after it as specified in the spec.
        // This behavior is similar to the standard CSS's url() function, it is also handled differently if its parameter
        // is a string.
        if (context.code === 39 /* CodePoint.Apostrophe */ || context.code === 34 /* CodePoint.QuotationMark */) {
            // Report whitespace tokens (if any)
            // It is important to report them, because we already consumed them - and the report is faster here than
            // a re-consume
            if (context.offset > start) {
                context.onToken(TokenType$1.Whitespace, start, context.offset);
            }
            // We simply abort the custom handler
            return;
        }
        // Otherwise, we need to find the closing parenthesis based on the parenthesis balance
        // Parenthesis balance: 1, because we start after the opening parenthesis:
        // :xpath(param)
        //        ^ we starts from here, so we already have 1 open parenthesis
        let balance = 1;
        // Don't forget to report already consumed whitespace chars as delim-tokens (if any)
        // Note: we handle the parameter characters as delim-tokens, this is why we don't need to report them here
        // as whitespace-tokens
        for (let i = start; i < context.offset; i += 1) {
            context.onToken(TokenType$1.Delim, i, i + 1);
        }
        // :xpath() is a bit tricky, because it can contain unescaped parentheses inside strings in the XPath expression,
        // like this:
        // :xpath(//div[@class="foo(bar)"])
        // but in this case, not required the whole XPath expression to be a string
        let inString = false;
        // Consume until we find the closing parenthesis or we reach the end of the source
        while (!context.isEof()) {
            // If we find an unescaped quote mark, we toggle the "inString" flag
            // It is important, because we should omit parentheses inside strings.
            if (context.code === 34 /* CodePoint.QuotationMark */ && context.prevCode !== 92 /* CodePoint.ReverseSolidus */) {
                inString = !inString;
            }
            // If we are not inside a string, we should check parentheses balance
            if (!inString) {
                if (context.code === 40 /* CodePoint.LeftParenthesis */ && context.prevCode !== 92 /* CodePoint.ReverseSolidus */) {
                    // If we find an unescaped opening parenthesis, we increase the balance
                    balance += 1;
                }
                else if (context.code === 41 /* CodePoint.RightParenthesis */ && context.prevCode !== 92 /* CodePoint.ReverseSolidus */) {
                    // If we find an unescaped closing parenthesis, we decrease the balance
                    balance -= 1;
                    // If the balance is 0, it means that we found the closing parenthesis of the
                    // pseudo-class
                    if (balance === 0) {
                        break;
                    }
                }
            }
            // Consume the current character as a delim-token
            context.consumeTrivialToken(TokenType$1.Delim);
        }
    };

    /**
     * @file Map utility functions
     */
    /**
     * Simple utility function to merge two maps.
     *
     * @param map1 First map
     * @param map2 Second map
     * @returns Merged map
     * @note If a key is present in both maps, the value from the second map will be used
     * @note This function does not modify the original maps, it returns a new map
     */
    function mergeMaps(map1, map2) {
        const result = new Map();
        for (const [key, value] of map1) {
            result.set(key, value);
        }
        for (const [key, value] of map2) {
            result.set(key, value);
        }
        return result;
    }

    /**
     * @file Extended CSS tokenizer that extends the core CSS tokenizer
     *
     * This library supports various Extended CSS language elements from
     * - AdGuard,
     * - uBlock Origin and
     * - Adblock Plus.
     *
     * @see {@link https://github.com/AdguardTeam/ExtendedCss}
     * @see {@link https://github.com/gorhill/uBlock/wiki/Procedural-cosmetic-filters}
     * @see {@link https://help.adblockplus.org/hc/en-us/articles/360062733293#elemhide-emulation}
     */
    const ABP_CONTAINS_HASH = 1989084725; // getStringHash('-abp-contains')
    const CONTAINS_HASH = 2399470598; // getStringHash('contains')
    const HAS_TEXT_HASH = 1221663855; // getStringHash('has-text')
    const MATCHES_CSS_HASH = 102304302; // getStringHash('matches-css')
    const MATCHES_CSS_AFTER_HASH = 2923888231; // getStringHash('matches-css-after')
    const MATCHES_CSS_BEFORE_HASH = 1739713050; // getStringHash('matches-css-before')
    const MATCHES_PROPERTY_HASH = 1860790666; // getStringHash('matches-property')
    const MATCHES_ATTR_HASH = 3376104318; // getStringHash('matches-attr')
    const XPATH_HASH = 196571984; // getStringHash('xpath')
    /**
     * Map of Extended CSS's pseudo-classes and their respective handler functions
     */
    const EXT_CSS_PSEUDO_HANDLERS = new Map([
        // Note: alternatively, you can use `getStringHash` to get the hash of the pseudo-class name, but we use
        // pre-calculated hashes here for performance reasons
        [ABP_CONTAINS_HASH, handleRegularExtendedCssPseudo],
        [CONTAINS_HASH, handleRegularExtendedCssPseudo],
        [HAS_TEXT_HASH, handleRegularExtendedCssPseudo],
        [MATCHES_CSS_HASH, handleRegularExtendedCssPseudo],
        [MATCHES_CSS_AFTER_HASH, handleRegularExtendedCssPseudo],
        [MATCHES_CSS_BEFORE_HASH, handleRegularExtendedCssPseudo],
        [MATCHES_PROPERTY_HASH, handleRegularExtendedCssPseudo],
        [MATCHES_ATTR_HASH, handleRegularExtendedCssPseudo],
        [XPATH_HASH, handleXpathExtendedCssPseudo],
    ]);
    /**
     * Extended CSS tokenizer function
     *
     * @param source Source code to tokenize
     * @param onToken Tokenizer callback which is called for each token found in source code
     * @param onError Error callback which is called when a parsing error is found (optional)
     * @param functionHandlers Custom function handlers (optional)
     * @note If you specify custom function handlers, they will be merged with the default function handlers. If you
     * duplicate a function handler, the custom one will be used instead of the default one, so you can override the default
     * function handlers this way, if you want to.
     */
    function tokenizeExtended(source, onToken, onError = () => { }, functionHandlers = new Map()) {
        tokenize(source, onToken, onError, 
        // Register custom function handlers for Extended CSS's pseudo-classes, but do not call mergeMaps if there are
        // no custom function handlers are provided
        functionHandlers.size > 0
            ? mergeMaps(EXT_CSS_PSEUDO_HANDLERS, functionHandlers)
            : EXT_CSS_PSEUDO_HANDLERS);
    }

    /**
     * Check if `vhost` is a valid suffix of `hostname` (top-domain)
     *
     * It means that `vhost` needs to be a suffix of `hostname` and we then need to
     * make sure that: either they are equal, or the character preceding `vhost` in
     * `hostname` is a '.' (it should not be a partial label).
     *
     * * hostname = 'not.evil.com' and vhost = 'vil.com'      => not ok
     * * hostname = 'not.evil.com' and vhost = 'evil.com'     => ok
     * * hostname = 'not.evil.com' and vhost = 'not.evil.com' => ok
     */
    function shareSameDomainSuffix(hostname, vhost) {
      if (hostname.endsWith(vhost)) {
        return hostname.length === vhost.length || hostname[hostname.length - vhost.length - 1] === '.';
      }
      return false;
    }
    /**
     * Given a hostname and its public suffix, extract the general domain.
     */
    function extractDomainWithSuffix(hostname, publicSuffix) {
      // Locate the index of the last '.' in the part of the `hostname` preceding
      // the public suffix.
      //
      // examples:
      //   1. not.evil.co.uk  => evil.co.uk
      //         ^    ^
      //         |    | start of public suffix
      //         | index of the last dot
      //
      //   2. example.co.uk   => example.co.uk
      //     ^       ^
      //     |       | start of public suffix
      //     |
      //     | (-1) no dot found before the public suffix
      var publicSuffixIndex = hostname.length - publicSuffix.length - 2;
      var lastDotBeforeSuffixIndex = hostname.lastIndexOf('.', publicSuffixIndex);
      // No '.' found, then `hostname` is the general domain (no sub-domain)
      if (lastDotBeforeSuffixIndex === -1) {
        return hostname;
      }
      // Extract the part between the last '.'
      return hostname.slice(lastDotBeforeSuffixIndex + 1);
    }
    /**
     * Detects the domain based on rules and upon and a host string
     */
    function getDomain$1(suffix, hostname, options) {
      // Check if `hostname` ends with a member of `validHosts`.
      if (options.validHosts !== null) {
        var validHosts = options.validHosts;
        for (var i = 0; i < validHosts.length; i += 1) {
          var vhost = validHosts[i];
          if ( /*@__INLINE__*/shareSameDomainSuffix(hostname, vhost) === true) {
            return vhost;
          }
        }
      }
      // If `hostname` is a valid public suffix, then there is no domain to return.
      // Since we already know that `getPublicSuffix` returns a suffix of `hostname`
      // there is no need to perform a string comparison and we only compare the
      // size.
      if (suffix.length === hostname.length) {
        return null;
      }
      // To extract the general domain, we start by identifying the public suffix
      // (if any), then consider the domain to be the public suffix with one added
      // level of depth. (e.g.: if hostname is `not.evil.co.uk` and public suffix:
      // `co.uk`, then we take one more level: `evil`, giving the final result:
      // `evil.co.uk`).
      return (/*@__INLINE__*/extractDomainWithSuffix(hostname, suffix)
      );
    }

    /**
     * Return the part of domain without suffix.
     *
     * Example: for domain 'foo.com', the result would be 'foo'.
     */
    function getDomainWithoutSuffix(domain, suffix) {
      // Note: here `domain` and `suffix` cannot have the same length because in
      // this case we set `domain` to `null` instead. It is thus safe to assume
      // that `suffix` is shorter than `domain`.
      return domain.slice(0, -suffix.length - 1);
    }

    /**
     * @param url - URL we want to extract a hostname from.
     * @param urlIsValidHostname - hint from caller; true if `url` is already a valid hostname.
     */
    function extractHostname(url, urlIsValidHostname) {
      var start = 0;
      var end = url.length;
      var hasUpper = false;
      // If url is not already a valid hostname, then try to extract hostname.
      if (urlIsValidHostname === false) {
        // Special handling of data URLs
        if (url.startsWith('data:') === true) {
          return null;
        }
        // Trim leading spaces
        while (start < url.length && url.charCodeAt(start) <= 32) {
          start += 1;
        }
        // Trim trailing spaces
        while (end > start + 1 && url.charCodeAt(end - 1) <= 32) {
          end -= 1;
        }
        // Skip scheme.
        if (url.charCodeAt(start) === 47 /* '/' */ && url.charCodeAt(start + 1) === 47 /* '/' */) {
          start += 2;
        } else {
          var indexOfProtocol = url.indexOf(':/', start);
          if (indexOfProtocol !== -1) {
            // Implement fast-path for common protocols. We expect most protocols
            // should be one of these 4 and thus we will not need to perform the
            // more expansive validity check most of the time.
            var protocolSize = indexOfProtocol - start;
            var c0 = url.charCodeAt(start);
            var c1 = url.charCodeAt(start + 1);
            var c2 = url.charCodeAt(start + 2);
            var c3 = url.charCodeAt(start + 3);
            var c4 = url.charCodeAt(start + 4);
            if (protocolSize === 5 && c0 === 104 /* 'h' */ && c1 === 116 /* 't' */ && c2 === 116 /* 't' */ && c3 === 112 /* 'p' */ && c4 === 115 /* 's' */) ; else if (protocolSize === 4 && c0 === 104 /* 'h' */ && c1 === 116 /* 't' */ && c2 === 116 /* 't' */ && c3 === 112 /* 'p' */) ; else if (protocolSize === 3 && c0 === 119 /* 'w' */ && c1 === 115 /* 's' */ && c2 === 115 /* 's' */) ; else if (protocolSize === 2 && c0 === 119 /* 'w' */ && c1 === 115 /* 's' */) ; else {
              // Check that scheme is valid
              for (var i = start; i < indexOfProtocol; i += 1) {
                var lowerCaseCode = url.charCodeAt(i) | 32;
                if ((lowerCaseCode >= 97 && lowerCaseCode <= 122 ||
                // [a, z]
                lowerCaseCode >= 48 && lowerCaseCode <= 57 ||
                // [0, 9]
                lowerCaseCode === 46 ||
                // '.'
                lowerCaseCode === 45 ||
                // '-'
                lowerCaseCode === 43) === false // '+'
                ) {
                  return null;
                }
              }
            }
            // Skip 0, 1 or more '/' after ':/'
            start = indexOfProtocol + 2;
            while (url.charCodeAt(start) === 47 /* '/' */) {
              start += 1;
            }
          }
        }
        // Detect first occurrence of '/', '?' or '#'. We also keep track of the
        // last occurrence of '@', ']' or ':' to speed-up subsequent parsing of
        // (respectively), identifier, ipv6 or port.
        var indexOfIdentifier = -1;
        var indexOfClosingBracket = -1;
        var indexOfPort = -1;
        for (var _i = start; _i < end; _i += 1) {
          var code = url.charCodeAt(_i);
          if (code === 35 ||
          // '#'
          code === 47 ||
          // '/'
          code === 63 // '?'
          ) {
            end = _i;
            break;
          } else if (code === 64) {
            // '@'
            indexOfIdentifier = _i;
          } else if (code === 93) {
            // ']'
            indexOfClosingBracket = _i;
          } else if (code === 58) {
            // ':'
            indexOfPort = _i;
          } else if (code >= 65 && code <= 90) {
            hasUpper = true;
          }
        }
        // Detect identifier: '@'
        if (indexOfIdentifier !== -1 && indexOfIdentifier > start && indexOfIdentifier < end) {
          start = indexOfIdentifier + 1;
        }
        // Handle ipv6 addresses
        if (url.charCodeAt(start) === 91 /* '[' */) {
          if (indexOfClosingBracket !== -1) {
            return url.slice(start + 1, indexOfClosingBracket).toLowerCase();
          }
          return null;
        } else if (indexOfPort !== -1 && indexOfPort > start && indexOfPort < end) {
          // Detect port: ':'
          end = indexOfPort;
        }
      }
      // Trim trailing dots
      while (end > start + 1 && url.charCodeAt(end - 1) === 46 /* '.' */) {
        end -= 1;
      }
      var hostname = start !== 0 || end !== url.length ? url.slice(start, end) : url;
      if (hasUpper) {
        return hostname.toLowerCase();
      }
      return hostname;
    }

    /**
     * Check if a hostname is an IP. You should be aware that this only works
     * because `hostname` is already garanteed to be a valid hostname!
     */
    function isProbablyIpv4(hostname) {
      // Cannot be shorted than 1.1.1.1
      if (hostname.length < 7) {
        return false;
      }
      // Cannot be longer than: 255.255.255.255
      if (hostname.length > 15) {
        return false;
      }
      var numberOfDots = 0;
      for (var i = 0; i < hostname.length; i += 1) {
        var code = hostname.charCodeAt(i);
        if (code === 46 /* '.' */) {
          numberOfDots += 1;
        } else if (code < 48 /* '0' */ || code > 57 /* '9' */) {
          return false;
        }
      }
      return numberOfDots === 3 && hostname.charCodeAt(0) !== 46 /* '.' */ && hostname.charCodeAt(hostname.length - 1) !== 46 /* '.' */;
    }
    /**
     * Similar to isProbablyIpv4.
     */
    function isProbablyIpv6(hostname) {
      if (hostname.length < 3) {
        return false;
      }
      var start = hostname[0] === '[' ? 1 : 0;
      var end = hostname.length;
      if (hostname[end - 1] === ']') {
        end -= 1;
      }
      // We only consider the maximum size of a normal IPV6. Note that this will
      // fail on so-called "IPv4 mapped IPv6 addresses" but this is a corner-case
      // and a proper validation library should be used for these.
      if (end - start > 39) {
        return false;
      }
      var hasColon = false;
      for (; start < end; start += 1) {
        var code = hostname.charCodeAt(start);
        if (code === 58 /* ':' */) {
          hasColon = true;
        } else if ((code >= 48 && code <= 57 ||
        // 0-9
        code >= 97 && code <= 102 ||
        // a-f
        code >= 65 && code <= 90) ===
        // A-F
        false) {
          return false;
        }
      }
      return hasColon;
    }
    /**
     * Check if `hostname` is *probably* a valid ip addr (either ipv6 or ipv4).
     * This *will not* work on any string. We need `hostname` to be a valid
     * hostname.
     */
    function isIp$2(hostname) {
      return isProbablyIpv6(hostname) || isProbablyIpv4(hostname);
    }

    /**
     * Implements fast shallow verification of hostnames. This does not perform a
     * struct check on the content of labels (classes of Unicode characters, etc.)
     * but instead check that the structure is valid (number of labels, length of
     * labels, etc.).
     *
     * If you need stricter validation, consider using an external library.
     */
    function isValidAscii(code) {
      return code >= 97 && code <= 122 || code >= 48 && code <= 57 || code > 127;
    }
    /**
     * Check if a hostname string is valid. It's usually a preliminary check before
     * trying to use getDomain or anything else.
     *
     * Beware: it does not check if the TLD exists.
     */
    function isValidHostname (hostname) {
      if (hostname.length > 255) {
        return false;
      }
      if (hostname.length === 0) {
        return false;
      }
      if ( /*@__INLINE__*/isValidAscii(hostname.charCodeAt(0)) === false) {
        return false;
      }
      // Validate hostname according to RFC
      var lastDotIndex = -1;
      var lastCharCode = -1;
      var len = hostname.length;
      for (var i = 0; i < len; i += 1) {
        var code = hostname.charCodeAt(i);
        if (code === 46 /* '.' */) {
          if (
          // Check that previous label is < 63 bytes long (64 = 63 + '.')
          i - lastDotIndex > 64 ||
          // Check that previous character was not already a '.'
          lastCharCode === 46 ||
          // Check that the previous label does not end with a '-' (dash)
          lastCharCode === 45 ||
          // Check that the previous label does not end with a '_' (underscore)
          lastCharCode === 95) {
            return false;
          }
          lastDotIndex = i;
        } else if (( /*@__INLINE__*/isValidAscii(code) || code === 45 || code === 95) === false) {
          // Check if there is a forbidden character in the label
          return false;
        }
        lastCharCode = code;
      }
      return (
        // Check that last label is shorter than 63 chars
        len - lastDotIndex - 1 <= 63 &&
        // Check that the last character is an allowed trailing label character.
        // Since we already checked that the char is a valid hostname character,
        // we only need to check that it's different from '-'.
        lastCharCode !== 45
      );
    }

    function setDefaultsImpl(_ref) {
      var _ref$allowIcannDomain = _ref.allowIcannDomains,
        allowIcannDomains = _ref$allowIcannDomain === void 0 ? true : _ref$allowIcannDomain,
        _ref$allowPrivateDoma = _ref.allowPrivateDomains,
        allowPrivateDomains = _ref$allowPrivateDoma === void 0 ? false : _ref$allowPrivateDoma,
        _ref$detectIp = _ref.detectIp,
        detectIp = _ref$detectIp === void 0 ? true : _ref$detectIp,
        _ref$extractHostname = _ref.extractHostname,
        extractHostname = _ref$extractHostname === void 0 ? true : _ref$extractHostname,
        _ref$mixedInputs = _ref.mixedInputs,
        mixedInputs = _ref$mixedInputs === void 0 ? true : _ref$mixedInputs,
        _ref$validHosts = _ref.validHosts,
        validHosts = _ref$validHosts === void 0 ? null : _ref$validHosts,
        _ref$validateHostname = _ref.validateHostname,
        validateHostname = _ref$validateHostname === void 0 ? true : _ref$validateHostname;
      return {
        allowIcannDomains,
        allowPrivateDomains,
        detectIp,
        extractHostname,
        mixedInputs,
        validHosts,
        validateHostname
      };
    }
    var DEFAULT_OPTIONS = /*@__INLINE__*/setDefaultsImpl({});
    function setDefaults(options) {
      if (options === undefined) {
        return DEFAULT_OPTIONS;
      }
      return (/*@__INLINE__*/setDefaultsImpl(options)
      );
    }

    /**
     * Returns the subdomain of a hostname string
     */
    function getSubdomain(hostname, domain) {
      // If `hostname` and `domain` are the same, then there is no sub-domain
      if (domain.length === hostname.length) {
        return '';
      }
      return hostname.slice(0, -domain.length - 1);
    }

    /**
     * Implement a factory allowing to plug different implementations of suffix
     * lookup (e.g.: using a trie or the packed hashes datastructures). This is used
     * and exposed in `tldts.ts` and `tldts-experimental.ts` bundle entrypoints.
     */
    function getEmptyResult() {
      return {
        domain: null,
        domainWithoutSuffix: null,
        hostname: null,
        isIcann: null,
        isIp: null,
        isPrivate: null,
        publicSuffix: null,
        subdomain: null
      };
    }
    function resetResult(result) {
      result.domain = null;
      result.domainWithoutSuffix = null;
      result.hostname = null;
      result.isIcann = null;
      result.isIp = null;
      result.isPrivate = null;
      result.publicSuffix = null;
      result.subdomain = null;
    }
    function parseImpl(url, step, suffixLookup, partialOptions, result) {
      var options = /*@__INLINE__*/setDefaults(partialOptions);
      // Very fast approximate check to make sure `url` is a string. This is needed
      // because the library will not necessarily be used in a typed setup and
      // values of arbitrary types might be given as argument.
      if (typeof url !== 'string') {
        return result;
      }
      // Extract hostname from `url` only if needed. This can be made optional
      // using `options.extractHostname`. This option will typically be used
      // whenever we are sure the inputs to `parse` are already hostnames and not
      // arbitrary URLs.
      //
      // `mixedInput` allows to specify if we expect a mix of URLs and hostnames
      // as input. If only hostnames are expected then `extractHostname` can be
      // set to `false` to speed-up parsing. If only URLs are expected then
      // `mixedInputs` can be set to `false`. The `mixedInputs` is only a hint
      // and will not change the behavior of the library.
      if (options.extractHostname === false) {
        result.hostname = url;
      } else if (options.mixedInputs === true) {
        result.hostname = extractHostname(url, isValidHostname(url));
      } else {
        result.hostname = extractHostname(url, false);
      }
      if (step === 0 /* FLAG.HOSTNAME */ || result.hostname === null) {
        return result;
      }
      // Check if `hostname` is a valid ip address
      if (options.detectIp === true) {
        result.isIp = isIp$2(result.hostname);
        if (result.isIp === true) {
          return result;
        }
      }
      // Perform optional hostname validation. If hostname is not valid, no need to
      // go further as there will be no valid domain or sub-domain.
      if (options.validateHostname === true && options.extractHostname === true && isValidHostname(result.hostname) === false) {
        result.hostname = null;
        return result;
      }
      // Extract public suffix
      suffixLookup(result.hostname, options, result);
      if (step === 2 /* FLAG.PUBLIC_SUFFIX */ || result.publicSuffix === null) {
        return result;
      }
      // Extract domain
      result.domain = getDomain$1(result.publicSuffix, result.hostname, options);
      if (step === 3 /* FLAG.DOMAIN */ || result.domain === null) {
        return result;
      }
      // Extract subdomain
      result.subdomain = getSubdomain(result.hostname, result.domain);
      if (step === 4 /* FLAG.SUB_DOMAIN */) {
        return result;
      }
      // Extract domain without suffix
      result.domainWithoutSuffix = getDomainWithoutSuffix(result.domain, result.publicSuffix);
      return result;
    }

    function fastPathLookup (hostname, options, out) {
      // Fast path for very popular suffixes; this allows to by-pass lookup
      // completely as well as any extra allocation or string manipulation.
      if (options.allowPrivateDomains === false && hostname.length > 3) {
        var last = hostname.length - 1;
        var c3 = hostname.charCodeAt(last);
        var c2 = hostname.charCodeAt(last - 1);
        var c1 = hostname.charCodeAt(last - 2);
        var c0 = hostname.charCodeAt(last - 3);
        if (c3 === 109 /* 'm' */ && c2 === 111 /* 'o' */ && c1 === 99 /* 'c' */ && c0 === 46 /* '.' */) {
          out.isIcann = true;
          out.isPrivate = false;
          out.publicSuffix = 'com';
          return true;
        } else if (c3 === 103 /* 'g' */ && c2 === 114 /* 'r' */ && c1 === 111 /* 'o' */ && c0 === 46 /* '.' */) {
          out.isIcann = true;
          out.isPrivate = false;
          out.publicSuffix = 'org';
          return true;
        } else if (c3 === 117 /* 'u' */ && c2 === 100 /* 'd' */ && c1 === 101 /* 'e' */ && c0 === 46 /* '.' */) {
          out.isIcann = true;
          out.isPrivate = false;
          out.publicSuffix = 'edu';
          return true;
        } else if (c3 === 118 /* 'v' */ && c2 === 111 /* 'o' */ && c1 === 103 /* 'g' */ && c0 === 46 /* '.' */) {
          out.isIcann = true;
          out.isPrivate = false;
          out.publicSuffix = 'gov';
          return true;
        } else if (c3 === 116 /* 't' */ && c2 === 101 /* 'e' */ && c1 === 110 /* 'n' */ && c0 === 46 /* '.' */) {
          out.isIcann = true;
          out.isPrivate = false;
          out.publicSuffix = 'net';
          return true;
        } else if (c3 === 101 /* 'e' */ && c2 === 100 /* 'd' */ && c1 === 46 /* '.' */) {
          out.isIcann = true;
          out.isPrivate = false;
          out.publicSuffix = 'de';
          return true;
        }
      }
      return false;
    }

    var exceptions = function () {
      var _0 = {
          "$": 1,
          "succ": {}
        },
        _1 = {
          "$": 0,
          "succ": {
            "city": _0
          }
        };
      var exceptions = {
        "$": 0,
        "succ": {
          "ck": {
            "$": 0,
            "succ": {
              "www": _0
            }
          },
          "jp": {
            "$": 0,
            "succ": {
              "kawasaki": _1,
              "kitakyushu": _1,
              "kobe": _1,
              "nagoya": _1,
              "sapporo": _1,
              "sendai": _1,
              "yokohama": _1
            }
          }
        }
      };
      return exceptions;
    }();
    var rules = function () {
      var _2 = {
          "$": 1,
          "succ": {}
        },
        _3 = {
          "$": 2,
          "succ": {}
        },
        _4 = {
          "$": 1,
          "succ": {
            "gov": _2,
            "com": _2,
            "org": _2,
            "net": _2,
            "edu": _2
          }
        },
        _5 = {
          "$": 0,
          "succ": {
            "*": _3
          }
        },
        _6 = {
          "$": 1,
          "succ": {
            "blogspot": _3
          }
        },
        _7 = {
          "$": 1,
          "succ": {
            "gov": _2
          }
        },
        _8 = {
          "$": 0,
          "succ": {
            "*": _2
          }
        },
        _9 = {
          "$": 0,
          "succ": {
            "cloud": _3
          }
        },
        _10 = {
          "$": 1,
          "succ": {
            "co": _3
          }
        },
        _11 = {
          "$": 2,
          "succ": {
            "nodes": _3
          }
        },
        _12 = {
          "$": 0,
          "succ": {
            "s3": _3
          }
        },
        _13 = {
          "$": 0,
          "succ": {
            "direct": _3
          }
        },
        _14 = {
          "$": 2,
          "succ": {
            "id": _3
          }
        },
        _15 = {
          "$": 0,
          "succ": {
            "vfs": _3,
            "webview-assets": _3
          }
        },
        _16 = {
          "$": 0,
          "succ": {
            "cloud9": _15
          }
        },
        _17 = {
          "$": 0,
          "succ": {
            "dualstack": _12,
            "cloud9": _15
          }
        },
        _18 = {
          "$": 0,
          "succ": {
            "dualstack": _12,
            "s3": _3,
            "s3-website": _3,
            "cloud9": _15
          }
        },
        _19 = {
          "$": 0,
          "succ": {
            "apps": _3
          }
        },
        _20 = {
          "$": 0,
          "succ": {
            "paas": _3
          }
        },
        _21 = {
          "$": 0,
          "succ": {
            "app": _3
          }
        },
        _22 = {
          "$": 2,
          "succ": {
            "eu": _3
          }
        },
        _23 = {
          "$": 0,
          "succ": {
            "site": _3
          }
        },
        _24 = {
          "$": 0,
          "succ": {
            "pages": _3
          }
        },
        _25 = {
          "$": 1,
          "succ": {
            "com": _2,
            "edu": _2,
            "net": _2,
            "org": _2
          }
        },
        _26 = {
          "$": 0,
          "succ": {
            "j": _3
          }
        },
        _27 = {
          "$": 0,
          "succ": {
            "jelastic": _3
          }
        },
        _28 = {
          "$": 0,
          "succ": {
            "user": _3
          }
        },
        _29 = {
          "$": 1,
          "succ": {
            "ybo": _3
          }
        },
        _30 = {
          "$": 0,
          "succ": {
            "cust": _3,
            "reservd": _3
          }
        },
        _31 = {
          "$": 0,
          "succ": {
            "cust": _3
          }
        },
        _32 = {
          "$": 1,
          "succ": {
            "gov": _2,
            "edu": _2,
            "mil": _2,
            "com": _2,
            "org": _2,
            "net": _2
          }
        },
        _33 = {
          "$": 1,
          "succ": {
            "edu": _2,
            "biz": _2,
            "net": _2,
            "org": _2,
            "gov": _2,
            "info": _2,
            "com": _2
          }
        },
        _34 = {
          "$": 1,
          "succ": {
            "gov": _2,
            "blogspot": _3
          }
        },
        _35 = {
          "$": 1,
          "succ": {
            "framer": _3
          }
        },
        _36 = {
          "$": 1,
          "succ": {
            "barsy": _3
          }
        },
        _37 = {
          "$": 0,
          "succ": {
            "forgot": _3
          }
        },
        _38 = {
          "$": 1,
          "succ": {
            "gs": _2
          }
        },
        _39 = {
          "$": 0,
          "succ": {
            "nes": _2
          }
        },
        _40 = {
          "$": 1,
          "succ": {
            "k12": _2,
            "cc": _2,
            "lib": _2
          }
        },
        _41 = {
          "$": 1,
          "succ": {
            "cc": _2,
            "lib": _2
          }
        };
      var rules = {
        "$": 0,
        "succ": {
          "ac": {
            "$": 1,
            "succ": {
              "com": _2,
              "edu": _2,
              "gov": _2,
              "net": _2,
              "mil": _2,
              "org": _2,
              "drr": _3
            }
          },
          "ad": {
            "$": 1,
            "succ": {
              "nom": _2
            }
          },
          "ae": {
            "$": 1,
            "succ": {
              "co": _2,
              "net": _2,
              "org": _2,
              "sch": _2,
              "ac": _2,
              "gov": _2,
              "mil": _2,
              "blogspot": _3
            }
          },
          "aero": {
            "$": 1,
            "succ": {
              "accident-investigation": _2,
              "accident-prevention": _2,
              "aerobatic": _2,
              "aeroclub": _2,
              "aerodrome": _2,
              "agents": _2,
              "aircraft": _2,
              "airline": _2,
              "airport": _2,
              "air-surveillance": _2,
              "airtraffic": _2,
              "air-traffic-control": _2,
              "ambulance": _2,
              "amusement": _2,
              "association": _2,
              "author": _2,
              "ballooning": _2,
              "broker": _2,
              "caa": _2,
              "cargo": _2,
              "catering": _2,
              "certification": _2,
              "championship": _2,
              "charter": _2,
              "civilaviation": _2,
              "club": _2,
              "conference": _2,
              "consultant": _2,
              "consulting": _2,
              "control": _2,
              "council": _2,
              "crew": _2,
              "design": _2,
              "dgca": _2,
              "educator": _2,
              "emergency": _2,
              "engine": _2,
              "engineer": _2,
              "entertainment": _2,
              "equipment": _2,
              "exchange": _2,
              "express": _2,
              "federation": _2,
              "flight": _2,
              "fuel": _2,
              "gliding": _2,
              "government": _2,
              "groundhandling": _2,
              "group": _2,
              "hanggliding": _2,
              "homebuilt": _2,
              "insurance": _2,
              "journal": _2,
              "journalist": _2,
              "leasing": _2,
              "logistics": _2,
              "magazine": _2,
              "maintenance": _2,
              "media": _2,
              "microlight": _2,
              "modelling": _2,
              "navigation": _2,
              "parachuting": _2,
              "paragliding": _2,
              "passenger-association": _2,
              "pilot": _2,
              "press": _2,
              "production": _2,
              "recreation": _2,
              "repbody": _2,
              "res": _2,
              "research": _2,
              "rotorcraft": _2,
              "safety": _2,
              "scientist": _2,
              "services": _2,
              "show": _2,
              "skydiving": _2,
              "software": _2,
              "student": _2,
              "trader": _2,
              "trading": _2,
              "trainer": _2,
              "union": _2,
              "workinggroup": _2,
              "works": _2
            }
          },
          "af": _4,
          "ag": {
            "$": 1,
            "succ": {
              "com": _2,
              "org": _2,
              "net": _2,
              "co": _2,
              "nom": _2
            }
          },
          "ai": {
            "$": 1,
            "succ": {
              "off": _2,
              "com": _2,
              "net": _2,
              "org": _2,
              "uwu": _3
            }
          },
          "al": {
            "$": 1,
            "succ": {
              "com": _2,
              "edu": _2,
              "gov": _2,
              "mil": _2,
              "net": _2,
              "org": _2,
              "blogspot": _3
            }
          },
          "am": {
            "$": 1,
            "succ": {
              "co": _2,
              "com": _2,
              "commune": _2,
              "net": _2,
              "org": _2,
              "radio": _3,
              "blogspot": _3,
              "neko": _3,
              "nyaa": _3
            }
          },
          "ao": {
            "$": 1,
            "succ": {
              "ed": _2,
              "gv": _2,
              "og": _2,
              "co": _2,
              "pb": _2,
              "it": _2
            }
          },
          "aq": _2,
          "ar": {
            "$": 1,
            "succ": {
              "bet": _2,
              "com": _6,
              "coop": _2,
              "edu": _2,
              "gob": _2,
              "gov": _2,
              "int": _2,
              "mil": _2,
              "musica": _2,
              "mutual": _2,
              "net": _2,
              "org": _2,
              "senasa": _2,
              "tur": _2
            }
          },
          "arpa": {
            "$": 1,
            "succ": {
              "e164": _2,
              "in-addr": _2,
              "ip6": _2,
              "iris": _2,
              "uri": _2,
              "urn": _2
            }
          },
          "as": _7,
          "asia": {
            "$": 1,
            "succ": {
              "cloudns": _3
            }
          },
          "at": {
            "$": 1,
            "succ": {
              "ac": {
                "$": 1,
                "succ": {
                  "sth": _2
                }
              },
              "co": _6,
              "gv": _2,
              "or": _2,
              "funkfeuer": {
                "$": 0,
                "succ": {
                  "wien": _3
                }
              },
              "futurecms": {
                "$": 0,
                "succ": {
                  "*": _3,
                  "ex": _5,
                  "in": _5
                }
              },
              "futurehosting": _3,
              "futuremailing": _3,
              "ortsinfo": {
                "$": 0,
                "succ": {
                  "ex": _5,
                  "kunden": _5
                }
              },
              "biz": _3,
              "info": _3,
              "123webseite": _3,
              "priv": _3,
              "myspreadshop": _3,
              "12hp": _3,
              "2ix": _3,
              "4lima": _3,
              "lima-city": _3
            }
          },
          "au": {
            "$": 1,
            "succ": {
              "com": {
                "$": 1,
                "succ": {
                  "blogspot": _3,
                  "cloudlets": {
                    "$": 0,
                    "succ": {
                      "mel": _3
                    }
                  },
                  "myspreadshop": _3
                }
              },
              "net": _2,
              "org": _2,
              "edu": {
                "$": 1,
                "succ": {
                  "act": _2,
                  "catholic": _2,
                  "nsw": {
                    "$": 1,
                    "succ": {
                      "schools": _2
                    }
                  },
                  "nt": _2,
                  "qld": _2,
                  "sa": _2,
                  "tas": _2,
                  "vic": _2,
                  "wa": _2
                }
              },
              "gov": {
                "$": 1,
                "succ": {
                  "qld": _2,
                  "sa": _2,
                  "tas": _2,
                  "vic": _2,
                  "wa": _2
                }
              },
              "asn": _2,
              "id": _2,
              "info": _2,
              "conf": _2,
              "oz": _2,
              "act": _2,
              "nsw": _2,
              "nt": _2,
              "qld": _2,
              "sa": _2,
              "tas": _2,
              "vic": _2,
              "wa": _2
            }
          },
          "aw": {
            "$": 1,
            "succ": {
              "com": _2
            }
          },
          "ax": {
            "$": 1,
            "succ": {
              "be": _3,
              "cat": _3,
              "es": _3,
              "eu": _3,
              "gg": _3,
              "mc": _3,
              "us": _3,
              "xy": _3
            }
          },
          "az": {
            "$": 1,
            "succ": {
              "com": _2,
              "net": _2,
              "int": _2,
              "gov": _2,
              "org": _2,
              "edu": _2,
              "info": _2,
              "pp": _2,
              "mil": _2,
              "name": _2,
              "pro": _2,
              "biz": _2
            }
          },
          "ba": {
            "$": 1,
            "succ": {
              "com": _2,
              "edu": _2,
              "gov": _2,
              "mil": _2,
              "net": _2,
              "org": _2,
              "rs": _3,
              "blogspot": _3
            }
          },
          "bb": {
            "$": 1,
            "succ": {
              "biz": _2,
              "co": _2,
              "com": _2,
              "edu": _2,
              "gov": _2,
              "info": _2,
              "net": _2,
              "org": _2,
              "store": _2,
              "tv": _2
            }
          },
          "bd": _8,
          "be": {
            "$": 1,
            "succ": {
              "ac": _2,
              "webhosting": _3,
              "blogspot": _3,
              "interhostsolutions": _9,
              "kuleuven": {
                "$": 0,
                "succ": {
                  "ezproxy": _3
                }
              },
              "123website": _3,
              "myspreadshop": _3,
              "transurl": _5
            }
          },
          "bf": _7,
          "bg": {
            "$": 1,
            "succ": {
              "0": _2,
              "1": _2,
              "2": _2,
              "3": _2,
              "4": _2,
              "5": _2,
              "6": _2,
              "7": _2,
              "8": _2,
              "9": _2,
              "a": _2,
              "b": _2,
              "c": _2,
              "d": _2,
              "e": _2,
              "f": _2,
              "g": _2,
              "h": _2,
              "i": _2,
              "j": _2,
              "k": _2,
              "l": _2,
              "m": _2,
              "n": _2,
              "o": _2,
              "p": _2,
              "q": _2,
              "r": _2,
              "s": _2,
              "t": _2,
              "u": _2,
              "v": _2,
              "w": _2,
              "x": _2,
              "y": _2,
              "z": _2,
              "blogspot": _3,
              "barsy": _3
            }
          },
          "bh": _4,
          "bi": {
            "$": 1,
            "succ": {
              "co": _2,
              "com": _2,
              "edu": _2,
              "or": _2,
              "org": _2
            }
          },
          "biz": {
            "$": 1,
            "succ": {
              "activetrail": _3,
              "cloudns": _3,
              "jozi": _3,
              "dyndns": _3,
              "for-better": _3,
              "for-more": _3,
              "for-some": _3,
              "for-the": _3,
              "selfip": _3,
              "webhop": _3,
              "orx": _3,
              "mmafan": _3,
              "myftp": _3,
              "no-ip": _3,
              "dscloud": _3
            }
          },
          "bj": {
            "$": 1,
            "succ": {
              "africa": _2,
              "agro": _2,
              "architectes": _2,
              "assur": _2,
              "avocats": _2,
              "co": _2,
              "com": _2,
              "eco": _2,
              "econo": _2,
              "edu": _2,
              "info": _2,
              "loisirs": _2,
              "money": _2,
              "net": _2,
              "org": _2,
              "ote": _2,
              "resto": _2,
              "restaurant": _2,
              "tourism": _2,
              "univ": _2,
              "blogspot": _3
            }
          },
          "bm": _4,
          "bn": {
            "$": 1,
            "succ": {
              "com": _2,
              "edu": _2,
              "gov": _2,
              "net": _2,
              "org": _2,
              "co": _3
            }
          },
          "bo": {
            "$": 1,
            "succ": {
              "com": _2,
              "edu": _2,
              "gob": _2,
              "int": _2,
              "org": _2,
              "net": _2,
              "mil": _2,
              "tv": _2,
              "web": _2,
              "academia": _2,
              "agro": _2,
              "arte": _2,
              "blog": _2,
              "bolivia": _2,
              "ciencia": _2,
              "cooperativa": _2,
              "democracia": _2,
              "deporte": _2,
              "ecologia": _2,
              "economia": _2,
              "empresa": _2,
              "indigena": _2,
              "industria": _2,
              "info": _2,
              "medicina": _2,
              "movimiento": _2,
              "musica": _2,
              "natural": _2,
              "nombre": _2,
              "noticias": _2,
              "patria": _2,
              "politica": _2,
              "profesional": _2,
              "plurinacional": _2,
              "pueblo": _2,
              "revista": _2,
              "salud": _2,
              "tecnologia": _2,
              "tksat": _2,
              "transporte": _2,
              "wiki": _2
            }
          },
          "br": {
            "$": 1,
            "succ": {
              "9guacu": _2,
              "abc": _2,
              "adm": _2,
              "adv": _2,
              "agr": _2,
              "aju": _2,
              "am": _2,
              "anani": _2,
              "aparecida": _2,
              "app": _2,
              "arq": _2,
              "art": _2,
              "ato": _2,
              "b": _2,
              "barueri": _2,
              "belem": _2,
              "bhz": _2,
              "bib": _2,
              "bio": _2,
              "blog": _2,
              "bmd": _2,
              "boavista": _2,
              "bsb": _2,
              "campinagrande": _2,
              "campinas": _2,
              "caxias": _2,
              "cim": _2,
              "cng": _2,
              "cnt": _2,
              "com": {
                "$": 1,
                "succ": {
                  "blogspot": _3,
                  "virtualcloud": {
                    "$": 0,
                    "succ": {
                      "scale": {
                        "$": 0,
                        "succ": {
                          "users": _3
                        }
                      }
                    }
                  },
                  "simplesite": _3
                }
              },
              "contagem": _2,
              "coop": _2,
              "coz": _2,
              "cri": _2,
              "cuiaba": _2,
              "curitiba": _2,
              "def": _2,
              "des": _2,
              "det": _2,
              "dev": _2,
              "ecn": _2,
              "eco": _2,
              "edu": _2,
              "emp": _2,
              "enf": _2,
              "eng": _2,
              "esp": _2,
              "etc": _2,
              "eti": _2,
              "far": _2,
              "feira": _2,
              "flog": _2,
              "floripa": _2,
              "fm": _2,
              "fnd": _2,
              "fortal": _2,
              "fot": _2,
              "foz": _2,
              "fst": _2,
              "g12": _2,
              "geo": _2,
              "ggf": _2,
              "goiania": _2,
              "gov": {
                "$": 1,
                "succ": {
                  "ac": _2,
                  "al": _2,
                  "am": _2,
                  "ap": _2,
                  "ba": _2,
                  "ce": _2,
                  "df": _2,
                  "es": _2,
                  "go": _2,
                  "ma": _2,
                  "mg": _2,
                  "ms": _2,
                  "mt": _2,
                  "pa": _2,
                  "pb": _2,
                  "pe": _2,
                  "pi": _2,
                  "pr": _2,
                  "rj": _2,
                  "rn": _2,
                  "ro": _2,
                  "rr": _2,
                  "rs": _2,
                  "sc": _2,
                  "se": _2,
                  "sp": _2,
                  "to": _2
                }
              },
              "gru": _2,
              "imb": _2,
              "ind": _2,
              "inf": _2,
              "jab": _2,
              "jampa": _2,
              "jdf": _2,
              "joinville": _2,
              "jor": _2,
              "jus": _2,
              "leg": {
                "$": 1,
                "succ": {
                  "ac": _3,
                  "al": _3,
                  "am": _3,
                  "ap": _3,
                  "ba": _3,
                  "ce": _3,
                  "df": _3,
                  "es": _3,
                  "go": _3,
                  "ma": _3,
                  "mg": _3,
                  "ms": _3,
                  "mt": _3,
                  "pa": _3,
                  "pb": _3,
                  "pe": _3,
                  "pi": _3,
                  "pr": _3,
                  "rj": _3,
                  "rn": _3,
                  "ro": _3,
                  "rr": _3,
                  "rs": _3,
                  "sc": _3,
                  "se": _3,
                  "sp": _3,
                  "to": _3
                }
              },
              "lel": _2,
              "log": _2,
              "londrina": _2,
              "macapa": _2,
              "maceio": _2,
              "manaus": _2,
              "maringa": _2,
              "mat": _2,
              "med": _2,
              "mil": _2,
              "morena": _2,
              "mp": _2,
              "mus": _2,
              "natal": _2,
              "net": _2,
              "niteroi": _2,
              "nom": _8,
              "not": _2,
              "ntr": _2,
              "odo": _2,
              "ong": _2,
              "org": _2,
              "osasco": _2,
              "palmas": _2,
              "poa": _2,
              "ppg": _2,
              "pro": _2,
              "psc": _2,
              "psi": _2,
              "pvh": _2,
              "qsl": _2,
              "radio": _2,
              "rec": _2,
              "recife": _2,
              "rep": _2,
              "ribeirao": _2,
              "rio": _2,
              "riobranco": _2,
              "riopreto": _2,
              "salvador": _2,
              "sampa": _2,
              "santamaria": _2,
              "santoandre": _2,
              "saobernardo": _2,
              "saogonca": _2,
              "seg": _2,
              "sjc": _2,
              "slg": _2,
              "slz": _2,
              "sorocaba": _2,
              "srv": _2,
              "taxi": _2,
              "tc": _2,
              "tec": _2,
              "teo": _2,
              "the": _2,
              "tmp": _2,
              "trd": _2,
              "tur": _2,
              "tv": _2,
              "udi": _2,
              "vet": _2,
              "vix": _2,
              "vlog": _2,
              "wiki": _2,
              "zlg": _2
            }
          },
          "bs": {
            "$": 1,
            "succ": {
              "com": _2,
              "net": _2,
              "org": _2,
              "edu": _2,
              "gov": _2,
              "we": _3
            }
          },
          "bt": _4,
          "bv": _2,
          "bw": {
            "$": 1,
            "succ": {
              "co": _2,
              "org": _2
            }
          },
          "by": {
            "$": 1,
            "succ": {
              "gov": _2,
              "mil": _2,
              "com": _6,
              "of": _2,
              "mycloud": _3,
              "mediatech": _3
            }
          },
          "bz": {
            "$": 1,
            "succ": {
              "com": _2,
              "net": _2,
              "org": _2,
              "edu": _2,
              "gov": _2,
              "za": _3,
              "gsj": _3
            }
          },
          "ca": {
            "$": 1,
            "succ": {
              "ab": _2,
              "bc": _2,
              "mb": _2,
              "nb": _2,
              "nf": _2,
              "nl": _2,
              "ns": _2,
              "nt": _2,
              "nu": _2,
              "on": _2,
              "pe": _2,
              "qc": _2,
              "sk": _2,
              "yk": _2,
              "gc": _2,
              "barsy": _3,
              "awdev": _5,
              "co": _3,
              "blogspot": _3,
              "no-ip": _3,
              "myspreadshop": _3
            }
          },
          "cat": _2,
          "cc": {
            "$": 1,
            "succ": {
              "cloudns": _3,
              "ftpaccess": _3,
              "game-server": _3,
              "myphotos": _3,
              "scrapping": _3,
              "twmail": _3,
              "csx": _3,
              "fantasyleague": _3,
              "spawn": {
                "$": 0,
                "succ": {
                  "instances": _3
                }
              }
            }
          },
          "cd": _7,
          "cf": _6,
          "cg": _2,
          "ch": {
            "$": 1,
            "succ": {
              "square7": _3,
              "blogspot": _3,
              "flow": {
                "$": 0,
                "succ": {
                  "ae": {
                    "$": 0,
                    "succ": {
                      "alp1": _3
                    }
                  },
                  "appengine": _3
                }
              },
              "linkyard-cloud": _3,
              "dnsking": _3,
              "gotdns": _3,
              "123website": _3,
              "myspreadshop": _3,
              "firenet": {
                "$": 0,
                "succ": {
                  "*": _3,
                  "svc": _5
                }
              },
              "12hp": _3,
              "2ix": _3,
              "4lima": _3,
              "lima-city": _3
            }
          },
          "ci": {
            "$": 1,
            "succ": {
              "org": _2,
              "or": _2,
              "com": _2,
              "co": _2,
              "edu": _2,
              "ed": _2,
              "ac": _2,
              "net": _2,
              "go": _2,
              "asso": _2,
              "xn--aroport-bya": _2,
              "aéroport": _2,
              "int": _2,
              "presse": _2,
              "md": _2,
              "gouv": _2,
              "fin": _3,
              "nl": _3
            }
          },
          "ck": _8,
          "cl": {
            "$": 1,
            "succ": {
              "co": _2,
              "gob": _2,
              "gov": _2,
              "mil": _2,
              "blogspot": _3
            }
          },
          "cm": {
            "$": 1,
            "succ": {
              "co": _2,
              "com": _2,
              "gov": _2,
              "net": _2
            }
          },
          "cn": {
            "$": 1,
            "succ": {
              "ac": _2,
              "com": {
                "$": 1,
                "succ": {
                  "amazonaws": {
                    "$": 0,
                    "succ": {
                      "compute": _5,
                      "cn-north-1": _12,
                      "eb": {
                        "$": 0,
                        "succ": {
                          "cn-north-1": _3,
                          "cn-northwest-1": _3
                        }
                      },
                      "elb": _5
                    }
                  }
                }
              },
              "edu": _2,
              "gov": _2,
              "net": _2,
              "org": _2,
              "mil": _2,
              "xn--55qx5d": _2,
              "公司": _2,
              "xn--io0a7i": _2,
              "网络": _2,
              "xn--od0alg": _2,
              "網絡": _2,
              "ah": _2,
              "bj": _2,
              "cq": _2,
              "fj": _2,
              "gd": _2,
              "gs": _2,
              "gz": _2,
              "gx": _2,
              "ha": _2,
              "hb": _2,
              "he": _2,
              "hi": _2,
              "hl": _2,
              "hn": _2,
              "jl": _2,
              "js": _2,
              "jx": _2,
              "ln": _2,
              "nm": _2,
              "nx": _2,
              "qh": _2,
              "sc": _2,
              "sd": _2,
              "sh": _2,
              "sn": _2,
              "sx": _2,
              "tj": _2,
              "xj": _2,
              "xz": _2,
              "yn": _2,
              "zj": _2,
              "hk": _2,
              "mo": _2,
              "tw": _2,
              "canva-apps": _3,
              "instantcloud": _3,
              "quickconnect": _13
            }
          },
          "co": {
            "$": 1,
            "succ": {
              "arts": _2,
              "com": _6,
              "edu": _2,
              "firm": _2,
              "gov": _2,
              "info": _2,
              "int": _2,
              "mil": _2,
              "net": _2,
              "nom": _2,
              "org": _2,
              "rec": _2,
              "web": _2,
              "carrd": _3,
              "crd": _3,
              "otap": _5,
              "leadpages": _3,
              "lpages": _3,
              "mypi": _3,
              "n4t": _3,
              "firewalledreplit": _14,
              "repl": _14,
              "supabase": _3
            }
          },
          "com": {
            "$": 1,
            "succ": {
              "devcdnaccesso": _5,
              "adobeaemcloud": {
                "$": 2,
                "succ": {
                  "dev": _5
                }
              },
              "airkitapps": _3,
              "airkitapps-au": _3,
              "aivencloud": _3,
              "kasserver": _3,
              "amazonaws": {
                "$": 0,
                "succ": {
                  "compute": _5,
                  "compute-1": _5,
                  "us-east-1": {
                    "$": 2,
                    "succ": {
                      "dualstack": _12,
                      "cloud9": _15
                    }
                  },
                  "ap-northeast-1": _17,
                  "ap-northeast-2": _18,
                  "ap-south-1": _18,
                  "ap-southeast-1": _17,
                  "ap-southeast-2": _17,
                  "ca-central-1": _18,
                  "eu-central-1": _18,
                  "eu-west-1": _17,
                  "eu-west-2": _18,
                  "eu-west-3": _18,
                  "s3": _3,
                  "s3-ap-northeast-1": _3,
                  "s3-ap-northeast-2": _3,
                  "s3-ap-south-1": _3,
                  "s3-ap-southeast-1": _3,
                  "s3-ap-southeast-2": _3,
                  "s3-ca-central-1": _3,
                  "s3-eu-central-1": _3,
                  "s3-eu-west-1": _3,
                  "s3-eu-west-2": _3,
                  "s3-eu-west-3": _3,
                  "s3-external-1": _3,
                  "s3-fips-us-gov-west-1": _3,
                  "s3-sa-east-1": _3,
                  "s3-us-east-2": _3,
                  "s3-us-gov-west-1": _3,
                  "s3-us-west-1": _3,
                  "s3-us-west-2": _3,
                  "s3-website-ap-northeast-1": _3,
                  "s3-website-ap-southeast-1": _3,
                  "s3-website-ap-southeast-2": _3,
                  "s3-website-eu-west-1": _3,
                  "s3-website-sa-east-1": _3,
                  "s3-website-us-east-1": _3,
                  "s3-website-us-west-1": _3,
                  "s3-website-us-west-2": _3,
                  "sa-east-1": _17,
                  "us-east-2": _18,
                  "af-south-1": _16,
                  "ap-east-1": _16,
                  "ap-northeast-3": _16,
                  "eu-north-1": _16,
                  "eu-south-1": _16,
                  "me-south-1": _16,
                  "us-west-1": _16,
                  "us-west-2": _16,
                  "elb": _5
                }
              },
              "elasticbeanstalk": {
                "$": 2,
                "succ": {
                  "ap-northeast-1": _3,
                  "ap-northeast-2": _3,
                  "ap-northeast-3": _3,
                  "ap-south-1": _3,
                  "ap-southeast-1": _3,
                  "ap-southeast-2": _3,
                  "ca-central-1": _3,
                  "eu-central-1": _3,
                  "eu-west-1": _3,
                  "eu-west-2": _3,
                  "eu-west-3": _3,
                  "sa-east-1": _3,
                  "us-east-1": _3,
                  "us-east-2": _3,
                  "us-gov-west-1": _3,
                  "us-west-1": _3,
                  "us-west-2": _3
                }
              },
              "awsglobalaccelerator": _3,
              "siiites": _3,
              "appspacehosted": _3,
              "appspaceusercontent": _3,
              "on-aptible": _3,
              "myasustor": _3,
              "balena-devices": _3,
              "betainabox": _3,
              "boutir": _3,
              "bplaced": _3,
              "cafjs": _3,
              "canva-apps": _3,
              "br": _3,
              "cn": _3,
              "de": _3,
              "eu": _3,
              "jpn": _3,
              "mex": _3,
              "ru": _3,
              "sa": _3,
              "uk": _3,
              "us": _3,
              "za": _3,
              "ar": _3,
              "hu": _3,
              "kr": _3,
              "no": _3,
              "qc": _3,
              "uy": _3,
              "africa": _3,
              "gr": _3,
              "co": _3,
              "jdevcloud": _3,
              "wpdevcloud": _3,
              "cloudcontrolled": _3,
              "cloudcontrolapp": _3,
              "cf-ipfs": _3,
              "cloudflare-ipfs": _3,
              "trycloudflare": _3,
              "customer-oci": {
                "$": 0,
                "succ": {
                  "*": _3,
                  "oci": _5,
                  "ocp": _5,
                  "ocs": _5
                }
              },
              "dattolocal": _3,
              "dattorelay": _3,
              "dattoweb": _3,
              "mydatto": _3,
              "builtwithdark": _3,
              "datadetect": {
                "$": 0,
                "succ": {
                  "demo": _3,
                  "instance": _3
                }
              },
              "ddns5": _3,
              "discordsays": _3,
              "discordsez": _3,
              "drayddns": _3,
              "dreamhosters": _3,
              "mydrobo": _3,
              "dyndns-at-home": _3,
              "dyndns-at-work": _3,
              "dyndns-blog": _3,
              "dyndns-free": _3,
              "dyndns-home": _3,
              "dyndns-ip": _3,
              "dyndns-mail": _3,
              "dyndns-office": _3,
              "dyndns-pics": _3,
              "dyndns-remote": _3,
              "dyndns-server": _3,
              "dyndns-web": _3,
              "dyndns-wiki": _3,
              "dyndns-work": _3,
              "blogdns": _3,
              "cechire": _3,
              "dnsalias": _3,
              "dnsdojo": _3,
              "doesntexist": _3,
              "dontexist": _3,
              "doomdns": _3,
              "dyn-o-saur": _3,
              "dynalias": _3,
              "est-a-la-maison": _3,
              "est-a-la-masion": _3,
              "est-le-patron": _3,
              "est-mon-blogueur": _3,
              "from-ak": _3,
              "from-al": _3,
              "from-ar": _3,
              "from-ca": _3,
              "from-ct": _3,
              "from-dc": _3,
              "from-de": _3,
              "from-fl": _3,
              "from-ga": _3,
              "from-hi": _3,
              "from-ia": _3,
              "from-id": _3,
              "from-il": _3,
              "from-in": _3,
              "from-ks": _3,
              "from-ky": _3,
              "from-ma": _3,
              "from-md": _3,
              "from-mi": _3,
              "from-mn": _3,
              "from-mo": _3,
              "from-ms": _3,
              "from-mt": _3,
              "from-nc": _3,
              "from-nd": _3,
              "from-ne": _3,
              "from-nh": _3,
              "from-nj": _3,
              "from-nm": _3,
              "from-nv": _3,
              "from-oh": _3,
              "from-ok": _3,
              "from-or": _3,
              "from-pa": _3,
              "from-pr": _3,
              "from-ri": _3,
              "from-sc": _3,
              "from-sd": _3,
              "from-tn": _3,
              "from-tx": _3,
              "from-ut": _3,
              "from-va": _3,
              "from-vt": _3,
              "from-wa": _3,
              "from-wi": _3,
              "from-wv": _3,
              "from-wy": _3,
              "getmyip": _3,
              "gotdns": _3,
              "hobby-site": _3,
              "homelinux": _3,
              "homeunix": _3,
              "iamallama": _3,
              "is-a-anarchist": _3,
              "is-a-blogger": _3,
              "is-a-bookkeeper": _3,
              "is-a-bulls-fan": _3,
              "is-a-caterer": _3,
              "is-a-chef": _3,
              "is-a-conservative": _3,
              "is-a-cpa": _3,
              "is-a-cubicle-slave": _3,
              "is-a-democrat": _3,
              "is-a-designer": _3,
              "is-a-doctor": _3,
              "is-a-financialadvisor": _3,
              "is-a-geek": _3,
              "is-a-green": _3,
              "is-a-guru": _3,
              "is-a-hard-worker": _3,
              "is-a-hunter": _3,
              "is-a-landscaper": _3,
              "is-a-lawyer": _3,
              "is-a-liberal": _3,
              "is-a-libertarian": _3,
              "is-a-llama": _3,
              "is-a-musician": _3,
              "is-a-nascarfan": _3,
              "is-a-nurse": _3,
              "is-a-painter": _3,
              "is-a-personaltrainer": _3,
              "is-a-photographer": _3,
              "is-a-player": _3,
              "is-a-republican": _3,
              "is-a-rockstar": _3,
              "is-a-socialist": _3,
              "is-a-student": _3,
              "is-a-teacher": _3,
              "is-a-techie": _3,
              "is-a-therapist": _3,
              "is-an-accountant": _3,
              "is-an-actor": _3,
              "is-an-actress": _3,
              "is-an-anarchist": _3,
              "is-an-artist": _3,
              "is-an-engineer": _3,
              "is-an-entertainer": _3,
              "is-certified": _3,
              "is-gone": _3,
              "is-into-anime": _3,
              "is-into-cars": _3,
              "is-into-cartoons": _3,
              "is-into-games": _3,
              "is-leet": _3,
              "is-not-certified": _3,
              "is-slick": _3,
              "is-uberleet": _3,
              "is-with-theband": _3,
              "isa-geek": _3,
              "isa-hockeynut": _3,
              "issmarterthanyou": _3,
              "likes-pie": _3,
              "likescandy": _3,
              "neat-url": _3,
              "saves-the-whales": _3,
              "selfip": _3,
              "sells-for-less": _3,
              "sells-for-u": _3,
              "servebbs": _3,
              "simple-url": _3,
              "space-to-rent": _3,
              "teaches-yoga": _3,
              "writesthisblog": _3,
              "digitaloceanspaces": _5,
              "ddnsfree": _3,
              "ddnsgeek": _3,
              "giize": _3,
              "gleeze": _3,
              "kozow": _3,
              "loseyourip": _3,
              "ooguy": _3,
              "theworkpc": _3,
              "mytuleap": _3,
              "tuleap-partners": _3,
              "encoreapi": _3,
              "evennode": {
                "$": 0,
                "succ": {
                  "eu-1": _3,
                  "eu-2": _3,
                  "eu-3": _3,
                  "eu-4": _3,
                  "us-1": _3,
                  "us-2": _3,
                  "us-3": _3,
                  "us-4": _3
                }
              },
              "onfabrica": _3,
              "fbsbx": _19,
              "fastly-edge": _3,
              "fastly-terrarium": _3,
              "fastvps-server": _3,
              "mydobiss": _3,
              "firebaseapp": _3,
              "fldrv": _3,
              "forgeblocks": _3,
              "framercanvas": _3,
              "freebox-os": _3,
              "freeboxos": _3,
              "freemyip": _3,
              "gentapps": _3,
              "gentlentapis": _3,
              "githubusercontent": _3,
              "0emm": _5,
              "appspot": {
                "$": 2,
                "succ": {
                  "r": _5
                }
              },
              "codespot": _3,
              "googleapis": _3,
              "googlecode": _3,
              "pagespeedmobilizer": _3,
              "publishproxy": _3,
              "withgoogle": _3,
              "withyoutube": _3,
              "blogspot": _3,
              "awsmppl": _3,
              "herokuapp": _3,
              "herokussl": _3,
              "impertrixcdn": _3,
              "impertrix": _3,
              "smushcdn": _3,
              "wphostedmail": _3,
              "wpmucdn": _3,
              "pixolino": _3,
              "amscompute": _3,
              "clicketcloud": _3,
              "dopaas": _3,
              "hidora": _3,
              "hosted-by-previder": _20,
              "hosteur": {
                "$": 0,
                "succ": {
                  "rag-cloud": _3,
                  "rag-cloud-ch": _3
                }
              },
              "ik-server": {
                "$": 0,
                "succ": {
                  "jcloud": _3,
                  "jcloud-ver-jpc": _3
                }
              },
              "jelastic": {
                "$": 0,
                "succ": {
                  "demo": _3
                }
              },
              "kilatiron": _3,
              "massivegrid": _20,
              "wafaicloud": {
                "$": 0,
                "succ": {
                  "jed": _3,
                  "lon": _3,
                  "ryd": _3
                }
              },
              "joyent": {
                "$": 0,
                "succ": {
                  "cns": _5
                }
              },
              "ktistory": _3,
              "lpusercontent": _3,
              "lmpm": _21,
              "linode": {
                "$": 0,
                "succ": {
                  "members": _3,
                  "nodebalancer": _5
                }
              },
              "linodeobjects": _5,
              "linodeusercontent": {
                "$": 0,
                "succ": {
                  "ip": _3
                }
              },
              "barsycenter": _3,
              "barsyonline": _3,
              "mazeplay": _3,
              "miniserver": _3,
              "meteorapp": _22,
              "hostedpi": _3,
              "mythic-beasts": {
                "$": 0,
                "succ": {
                  "customer": _3,
                  "caracal": _3,
                  "fentiger": _3,
                  "lynx": _3,
                  "ocelot": _3,
                  "oncilla": _3,
                  "onza": _3,
                  "sphinx": _3,
                  "vs": _3,
                  "x": _3,
                  "yali": _3
                }
              },
              "nospamproxy": _9,
              "4u": _3,
              "nfshost": _3,
              "001www": _3,
              "ddnslive": _3,
              "myiphost": _3,
              "blogsyte": _3,
              "ciscofreak": _3,
              "damnserver": _3,
              "ditchyourip": _3,
              "dnsiskinky": _3,
              "dynns": _3,
              "geekgalaxy": _3,
              "health-carereform": _3,
              "homesecuritymac": _3,
              "homesecuritypc": _3,
              "myactivedirectory": _3,
              "mysecuritycamera": _3,
              "net-freaks": _3,
              "onthewifi": _3,
              "point2this": _3,
              "quicksytes": _3,
              "securitytactics": _3,
              "serveexchange": _3,
              "servehumour": _3,
              "servep2p": _3,
              "servesarcasm": _3,
              "stufftoread": _3,
              "unusualperson": _3,
              "workisboring": _3,
              "3utilities": _3,
              "ddnsking": _3,
              "myvnc": _3,
              "servebeer": _3,
              "servecounterstrike": _3,
              "serveftp": _3,
              "servegame": _3,
              "servehalflife": _3,
              "servehttp": _3,
              "serveirc": _3,
              "servemp3": _3,
              "servepics": _3,
              "servequake": _3,
              "observableusercontent": {
                "$": 0,
                "succ": {
                  "static": _3
                }
              },
              "simplesite": _3,
              "orsites": _3,
              "operaunite": _3,
              "authgear-staging": _3,
              "authgearapps": _3,
              "skygearapp": _3,
              "outsystemscloud": _3,
              "ownprovider": _3,
              "pgfog": _3,
              "pagefrontapp": _3,
              "pagexl": _3,
              "paywhirl": _5,
              "gotpantheon": _3,
              "platter-app": _3,
              "pleskns": _3,
              "postman-echo": _3,
              "prgmr": {
                "$": 0,
                "succ": {
                  "xen": _3
                }
              },
              "pythonanywhere": _22,
              "qualifioapp": _3,
              "qbuser": _3,
              "qa2": _3,
              "dev-myqnapcloud": _3,
              "alpha-myqnapcloud": _3,
              "myqnapcloud": _3,
              "quipelements": _5,
              "rackmaze": _3,
              "rhcloud": _3,
              "render": _21,
              "onrender": _3,
              "180r": _3,
              "dojin": _3,
              "sakuratan": _3,
              "sakuraweb": _3,
              "x0": _3,
              "code": {
                "$": 0,
                "succ": {
                  "builder": _5,
                  "dev-builder": _5,
                  "stg-builder": _5
                }
              },
              "logoip": _3,
              "scrysec": _3,
              "firewall-gateway": _3,
              "myshopblocks": _3,
              "myshopify": _3,
              "shopitsite": _3,
              "1kapp": _3,
              "appchizi": _3,
              "applinzi": _3,
              "sinaapp": _3,
              "vipsinaapp": _3,
              "bounty-full": {
                "$": 2,
                "succ": {
                  "alpha": _3,
                  "beta": _3
                }
              },
              "streamlitapp": _3,
              "try-snowplow": _3,
              "stackhero-network": _3,
              "playstation-cloud": _3,
              "myspreadshop": _3,
              "stdlib": {
                "$": 0,
                "succ": {
                  "api": _3
                }
              },
              "temp-dns": _3,
              "dsmynas": _3,
              "familyds": _3,
              "mytabit": _3,
              "tb-hosting": _23,
              "reservd": _3,
              "thingdustdata": _3,
              "bloxcms": _3,
              "townnews-staging": _3,
              "typeform": {
                "$": 0,
                "succ": {
                  "pro": _3
                }
              },
              "hk": _3,
              "it": _3,
              "vultrobjects": _5,
              "wafflecell": _3,
              "reserve-online": _3,
              "hotelwithflight": _3,
              "remotewd": _3,
              "wiardweb": _24,
              "messwithdns": _3,
              "woltlab-demo": _3,
              "wpenginepowered": {
                "$": 2,
                "succ": {
                  "js": _3
                }
              },
              "wixsite": _3,
              "xnbay": {
                "$": 2,
                "succ": {
                  "u2": _3,
                  "u2-local": _3
                }
              },
              "yolasite": _3
            }
          },
          "coop": _2,
          "cr": {
            "$": 1,
            "succ": {
              "ac": _2,
              "co": _2,
              "ed": _2,
              "fi": _2,
              "go": _2,
              "or": _2,
              "sa": _2
            }
          },
          "cu": {
            "$": 1,
            "succ": {
              "com": _2,
              "edu": _2,
              "org": _2,
              "net": _2,
              "gov": _2,
              "inf": _2
            }
          },
          "cv": {
            "$": 1,
            "succ": {
              "com": _2,
              "edu": _2,
              "int": _2,
              "nome": _2,
              "org": _2,
              "blogspot": _3
            }
          },
          "cw": _25,
          "cx": {
            "$": 1,
            "succ": {
              "gov": _2,
              "ath": _3,
              "info": _3
            }
          },
          "cy": {
            "$": 1,
            "succ": {
              "ac": _2,
              "biz": _2,
              "com": {
                "$": 1,
                "succ": {
                  "blogspot": _3,
                  "scaleforce": _26
                }
              },
              "ekloges": _2,
              "gov": _2,
              "ltd": _2,
              "mil": _2,
              "net": _2,
              "org": _2,
              "press": _2,
              "pro": _2,
              "tm": _2
            }
          },
          "cz": {
            "$": 1,
            "succ": {
              "co": _3,
              "realm": _3,
              "e4": _3,
              "blogspot": _3,
              "metacentrum": {
                "$": 0,
                "succ": {
                  "cloud": _5,
                  "custom": _3
                }
              },
              "muni": {
                "$": 0,
                "succ": {
                  "cloud": {
                    "$": 0,
                    "succ": {
                      "flt": _3,
                      "usr": _3
                    }
                  }
                }
              }
            }
          },
          "de": {
            "$": 1,
            "succ": {
              "bplaced": _3,
              "square7": _3,
              "com": _3,
              "cosidns": {
                "$": 0,
                "succ": {
                  "dyn": _3
                }
              },
              "dynamisches-dns": _3,
              "dnsupdater": _3,
              "internet-dns": _3,
              "l-o-g-i-n": _3,
              "dnshome": _3,
              "fuettertdasnetz": _3,
              "isteingeek": _3,
              "istmein": _3,
              "lebtimnetz": _3,
              "leitungsen": _3,
              "traeumtgerade": _3,
              "ddnss": {
                "$": 2,
                "succ": {
                  "dyn": _3,
                  "dyndns": _3
                }
              },
              "dyndns1": _3,
              "dyn-ip24": _3,
              "home-webserver": {
                "$": 2,
                "succ": {
                  "dyn": _3
                }
              },
              "myhome-server": _3,
              "frusky": _5,
              "goip": _3,
              "blogspot": _3,
              "xn--gnstigbestellen-zvb": _3,
              "günstigbestellen": _3,
              "xn--gnstigliefern-wob": _3,
              "günstigliefern": _3,
              "hs-heilbronn": {
                "$": 0,
                "succ": {
                  "it": _24
                }
              },
              "dyn-berlin": _3,
              "in-berlin": _3,
              "in-brb": _3,
              "in-butter": _3,
              "in-dsl": _3,
              "in-vpn": _3,
              "iservschule": _3,
              "mein-iserv": _3,
              "schulplattform": _3,
              "schulserver": _3,
              "test-iserv": _3,
              "keymachine": _3,
              "git-repos": _3,
              "lcube-server": _3,
              "svn-repos": _3,
              "barsy": _3,
              "123webseite": _3,
              "logoip": _3,
              "firewall-gateway": _3,
              "my-gateway": _3,
              "my-router": _3,
              "spdns": _3,
              "speedpartner": {
                "$": 0,
                "succ": {
                  "customer": _3
                }
              },
              "myspreadshop": _3,
              "taifun-dns": _3,
              "12hp": _3,
              "2ix": _3,
              "4lima": _3,
              "lima-city": _3,
              "dd-dns": _3,
              "dray-dns": _3,
              "draydns": _3,
              "dyn-vpn": _3,
              "dynvpn": _3,
              "mein-vigor": _3,
              "my-vigor": _3,
              "my-wan": _3,
              "syno-ds": _3,
              "synology-diskstation": _3,
              "synology-ds": _3,
              "uberspace": _5,
              "virtualuser": _3,
              "virtual-user": _3,
              "community-pro": _3,
              "diskussionsbereich": _3
            }
          },
          "dj": _2,
          "dk": {
            "$": 1,
            "succ": {
              "biz": _3,
              "co": _3,
              "firm": _3,
              "reg": _3,
              "store": _3,
              "blogspot": _3,
              "123hjemmeside": _3,
              "myspreadshop": _3
            }
          },
          "dm": _4,
          "do": {
            "$": 1,
            "succ": {
              "art": _2,
              "com": _2,
              "edu": _2,
              "gob": _2,
              "gov": _2,
              "mil": _2,
              "net": _2,
              "org": _2,
              "sld": _2,
              "web": _2
            }
          },
          "dz": {
            "$": 1,
            "succ": {
              "art": _2,
              "asso": _2,
              "com": _2,
              "edu": _2,
              "gov": _2,
              "org": _2,
              "net": _2,
              "pol": _2,
              "soc": _2,
              "tm": _2
            }
          },
          "ec": {
            "$": 1,
            "succ": {
              "com": _2,
              "info": _2,
              "net": _2,
              "fin": _2,
              "k12": _2,
              "med": _2,
              "pro": _2,
              "org": _2,
              "edu": _2,
              "gov": _2,
              "gob": _2,
              "mil": _2,
              "base": _3,
              "official": _3
            }
          },
          "edu": {
            "$": 1,
            "succ": {
              "rit": {
                "$": 0,
                "succ": {
                  "git-pages": _3
                }
              }
            }
          },
          "ee": {
            "$": 1,
            "succ": {
              "edu": _2,
              "gov": _2,
              "riik": _2,
              "lib": _2,
              "med": _2,
              "com": _6,
              "pri": _2,
              "aip": _2,
              "org": _2,
              "fie": _2
            }
          },
          "eg": {
            "$": 1,
            "succ": {
              "com": _6,
              "edu": _2,
              "eun": _2,
              "gov": _2,
              "mil": _2,
              "name": _2,
              "net": _2,
              "org": _2,
              "sci": _2
            }
          },
          "er": _8,
          "es": {
            "$": 1,
            "succ": {
              "com": _6,
              "nom": _2,
              "org": _2,
              "gob": _2,
              "edu": _2,
              "123miweb": _3,
              "myspreadshop": _3
            }
          },
          "et": {
            "$": 1,
            "succ": {
              "com": _2,
              "gov": _2,
              "org": _2,
              "edu": _2,
              "biz": _2,
              "name": _2,
              "info": _2,
              "net": _2
            }
          },
          "eu": {
            "$": 1,
            "succ": {
              "airkitapps": _3,
              "mycd": _3,
              "cloudns": _3,
              "dogado": _27,
              "barsy": _3,
              "wellbeingzone": _3,
              "spdns": _3,
              "transurl": _5,
              "diskstation": _3
            }
          },
          "fi": {
            "$": 1,
            "succ": {
              "aland": _2,
              "dy": _3,
              "blogspot": _3,
              "xn--hkkinen-5wa": _3,
              "häkkinen": _3,
              "iki": _3,
              "cloudplatform": {
                "$": 0,
                "succ": {
                  "fi": _3
                }
              },
              "datacenter": {
                "$": 0,
                "succ": {
                  "demo": _3,
                  "paas": _3
                }
              },
              "kapsi": _3,
              "123kotisivu": _3,
              "myspreadshop": _3
            }
          },
          "fj": {
            "$": 1,
            "succ": {
              "ac": _2,
              "biz": _2,
              "com": _2,
              "gov": _2,
              "info": _2,
              "mil": _2,
              "name": _2,
              "net": _2,
              "org": _2,
              "pro": _2
            }
          },
          "fk": _8,
          "fm": {
            "$": 1,
            "succ": {
              "com": _2,
              "edu": _2,
              "net": _2,
              "org": _2,
              "radio": _3,
              "user": _5
            }
          },
          "fo": _2,
          "fr": {
            "$": 1,
            "succ": {
              "asso": _2,
              "com": _2,
              "gouv": _2,
              "nom": _2,
              "prd": _2,
              "tm": _2,
              "aeroport": _2,
              "avocat": _2,
              "avoues": _2,
              "cci": _2,
              "chambagri": _2,
              "chirurgiens-dentistes": _2,
              "experts-comptables": _2,
              "geometre-expert": _2,
              "greta": _2,
              "huissier-justice": _2,
              "medecin": _2,
              "notaires": _2,
              "pharmacien": _2,
              "port": _2,
              "veterinaire": _2,
              "en-root": _3,
              "fbx-os": _3,
              "fbxos": _3,
              "freebox-os": _3,
              "freeboxos": _3,
              "blogspot": _3,
              "goupile": _3,
              "123siteweb": _3,
              "on-web": _3,
              "chirurgiens-dentistes-en-france": _3,
              "dedibox": _3,
              "myspreadshop": _3,
              "ynh": _3
            }
          },
          "ga": _2,
          "gb": _2,
          "gd": {
            "$": 1,
            "succ": {
              "edu": _2,
              "gov": _2
            }
          },
          "ge": {
            "$": 1,
            "succ": {
              "com": _2,
              "edu": _2,
              "gov": _2,
              "org": _2,
              "mil": _2,
              "net": _2,
              "pvt": _2
            }
          },
          "gf": _2,
          "gg": {
            "$": 1,
            "succ": {
              "co": _2,
              "net": _2,
              "org": _2,
              "kaas": _3,
              "cya": _3,
              "panel": {
                "$": 2,
                "succ": {
                  "daemon": _3
                }
              }
            }
          },
          "gh": {
            "$": 1,
            "succ": {
              "com": _2,
              "edu": _2,
              "gov": _2,
              "org": _2,
              "mil": _2
            }
          },
          "gi": {
            "$": 1,
            "succ": {
              "com": _2,
              "ltd": _2,
              "gov": _2,
              "mod": _2,
              "edu": _2,
              "org": _2
            }
          },
          "gl": {
            "$": 1,
            "succ": {
              "co": _2,
              "com": _2,
              "edu": _2,
              "net": _2,
              "org": _2,
              "biz": _3,
              "xx": _3
            }
          },
          "gm": _2,
          "gn": {
            "$": 1,
            "succ": {
              "ac": _2,
              "com": _2,
              "edu": _2,
              "gov": _2,
              "org": _2,
              "net": _2
            }
          },
          "gov": _2,
          "gp": {
            "$": 1,
            "succ": {
              "com": _2,
              "net": _2,
              "mobi": _2,
              "edu": _2,
              "org": _2,
              "asso": _2,
              "app": _3
            }
          },
          "gq": _2,
          "gr": {
            "$": 1,
            "succ": {
              "com": _2,
              "edu": _2,
              "net": _2,
              "org": _2,
              "gov": _2,
              "blogspot": _3,
              "simplesite": _3
            }
          },
          "gs": _2,
          "gt": {
            "$": 1,
            "succ": {
              "com": _2,
              "edu": _2,
              "gob": _2,
              "ind": _2,
              "mil": _2,
              "net": _2,
              "org": _2,
              "blog": _3,
              "de": _3,
              "to": _3
            }
          },
          "gu": {
            "$": 1,
            "succ": {
              "com": _2,
              "edu": _2,
              "gov": _2,
              "guam": _2,
              "info": _2,
              "net": _2,
              "org": _2,
              "web": _2
            }
          },
          "gw": _2,
          "gy": {
            "$": 1,
            "succ": {
              "co": _2,
              "com": _2,
              "edu": _2,
              "gov": _2,
              "net": _2,
              "org": _2,
              "be": _3
            }
          },
          "hk": {
            "$": 1,
            "succ": {
              "com": _2,
              "edu": _2,
              "gov": _2,
              "idv": _2,
              "net": _2,
              "org": _2,
              "xn--55qx5d": _2,
              "公司": _2,
              "xn--wcvs22d": _2,
              "教育": _2,
              "xn--lcvr32d": _2,
              "敎育": _2,
              "xn--mxtq1m": _2,
              "政府": _2,
              "xn--gmqw5a": _2,
              "個人": _2,
              "xn--ciqpn": _2,
              "个人": _2,
              "xn--gmq050i": _2,
              "箇人": _2,
              "xn--zf0avx": _2,
              "網络": _2,
              "xn--io0a7i": _2,
              "网络": _2,
              "xn--mk0axi": _2,
              "组織": _2,
              "xn--od0alg": _2,
              "網絡": _2,
              "xn--od0aq3b": _2,
              "网絡": _2,
              "xn--tn0ag": _2,
              "组织": _2,
              "xn--uc0atv": _2,
              "組織": _2,
              "xn--uc0ay4a": _2,
              "組织": _2,
              "blogspot": _3,
              "secaas": _3,
              "ltd": _3,
              "inc": _3
            }
          },
          "hm": _2,
          "hn": {
            "$": 1,
            "succ": {
              "com": _2,
              "edu": _2,
              "org": _2,
              "net": _2,
              "mil": _2,
              "gob": _2,
              "cc": _3
            }
          },
          "hr": {
            "$": 1,
            "succ": {
              "iz": _2,
              "from": _2,
              "name": _2,
              "com": _2,
              "blogspot": _3,
              "free": _3
            }
          },
          "ht": {
            "$": 1,
            "succ": {
              "com": _2,
              "shop": _2,
              "firm": _2,
              "info": _2,
              "adult": _2,
              "net": _2,
              "pro": _2,
              "org": _2,
              "med": _2,
              "art": _2,
              "coop": _2,
              "pol": _2,
              "asso": _2,
              "edu": _2,
              "rel": _2,
              "gouv": _2,
              "perso": _2
            }
          },
          "hu": {
            "$": 1,
            "succ": {
              "2000": _2,
              "co": _2,
              "info": _2,
              "org": _2,
              "priv": _2,
              "sport": _2,
              "tm": _2,
              "agrar": _2,
              "bolt": _2,
              "casino": _2,
              "city": _2,
              "erotica": _2,
              "erotika": _2,
              "film": _2,
              "forum": _2,
              "games": _2,
              "hotel": _2,
              "ingatlan": _2,
              "jogasz": _2,
              "konyvelo": _2,
              "lakas": _2,
              "media": _2,
              "news": _2,
              "reklam": _2,
              "sex": _2,
              "shop": _2,
              "suli": _2,
              "szex": _2,
              "tozsde": _2,
              "utazas": _2,
              "video": _2,
              "blogspot": _3
            }
          },
          "id": {
            "$": 1,
            "succ": {
              "ac": _2,
              "biz": _2,
              "co": _6,
              "desa": _2,
              "go": _2,
              "mil": _2,
              "my": {
                "$": 1,
                "succ": {
                  "rss": _5
                }
              },
              "net": _2,
              "or": _2,
              "ponpes": _2,
              "sch": _2,
              "web": _2,
              "flap": _3,
              "forte": _3
            }
          },
          "ie": {
            "$": 1,
            "succ": {
              "gov": _2,
              "blogspot": _3,
              "myspreadshop": _3
            }
          },
          "il": {
            "$": 1,
            "succ": {
              "ac": _2,
              "co": {
                "$": 1,
                "succ": {
                  "ravpage": _3,
                  "blogspot": _3,
                  "tabitorder": _3,
                  "mytabit": _3
                }
              },
              "gov": _2,
              "idf": _2,
              "k12": _2,
              "muni": _2,
              "net": _2,
              "org": _2
            }
          },
          "xn--4dbrk0ce": {
            "$": 1,
            "succ": {
              "xn--4dbgdty6c": _2,
              "xn--5dbhl8d": _2,
              "xn--8dbq2a": _2,
              "xn--hebda8b": _2
            }
          },
          "ישראל": {
            "$": 1,
            "succ": {
              "אקדמיה": _2,
              "ישוב": _2,
              "צהל": _2,
              "ממשל": _2
            }
          },
          "im": {
            "$": 1,
            "succ": {
              "ac": _2,
              "co": {
                "$": 1,
                "succ": {
                  "ltd": _2,
                  "plc": _2
                }
              },
              "com": _2,
              "net": _2,
              "org": _2,
              "tt": _2,
              "tv": _2,
              "ro": _3
            }
          },
          "in": {
            "$": 1,
            "succ": {
              "5g": _2,
              "6g": _2,
              "ac": _2,
              "ai": _2,
              "am": _2,
              "bihar": _2,
              "biz": _2,
              "business": _2,
              "ca": _2,
              "cn": _2,
              "co": _2,
              "com": _2,
              "coop": _2,
              "cs": _2,
              "delhi": _2,
              "dr": _2,
              "edu": _2,
              "er": _2,
              "firm": _2,
              "gen": _2,
              "gov": _2,
              "gujarat": _2,
              "ind": _2,
              "info": _2,
              "int": _2,
              "internet": _2,
              "io": _2,
              "me": _2,
              "mil": _2,
              "net": _2,
              "nic": _2,
              "org": _2,
              "pg": _2,
              "post": _2,
              "pro": _2,
              "res": _2,
              "travel": _2,
              "tv": _2,
              "uk": _2,
              "up": _2,
              "us": _2,
              "web": _3,
              "cloudns": _3,
              "blogspot": _3,
              "barsy": _3,
              "supabase": _3
            }
          },
          "info": {
            "$": 1,
            "succ": {
              "cloudns": _3,
              "dynamic-dns": _3,
              "dyndns": _3,
              "barrel-of-knowledge": _3,
              "barrell-of-knowledge": _3,
              "for-our": _3,
              "groks-the": _3,
              "groks-this": _3,
              "here-for-more": _3,
              "knowsitall": _3,
              "selfip": _3,
              "webhop": _3,
              "barsy": _3,
              "mayfirst": _3,
              "forumz": _3,
              "nsupdate": _3,
              "dvrcam": _3,
              "ilovecollege": _3,
              "no-ip": _3,
              "dnsupdate": _3,
              "v-info": _3
            }
          },
          "int": {
            "$": 1,
            "succ": {
              "eu": _2
            }
          },
          "io": {
            "$": 1,
            "succ": {
              "2038": _3,
              "com": _2,
              "on-acorn": _5,
              "apigee": _3,
              "b-data": _3,
              "backplaneapp": _3,
              "banzaicloud": {
                "$": 0,
                "succ": {
                  "app": _3,
                  "backyards": _5
                }
              },
              "beagleboard": _3,
              "bitbucket": _3,
              "bluebite": _3,
              "boxfuse": _3,
              "browsersafetymark": _3,
              "bigv": {
                "$": 0,
                "succ": {
                  "uk0": _3
                }
              },
              "cleverapps": _3,
              "dappnode": {
                "$": 0,
                "succ": {
                  "dyndns": _3
                }
              },
              "dedyn": _3,
              "drud": _3,
              "definima": _3,
              "fh-muenster": _3,
              "shw": _3,
              "forgerock": {
                "$": 0,
                "succ": {
                  "id": _3
                }
              },
              "ghost": _3,
              "github": _3,
              "gitlab": _3,
              "lolipop": _3,
              "hasura-app": _3,
              "hostyhosting": _3,
              "moonscale": _5,
              "beebyte": _20,
              "beebyteapp": {
                "$": 0,
                "succ": {
                  "sekd1": _3
                }
              },
              "jele": _3,
              "unispace": {
                "$": 0,
                "succ": {
                  "cloud-fr1": _3
                }
              },
              "webthings": _3,
              "loginline": _3,
              "barsy": _3,
              "azurecontainer": _5,
              "ngrok": {
                "$": 2,
                "succ": {
                  "ap": _3,
                  "au": _3,
                  "eu": _3,
                  "in": _3,
                  "jp": _3,
                  "sa": _3,
                  "us": _3
                }
              },
              "nodeart": {
                "$": 0,
                "succ": {
                  "stage": _3
                }
              },
              "nid": _3,
              "pantheonsite": _3,
              "dyn53": _3,
              "pstmn": {
                "$": 2,
                "succ": {
                  "mock": _3
                }
              },
              "protonet": _3,
              "qoto": _3,
              "qcx": {
                "$": 2,
                "succ": {
                  "sys": _5
                }
              },
              "vaporcloud": _3,
              "vbrplsbx": {
                "$": 0,
                "succ": {
                  "g": _3
                }
              },
              "on-k3s": _5,
              "on-rio": _5,
              "readthedocs": _3,
              "resindevice": _3,
              "resinstaging": {
                "$": 0,
                "succ": {
                  "devices": _3
                }
              },
              "hzc": _3,
              "sandcats": _3,
              "shiftcrypto": _3,
              "shiftedit": _3,
              "mo-siemens": _3,
              "musician": _3,
              "lair": _19,
              "stolos": _5,
              "spacekit": _3,
              "utwente": _3,
              "s5y": _5,
              "edugit": _3,
              "telebit": _3,
              "thingdust": {
                "$": 0,
                "succ": {
                  "dev": _30,
                  "disrec": _30,
                  "prod": _31,
                  "testing": _30
                }
              },
              "tickets": _3,
              "upli": _3,
              "wedeploy": _3,
              "editorx": _3,
              "basicserver": _3,
              "virtualserver": _3
            }
          },
          "iq": _32,
          "ir": {
            "$": 1,
            "succ": {
              "ac": _2,
              "co": _2,
              "gov": _2,
              "id": _2,
              "net": _2,
              "org": _2,
              "sch": _2,
              "xn--mgba3a4f16a": _2,
              "ایران": _2,
              "xn--mgba3a4fra": _2,
              "ايران": _2
            }
          },
          "is": {
            "$": 1,
            "succ": {
              "net": _2,
              "com": _2,
              "edu": _2,
              "gov": _2,
              "org": _2,
              "int": _2,
              "cupcake": _3,
              "blogspot": _3
            }
          },
          "it": {
            "$": 1,
            "succ": {
              "gov": _2,
              "edu": _2,
              "abr": _2,
              "abruzzo": _2,
              "aosta-valley": _2,
              "aostavalley": _2,
              "bas": _2,
              "basilicata": _2,
              "cal": _2,
              "calabria": _2,
              "cam": _2,
              "campania": _2,
              "emilia-romagna": _2,
              "emiliaromagna": _2,
              "emr": _2,
              "friuli-v-giulia": _2,
              "friuli-ve-giulia": _2,
              "friuli-vegiulia": _2,
              "friuli-venezia-giulia": _2,
              "friuli-veneziagiulia": _2,
              "friuli-vgiulia": _2,
              "friuliv-giulia": _2,
              "friulive-giulia": _2,
              "friulivegiulia": _2,
              "friulivenezia-giulia": _2,
              "friuliveneziagiulia": _2,
              "friulivgiulia": _2,
              "fvg": _2,
              "laz": _2,
              "lazio": _2,
              "lig": _2,
              "liguria": _2,
              "lom": _2,
              "lombardia": _2,
              "lombardy": _2,
              "lucania": _2,
              "mar": _2,
              "marche": _2,
              "mol": _2,
              "molise": _2,
              "piedmont": _2,
              "piemonte": _2,
              "pmn": _2,
              "pug": _2,
              "puglia": _2,
              "sar": _2,
              "sardegna": _2,
              "sardinia": _2,
              "sic": _2,
              "sicilia": _2,
              "sicily": _2,
              "taa": _2,
              "tos": _2,
              "toscana": _2,
              "trentin-sud-tirol": _2,
              "xn--trentin-sd-tirol-rzb": _2,
              "trentin-süd-tirol": _2,
              "trentin-sudtirol": _2,
              "xn--trentin-sdtirol-7vb": _2,
              "trentin-südtirol": _2,
              "trentin-sued-tirol": _2,
              "trentin-suedtirol": _2,
              "trentino-a-adige": _2,
              "trentino-aadige": _2,
              "trentino-alto-adige": _2,
              "trentino-altoadige": _2,
              "trentino-s-tirol": _2,
              "trentino-stirol": _2,
              "trentino-sud-tirol": _2,
              "xn--trentino-sd-tirol-c3b": _2,
              "trentino-süd-tirol": _2,
              "trentino-sudtirol": _2,
              "xn--trentino-sdtirol-szb": _2,
              "trentino-südtirol": _2,
              "trentino-sued-tirol": _2,
              "trentino-suedtirol": _2,
              "trentino": _2,
              "trentinoa-adige": _2,
              "trentinoaadige": _2,
              "trentinoalto-adige": _2,
              "trentinoaltoadige": _2,
              "trentinos-tirol": _2,
              "trentinostirol": _2,
              "trentinosud-tirol": _2,
              "xn--trentinosd-tirol-rzb": _2,
              "trentinosüd-tirol": _2,
              "trentinosudtirol": _2,
              "xn--trentinosdtirol-7vb": _2,
              "trentinosüdtirol": _2,
              "trentinosued-tirol": _2,
              "trentinosuedtirol": _2,
              "trentinsud-tirol": _2,
              "xn--trentinsd-tirol-6vb": _2,
              "trentinsüd-tirol": _2,
              "trentinsudtirol": _2,
              "xn--trentinsdtirol-nsb": _2,
              "trentinsüdtirol": _2,
              "trentinsued-tirol": _2,
              "trentinsuedtirol": _2,
              "tuscany": _2,
              "umb": _2,
              "umbria": _2,
              "val-d-aosta": _2,
              "val-daosta": _2,
              "vald-aosta": _2,
              "valdaosta": _2,
              "valle-aosta": _2,
              "valle-d-aosta": _2,
              "valle-daosta": _2,
              "valleaosta": _2,
              "valled-aosta": _2,
              "valledaosta": _2,
              "vallee-aoste": _2,
              "xn--valle-aoste-ebb": _2,
              "vallée-aoste": _2,
              "vallee-d-aoste": _2,
              "xn--valle-d-aoste-ehb": _2,
              "vallée-d-aoste": _2,
              "valleeaoste": _2,
              "xn--valleaoste-e7a": _2,
              "valléeaoste": _2,
              "valleedaoste": _2,
              "xn--valledaoste-ebb": _2,
              "valléedaoste": _2,
              "vao": _2,
              "vda": _2,
              "ven": _2,
              "veneto": _2,
              "ag": _2,
              "agrigento": _2,
              "al": _2,
              "alessandria": _2,
              "alto-adige": _2,
              "altoadige": _2,
              "an": _2,
              "ancona": _2,
              "andria-barletta-trani": _2,
              "andria-trani-barletta": _2,
              "andriabarlettatrani": _2,
              "andriatranibarletta": _2,
              "ao": _2,
              "aosta": _2,
              "aoste": _2,
              "ap": _2,
              "aq": _2,
              "aquila": _2,
              "ar": _2,
              "arezzo": _2,
              "ascoli-piceno": _2,
              "ascolipiceno": _2,
              "asti": _2,
              "at": _2,
              "av": _2,
              "avellino": _2,
              "ba": _2,
              "balsan-sudtirol": _2,
              "xn--balsan-sdtirol-nsb": _2,
              "balsan-südtirol": _2,
              "balsan-suedtirol": _2,
              "balsan": _2,
              "bari": _2,
              "barletta-trani-andria": _2,
              "barlettatraniandria": _2,
              "belluno": _2,
              "benevento": _2,
              "bergamo": _2,
              "bg": _2,
              "bi": _2,
              "biella": _2,
              "bl": _2,
              "bn": _2,
              "bo": _2,
              "bologna": _2,
              "bolzano-altoadige": _2,
              "bolzano": _2,
              "bozen-sudtirol": _2,
              "xn--bozen-sdtirol-2ob": _2,
              "bozen-südtirol": _2,
              "bozen-suedtirol": _2,
              "bozen": _2,
              "br": _2,
              "brescia": _2,
              "brindisi": _2,
              "bs": _2,
              "bt": _2,
              "bulsan-sudtirol": _2,
              "xn--bulsan-sdtirol-nsb": _2,
              "bulsan-südtirol": _2,
              "bulsan-suedtirol": _2,
              "bulsan": _2,
              "bz": _2,
              "ca": _2,
              "cagliari": _2,
              "caltanissetta": _2,
              "campidano-medio": _2,
              "campidanomedio": _2,
              "campobasso": _2,
              "carbonia-iglesias": _2,
              "carboniaiglesias": _2,
              "carrara-massa": _2,
              "carraramassa": _2,
              "caserta": _2,
              "catania": _2,
              "catanzaro": _2,
              "cb": _2,
              "ce": _2,
              "cesena-forli": _2,
              "xn--cesena-forl-mcb": _2,
              "cesena-forlì": _2,
              "cesenaforli": _2,
              "xn--cesenaforl-i8a": _2,
              "cesenaforlì": _2,
              "ch": _2,
              "chieti": _2,
              "ci": _2,
              "cl": _2,
              "cn": _2,
              "co": _2,
              "como": _2,
              "cosenza": _2,
              "cr": _2,
              "cremona": _2,
              "crotone": _2,
              "cs": _2,
              "ct": _2,
              "cuneo": _2,
              "cz": _2,
              "dell-ogliastra": _2,
              "dellogliastra": _2,
              "en": _2,
              "enna": _2,
              "fc": _2,
              "fe": _2,
              "fermo": _2,
              "ferrara": _2,
              "fg": _2,
              "fi": _2,
              "firenze": _2,
              "florence": _2,
              "fm": _2,
              "foggia": _2,
              "forli-cesena": _2,
              "xn--forl-cesena-fcb": _2,
              "forlì-cesena": _2,
              "forlicesena": _2,
              "xn--forlcesena-c8a": _2,
              "forlìcesena": _2,
              "fr": _2,
              "frosinone": _2,
              "ge": _2,
              "genoa": _2,
              "genova": _2,
              "go": _2,
              "gorizia": _2,
              "gr": _2,
              "grosseto": _2,
              "iglesias-carbonia": _2,
              "iglesiascarbonia": _2,
              "im": _2,
              "imperia": _2,
              "is": _2,
              "isernia": _2,
              "kr": _2,
              "la-spezia": _2,
              "laquila": _2,
              "laspezia": _2,
              "latina": _2,
              "lc": _2,
              "le": _2,
              "lecce": _2,
              "lecco": _2,
              "li": _2,
              "livorno": _2,
              "lo": _2,
              "lodi": _2,
              "lt": _2,
              "lu": _2,
              "lucca": _2,
              "macerata": _2,
              "mantova": _2,
              "massa-carrara": _2,
              "massacarrara": _2,
              "matera": _2,
              "mb": _2,
              "mc": _2,
              "me": _2,
              "medio-campidano": _2,
              "mediocampidano": _2,
              "messina": _2,
              "mi": _2,
              "milan": _2,
              "milano": _2,
              "mn": _2,
              "mo": _2,
              "modena": _2,
              "monza-brianza": _2,
              "monza-e-della-brianza": _2,
              "monza": _2,
              "monzabrianza": _2,
              "monzaebrianza": _2,
              "monzaedellabrianza": _2,
              "ms": _2,
              "mt": _2,
              "na": _2,
              "naples": _2,
              "napoli": _2,
              "no": _2,
              "novara": _2,
              "nu": _2,
              "nuoro": _2,
              "og": _2,
              "ogliastra": _2,
              "olbia-tempio": _2,
              "olbiatempio": _2,
              "or": _2,
              "oristano": _2,
              "ot": _2,
              "pa": _2,
              "padova": _2,
              "padua": _2,
              "palermo": _2,
              "parma": _2,
              "pavia": _2,
              "pc": _2,
              "pd": _2,
              "pe": _2,
              "perugia": _2,
              "pesaro-urbino": _2,
              "pesarourbino": _2,
              "pescara": _2,
              "pg": _2,
              "pi": _2,
              "piacenza": _2,
              "pisa": _2,
              "pistoia": _2,
              "pn": _2,
              "po": _2,
              "pordenone": _2,
              "potenza": _2,
              "pr": _2,
              "prato": _2,
              "pt": _2,
              "pu": _2,
              "pv": _2,
              "pz": _2,
              "ra": _2,
              "ragusa": _2,
              "ravenna": _2,
              "rc": _2,
              "re": _2,
              "reggio-calabria": _2,
              "reggio-emilia": _2,
              "reggiocalabria": _2,
              "reggioemilia": _2,
              "rg": _2,
              "ri": _2,
              "rieti": _2,
              "rimini": _2,
              "rm": _2,
              "rn": _2,
              "ro": _2,
              "roma": _2,
              "rome": _2,
              "rovigo": _2,
              "sa": _2,
              "salerno": _2,
              "sassari": _2,
              "savona": _2,
              "si": _2,
              "siena": _2,
              "siracusa": _2,
              "so": _2,
              "sondrio": _2,
              "sp": _2,
              "sr": _2,
              "ss": _2,
              "suedtirol": _2,
              "xn--sdtirol-n2a": _2,
              "südtirol": _2,
              "sv": _2,
              "ta": _2,
              "taranto": _2,
              "te": _2,
              "tempio-olbia": _2,
              "tempioolbia": _2,
              "teramo": _2,
              "terni": _2,
              "tn": _2,
              "to": _2,
              "torino": _2,
              "tp": _2,
              "tr": _2,
              "trani-andria-barletta": _2,
              "trani-barletta-andria": _2,
              "traniandriabarletta": _2,
              "tranibarlettaandria": _2,
              "trapani": _2,
              "trento": _2,
              "treviso": _2,
              "trieste": _2,
              "ts": _2,
              "turin": _2,
              "tv": _2,
              "ud": _2,
              "udine": _2,
              "urbino-pesaro": _2,
              "urbinopesaro": _2,
              "va": _2,
              "varese": _2,
              "vb": _2,
              "vc": _2,
              "ve": _2,
              "venezia": _2,
              "venice": _2,
              "verbania": _2,
              "vercelli": _2,
              "verona": _2,
              "vi": _2,
              "vibo-valentia": _2,
              "vibovalentia": _2,
              "vicenza": _2,
              "viterbo": _2,
              "vr": _2,
              "vs": _2,
              "vt": _2,
              "vv": _2,
              "blogspot": _3,
              "ibxos": _3,
              "iliadboxos": _3,
              "neen": {
                "$": 0,
                "succ": {
                  "jc": _3
                }
              },
              "tim": {
                "$": 0,
                "succ": {
                  "open": {
                    "$": 0,
                    "succ": {
                      "jelastic": _9
                    }
                  }
                }
              },
              "16-b": _3,
              "32-b": _3,
              "64-b": _3,
              "123homepage": _3,
              "myspreadshop": _3,
              "syncloud": _3
            }
          },
          "je": {
            "$": 1,
            "succ": {
              "co": _2,
              "net": _2,
              "org": _2,
              "of": _3
            }
          },
          "jm": _8,
          "jo": {
            "$": 1,
            "succ": {
              "com": _2,
              "org": _2,
              "net": _2,
              "edu": _2,
              "sch": _2,
              "gov": _2,
              "mil": _2,
              "name": _2
            }
          },
          "jobs": _2,
          "jp": {
            "$": 1,
            "succ": {
              "ac": _2,
              "ad": _2,
              "co": _2,
              "ed": _2,
              "go": _2,
              "gr": _2,
              "lg": _2,
              "ne": {
                "$": 1,
                "succ": {
                  "aseinet": _28,
                  "gehirn": _3,
                  "ivory": _3,
                  "mail-box": _3,
                  "mints": _3,
                  "mokuren": _3,
                  "opal": _3,
                  "sakura": _3,
                  "sumomo": _3,
                  "topaz": _3
                }
              },
              "or": _2,
              "aichi": {
                "$": 1,
                "succ": {
                  "aisai": _2,
                  "ama": _2,
                  "anjo": _2,
                  "asuke": _2,
                  "chiryu": _2,
                  "chita": _2,
                  "fuso": _2,
                  "gamagori": _2,
                  "handa": _2,
                  "hazu": _2,
                  "hekinan": _2,
                  "higashiura": _2,
                  "ichinomiya": _2,
                  "inazawa": _2,
                  "inuyama": _2,
                  "isshiki": _2,
                  "iwakura": _2,
                  "kanie": _2,
                  "kariya": _2,
                  "kasugai": _2,
                  "kira": _2,
                  "kiyosu": _2,
                  "komaki": _2,
                  "konan": _2,
                  "kota": _2,
                  "mihama": _2,
                  "miyoshi": _2,
                  "nishio": _2,
                  "nisshin": _2,
                  "obu": _2,
                  "oguchi": _2,
                  "oharu": _2,
                  "okazaki": _2,
                  "owariasahi": _2,
                  "seto": _2,
                  "shikatsu": _2,
                  "shinshiro": _2,
                  "shitara": _2,
                  "tahara": _2,
                  "takahama": _2,
                  "tobishima": _2,
                  "toei": _2,
                  "togo": _2,
                  "tokai": _2,
                  "tokoname": _2,
                  "toyoake": _2,
                  "toyohashi": _2,
                  "toyokawa": _2,
                  "toyone": _2,
                  "toyota": _2,
                  "tsushima": _2,
                  "yatomi": _2
                }
              },
              "akita": {
                "$": 1,
                "succ": {
                  "akita": _2,
                  "daisen": _2,
                  "fujisato": _2,
                  "gojome": _2,
                  "hachirogata": _2,
                  "happou": _2,
                  "higashinaruse": _2,
                  "honjo": _2,
                  "honjyo": _2,
                  "ikawa": _2,
                  "kamikoani": _2,
                  "kamioka": _2,
                  "katagami": _2,
                  "kazuno": _2,
                  "kitaakita": _2,
                  "kosaka": _2,
                  "kyowa": _2,
                  "misato": _2,
                  "mitane": _2,
                  "moriyoshi": _2,
                  "nikaho": _2,
                  "noshiro": _2,
                  "odate": _2,
                  "oga": _2,
                  "ogata": _2,
                  "semboku": _2,
                  "yokote": _2,
                  "yurihonjo": _2
                }
              },
              "aomori": {
                "$": 1,
                "succ": {
                  "aomori": _2,
                  "gonohe": _2,
                  "hachinohe": _2,
                  "hashikami": _2,
                  "hiranai": _2,
                  "hirosaki": _2,
                  "itayanagi": _2,
                  "kuroishi": _2,
                  "misawa": _2,
                  "mutsu": _2,
                  "nakadomari": _2,
                  "noheji": _2,
                  "oirase": _2,
                  "owani": _2,
                  "rokunohe": _2,
                  "sannohe": _2,
                  "shichinohe": _2,
                  "shingo": _2,
                  "takko": _2,
                  "towada": _2,
                  "tsugaru": _2,
                  "tsuruta": _2
                }
              },
              "chiba": {
                "$": 1,
                "succ": {
                  "abiko": _2,
                  "asahi": _2,
                  "chonan": _2,
                  "chosei": _2,
                  "choshi": _2,
                  "chuo": _2,
                  "funabashi": _2,
                  "futtsu": _2,
                  "hanamigawa": _2,
                  "ichihara": _2,
                  "ichikawa": _2,
                  "ichinomiya": _2,
                  "inzai": _2,
                  "isumi": _2,
                  "kamagaya": _2,
                  "kamogawa": _2,
                  "kashiwa": _2,
                  "katori": _2,
                  "katsuura": _2,
                  "kimitsu": _2,
                  "kisarazu": _2,
                  "kozaki": _2,
                  "kujukuri": _2,
                  "kyonan": _2,
                  "matsudo": _2,
                  "midori": _2,
                  "mihama": _2,
                  "minamiboso": _2,
                  "mobara": _2,
                  "mutsuzawa": _2,
                  "nagara": _2,
                  "nagareyama": _2,
                  "narashino": _2,
                  "narita": _2,
                  "noda": _2,
                  "oamishirasato": _2,
                  "omigawa": _2,
                  "onjuku": _2,
                  "otaki": _2,
                  "sakae": _2,
                  "sakura": _2,
                  "shimofusa": _2,
                  "shirako": _2,
                  "shiroi": _2,
                  "shisui": _2,
                  "sodegaura": _2,
                  "sosa": _2,
                  "tako": _2,
                  "tateyama": _2,
                  "togane": _2,
                  "tohnosho": _2,
                  "tomisato": _2,
                  "urayasu": _2,
                  "yachimata": _2,
                  "yachiyo": _2,
                  "yokaichiba": _2,
                  "yokoshibahikari": _2,
                  "yotsukaido": _2
                }
              },
              "ehime": {
                "$": 1,
                "succ": {
                  "ainan": _2,
                  "honai": _2,
                  "ikata": _2,
                  "imabari": _2,
                  "iyo": _2,
                  "kamijima": _2,
                  "kihoku": _2,
                  "kumakogen": _2,
                  "masaki": _2,
                  "matsuno": _2,
                  "matsuyama": _2,
                  "namikata": _2,
                  "niihama": _2,
                  "ozu": _2,
                  "saijo": _2,
                  "seiyo": _2,
                  "shikokuchuo": _2,
                  "tobe": _2,
                  "toon": _2,
                  "uchiko": _2,
                  "uwajima": _2,
                  "yawatahama": _2
                }
              },
              "fukui": {
                "$": 1,
                "succ": {
                  "echizen": _2,
                  "eiheiji": _2,
                  "fukui": _2,
                  "ikeda": _2,
                  "katsuyama": _2,
                  "mihama": _2,
                  "minamiechizen": _2,
                  "obama": _2,
                  "ohi": _2,
                  "ono": _2,
                  "sabae": _2,
                  "sakai": _2,
                  "takahama": _2,
                  "tsuruga": _2,
                  "wakasa": _2
                }
              },
              "fukuoka": {
                "$": 1,
                "succ": {
                  "ashiya": _2,
                  "buzen": _2,
                  "chikugo": _2,
                  "chikuho": _2,
                  "chikujo": _2,
                  "chikushino": _2,
                  "chikuzen": _2,
                  "chuo": _2,
                  "dazaifu": _2,
                  "fukuchi": _2,
                  "hakata": _2,
                  "higashi": _2,
                  "hirokawa": _2,
                  "hisayama": _2,
                  "iizuka": _2,
                  "inatsuki": _2,
                  "kaho": _2,
                  "kasuga": _2,
                  "kasuya": _2,
                  "kawara": _2,
                  "keisen": _2,
                  "koga": _2,
                  "kurate": _2,
                  "kurogi": _2,
                  "kurume": _2,
                  "minami": _2,
                  "miyako": _2,
                  "miyama": _2,
                  "miyawaka": _2,
                  "mizumaki": _2,
                  "munakata": _2,
                  "nakagawa": _2,
                  "nakama": _2,
                  "nishi": _2,
                  "nogata": _2,
                  "ogori": _2,
                  "okagaki": _2,
                  "okawa": _2,
                  "oki": _2,
                  "omuta": _2,
                  "onga": _2,
                  "onojo": _2,
                  "oto": _2,
                  "saigawa": _2,
                  "sasaguri": _2,
                  "shingu": _2,
                  "shinyoshitomi": _2,
                  "shonai": _2,
                  "soeda": _2,
                  "sue": _2,
                  "tachiarai": _2,
                  "tagawa": _2,
                  "takata": _2,
                  "toho": _2,
                  "toyotsu": _2,
                  "tsuiki": _2,
                  "ukiha": _2,
                  "umi": _2,
                  "usui": _2,
                  "yamada": _2,
                  "yame": _2,
                  "yanagawa": _2,
                  "yukuhashi": _2
                }
              },
              "fukushima": {
                "$": 1,
                "succ": {
                  "aizubange": _2,
                  "aizumisato": _2,
                  "aizuwakamatsu": _2,
                  "asakawa": _2,
                  "bandai": _2,
                  "date": _2,
                  "fukushima": _2,
                  "furudono": _2,
                  "futaba": _2,
                  "hanawa": _2,
                  "higashi": _2,
                  "hirata": _2,
                  "hirono": _2,
                  "iitate": _2,
                  "inawashiro": _2,
                  "ishikawa": _2,
                  "iwaki": _2,
                  "izumizaki": _2,
                  "kagamiishi": _2,
                  "kaneyama": _2,
                  "kawamata": _2,
                  "kitakata": _2,
                  "kitashiobara": _2,
                  "koori": _2,
                  "koriyama": _2,
                  "kunimi": _2,
                  "miharu": _2,
                  "mishima": _2,
                  "namie": _2,
                  "nango": _2,
                  "nishiaizu": _2,
                  "nishigo": _2,
                  "okuma": _2,
                  "omotego": _2,
                  "ono": _2,
                  "otama": _2,
                  "samegawa": _2,
                  "shimogo": _2,
                  "shirakawa": _2,
                  "showa": _2,
                  "soma": _2,
                  "sukagawa": _2,
                  "taishin": _2,
                  "tamakawa": _2,
                  "tanagura": _2,
                  "tenei": _2,
                  "yabuki": _2,
                  "yamato": _2,
                  "yamatsuri": _2,
                  "yanaizu": _2,
                  "yugawa": _2
                }
              },
              "gifu": {
                "$": 1,
                "succ": {
                  "anpachi": _2,
                  "ena": _2,
                  "gifu": _2,
                  "ginan": _2,
                  "godo": _2,
                  "gujo": _2,
                  "hashima": _2,
                  "hichiso": _2,
                  "hida": _2,
                  "higashishirakawa": _2,
                  "ibigawa": _2,
                  "ikeda": _2,
                  "kakamigahara": _2,
                  "kani": _2,
                  "kasahara": _2,
                  "kasamatsu": _2,
                  "kawaue": _2,
                  "kitagata": _2,
                  "mino": _2,
                  "minokamo": _2,
                  "mitake": _2,
                  "mizunami": _2,
                  "motosu": _2,
                  "nakatsugawa": _2,
                  "ogaki": _2,
                  "sakahogi": _2,
                  "seki": _2,
                  "sekigahara": _2,
                  "shirakawa": _2,
                  "tajimi": _2,
                  "takayama": _2,
                  "tarui": _2,
                  "toki": _2,
                  "tomika": _2,
                  "wanouchi": _2,
                  "yamagata": _2,
                  "yaotsu": _2,
                  "yoro": _2
                }
              },
              "gunma": {
                "$": 1,
                "succ": {
                  "annaka": _2,
                  "chiyoda": _2,
                  "fujioka": _2,
                  "higashiagatsuma": _2,
                  "isesaki": _2,
                  "itakura": _2,
                  "kanna": _2,
                  "kanra": _2,
                  "katashina": _2,
                  "kawaba": _2,
                  "kiryu": _2,
                  "kusatsu": _2,
                  "maebashi": _2,
                  "meiwa": _2,
                  "midori": _2,
                  "minakami": _2,
                  "naganohara": _2,
                  "nakanojo": _2,
                  "nanmoku": _2,
                  "numata": _2,
                  "oizumi": _2,
                  "ora": _2,
                  "ota": _2,
                  "shibukawa": _2,
                  "shimonita": _2,
                  "shinto": _2,
                  "showa": _2,
                  "takasaki": _2,
                  "takayama": _2,
                  "tamamura": _2,
                  "tatebayashi": _2,
                  "tomioka": _2,
                  "tsukiyono": _2,
                  "tsumagoi": _2,
                  "ueno": _2,
                  "yoshioka": _2
                }
              },
              "hiroshima": {
                "$": 1,
                "succ": {
                  "asaminami": _2,
                  "daiwa": _2,
                  "etajima": _2,
                  "fuchu": _2,
                  "fukuyama": _2,
                  "hatsukaichi": _2,
                  "higashihiroshima": _2,
                  "hongo": _2,
                  "jinsekikogen": _2,
                  "kaita": _2,
                  "kui": _2,
                  "kumano": _2,
                  "kure": _2,
                  "mihara": _2,
                  "miyoshi": _2,
                  "naka": _2,
                  "onomichi": _2,
                  "osakikamijima": _2,
                  "otake": _2,
                  "saka": _2,
                  "sera": _2,
                  "seranishi": _2,
                  "shinichi": _2,
                  "shobara": _2,
                  "takehara": _2
                }
              },
              "hokkaido": {
                "$": 1,
                "succ": {
                  "abashiri": _2,
                  "abira": _2,
                  "aibetsu": _2,
                  "akabira": _2,
                  "akkeshi": _2,
                  "asahikawa": _2,
                  "ashibetsu": _2,
                  "ashoro": _2,
                  "assabu": _2,
                  "atsuma": _2,
                  "bibai": _2,
                  "biei": _2,
                  "bifuka": _2,
                  "bihoro": _2,
                  "biratori": _2,
                  "chippubetsu": _2,
                  "chitose": _2,
                  "date": _2,
                  "ebetsu": _2,
                  "embetsu": _2,
                  "eniwa": _2,
                  "erimo": _2,
                  "esan": _2,
                  "esashi": _2,
                  "fukagawa": _2,
                  "fukushima": _2,
                  "furano": _2,
                  "furubira": _2,
                  "haboro": _2,
                  "hakodate": _2,
                  "hamatonbetsu": _2,
                  "hidaka": _2,
                  "higashikagura": _2,
                  "higashikawa": _2,
                  "hiroo": _2,
                  "hokuryu": _2,
                  "hokuto": _2,
                  "honbetsu": _2,
                  "horokanai": _2,
                  "horonobe": _2,
                  "ikeda": _2,
                  "imakane": _2,
                  "ishikari": _2,
                  "iwamizawa": _2,
                  "iwanai": _2,
                  "kamifurano": _2,
                  "kamikawa": _2,
                  "kamishihoro": _2,
                  "kamisunagawa": _2,
                  "kamoenai": _2,
                  "kayabe": _2,
                  "kembuchi": _2,
                  "kikonai": _2,
                  "kimobetsu": _2,
                  "kitahiroshima": _2,
                  "kitami": _2,
                  "kiyosato": _2,
                  "koshimizu": _2,
                  "kunneppu": _2,
                  "kuriyama": _2,
                  "kuromatsunai": _2,
                  "kushiro": _2,
                  "kutchan": _2,
                  "kyowa": _2,
                  "mashike": _2,
                  "matsumae": _2,
                  "mikasa": _2,
                  "minamifurano": _2,
                  "mombetsu": _2,
                  "moseushi": _2,
                  "mukawa": _2,
                  "muroran": _2,
                  "naie": _2,
                  "nakagawa": _2,
                  "nakasatsunai": _2,
                  "nakatombetsu": _2,
                  "nanae": _2,
                  "nanporo": _2,
                  "nayoro": _2,
                  "nemuro": _2,
                  "niikappu": _2,
                  "niki": _2,
                  "nishiokoppe": _2,
                  "noboribetsu": _2,
                  "numata": _2,
                  "obihiro": _2,
                  "obira": _2,
                  "oketo": _2,
                  "okoppe": _2,
                  "otaru": _2,
                  "otobe": _2,
                  "otofuke": _2,
                  "otoineppu": _2,
                  "oumu": _2,
                  "ozora": _2,
                  "pippu": _2,
                  "rankoshi": _2,
                  "rebun": _2,
                  "rikubetsu": _2,
                  "rishiri": _2,
                  "rishirifuji": _2,
                  "saroma": _2,
                  "sarufutsu": _2,
                  "shakotan": _2,
                  "shari": _2,
                  "shibecha": _2,
                  "shibetsu": _2,
                  "shikabe": _2,
                  "shikaoi": _2,
                  "shimamaki": _2,
                  "shimizu": _2,
                  "shimokawa": _2,
                  "shinshinotsu": _2,
                  "shintoku": _2,
                  "shiranuka": _2,
                  "shiraoi": _2,
                  "shiriuchi": _2,
                  "sobetsu": _2,
                  "sunagawa": _2,
                  "taiki": _2,
                  "takasu": _2,
                  "takikawa": _2,
                  "takinoue": _2,
                  "teshikaga": _2,
                  "tobetsu": _2,
                  "tohma": _2,
                  "tomakomai": _2,
                  "tomari": _2,
                  "toya": _2,
                  "toyako": _2,
                  "toyotomi": _2,
                  "toyoura": _2,
                  "tsubetsu": _2,
                  "tsukigata": _2,
                  "urakawa": _2,
                  "urausu": _2,
                  "uryu": _2,
                  "utashinai": _2,
                  "wakkanai": _2,
                  "wassamu": _2,
                  "yakumo": _2,
                  "yoichi": _2
                }
              },
              "hyogo": {
                "$": 1,
                "succ": {
                  "aioi": _2,
                  "akashi": _2,
                  "ako": _2,
                  "amagasaki": _2,
                  "aogaki": _2,
                  "asago": _2,
                  "ashiya": _2,
                  "awaji": _2,
                  "fukusaki": _2,
                  "goshiki": _2,
                  "harima": _2,
                  "himeji": _2,
                  "ichikawa": _2,
                  "inagawa": _2,
                  "itami": _2,
                  "kakogawa": _2,
                  "kamigori": _2,
                  "kamikawa": _2,
                  "kasai": _2,
                  "kasuga": _2,
                  "kawanishi": _2,
                  "miki": _2,
                  "minamiawaji": _2,
                  "nishinomiya": _2,
                  "nishiwaki": _2,
                  "ono": _2,
                  "sanda": _2,
                  "sannan": _2,
                  "sasayama": _2,
                  "sayo": _2,
                  "shingu": _2,
                  "shinonsen": _2,
                  "shiso": _2,
                  "sumoto": _2,
                  "taishi": _2,
                  "taka": _2,
                  "takarazuka": _2,
                  "takasago": _2,
                  "takino": _2,
                  "tamba": _2,
                  "tatsuno": _2,
                  "toyooka": _2,
                  "yabu": _2,
                  "yashiro": _2,
                  "yoka": _2,
                  "yokawa": _2
                }
              },
              "ibaraki": {
                "$": 1,
                "succ": {
                  "ami": _2,
                  "asahi": _2,
                  "bando": _2,
                  "chikusei": _2,
                  "daigo": _2,
                  "fujishiro": _2,
                  "hitachi": _2,
                  "hitachinaka": _2,
                  "hitachiomiya": _2,
                  "hitachiota": _2,
                  "ibaraki": _2,
                  "ina": _2,
                  "inashiki": _2,
                  "itako": _2,
                  "iwama": _2,
                  "joso": _2,
                  "kamisu": _2,
                  "kasama": _2,
                  "kashima": _2,
                  "kasumigaura": _2,
                  "koga": _2,
                  "miho": _2,
                  "mito": _2,
                  "moriya": _2,
                  "naka": _2,
                  "namegata": _2,
                  "oarai": _2,
                  "ogawa": _2,
                  "omitama": _2,
                  "ryugasaki": _2,
                  "sakai": _2,
                  "sakuragawa": _2,
                  "shimodate": _2,
                  "shimotsuma": _2,
                  "shirosato": _2,
                  "sowa": _2,
                  "suifu": _2,
                  "takahagi": _2,
                  "tamatsukuri": _2,
                  "tokai": _2,
                  "tomobe": _2,
                  "tone": _2,
                  "toride": _2,
                  "tsuchiura": _2,
                  "tsukuba": _2,
                  "uchihara": _2,
                  "ushiku": _2,
                  "yachiyo": _2,
                  "yamagata": _2,
                  "yawara": _2,
                  "yuki": _2
                }
              },
              "ishikawa": {
                "$": 1,
                "succ": {
                  "anamizu": _2,
                  "hakui": _2,
                  "hakusan": _2,
                  "kaga": _2,
                  "kahoku": _2,
                  "kanazawa": _2,
                  "kawakita": _2,
                  "komatsu": _2,
                  "nakanoto": _2,
                  "nanao": _2,
                  "nomi": _2,
                  "nonoichi": _2,
                  "noto": _2,
                  "shika": _2,
                  "suzu": _2,
                  "tsubata": _2,
                  "tsurugi": _2,
                  "uchinada": _2,
                  "wajima": _2
                }
              },
              "iwate": {
                "$": 1,
                "succ": {
                  "fudai": _2,
                  "fujisawa": _2,
                  "hanamaki": _2,
                  "hiraizumi": _2,
                  "hirono": _2,
                  "ichinohe": _2,
                  "ichinoseki": _2,
                  "iwaizumi": _2,
                  "iwate": _2,
                  "joboji": _2,
                  "kamaishi": _2,
                  "kanegasaki": _2,
                  "karumai": _2,
                  "kawai": _2,
                  "kitakami": _2,
                  "kuji": _2,
                  "kunohe": _2,
                  "kuzumaki": _2,
                  "miyako": _2,
                  "mizusawa": _2,
                  "morioka": _2,
                  "ninohe": _2,
                  "noda": _2,
                  "ofunato": _2,
                  "oshu": _2,
                  "otsuchi": _2,
                  "rikuzentakata": _2,
                  "shiwa": _2,
                  "shizukuishi": _2,
                  "sumita": _2,
                  "tanohata": _2,
                  "tono": _2,
                  "yahaba": _2,
                  "yamada": _2
                }
              },
              "kagawa": {
                "$": 1,
                "succ": {
                  "ayagawa": _2,
                  "higashikagawa": _2,
                  "kanonji": _2,
                  "kotohira": _2,
                  "manno": _2,
                  "marugame": _2,
                  "mitoyo": _2,
                  "naoshima": _2,
                  "sanuki": _2,
                  "tadotsu": _2,
                  "takamatsu": _2,
                  "tonosho": _2,
                  "uchinomi": _2,
                  "utazu": _2,
                  "zentsuji": _2
                }
              },
              "kagoshima": {
                "$": 1,
                "succ": {
                  "akune": _2,
                  "amami": _2,
                  "hioki": _2,
                  "isa": _2,
                  "isen": _2,
                  "izumi": _2,
                  "kagoshima": _2,
                  "kanoya": _2,
                  "kawanabe": _2,
                  "kinko": _2,
                  "kouyama": _2,
                  "makurazaki": _2,
                  "matsumoto": _2,
                  "minamitane": _2,
                  "nakatane": _2,
                  "nishinoomote": _2,
                  "satsumasendai": _2,
                  "soo": _2,
                  "tarumizu": _2,
                  "yusui": _2
                }
              },
              "kanagawa": {
                "$": 1,
                "succ": {
                  "aikawa": _2,
                  "atsugi": _2,
                  "ayase": _2,
                  "chigasaki": _2,
                  "ebina": _2,
                  "fujisawa": _2,
                  "hadano": _2,
                  "hakone": _2,
                  "hiratsuka": _2,
                  "isehara": _2,
                  "kaisei": _2,
                  "kamakura": _2,
                  "kiyokawa": _2,
                  "matsuda": _2,
                  "minamiashigara": _2,
                  "miura": _2,
                  "nakai": _2,
                  "ninomiya": _2,
                  "odawara": _2,
                  "oi": _2,
                  "oiso": _2,
                  "sagamihara": _2,
                  "samukawa": _2,
                  "tsukui": _2,
                  "yamakita": _2,
                  "yamato": _2,
                  "yokosuka": _2,
                  "yugawara": _2,
                  "zama": _2,
                  "zushi": _2
                }
              },
              "kochi": {
                "$": 1,
                "succ": {
                  "aki": _2,
                  "geisei": _2,
                  "hidaka": _2,
                  "higashitsuno": _2,
                  "ino": _2,
                  "kagami": _2,
                  "kami": _2,
                  "kitagawa": _2,
                  "kochi": _2,
                  "mihara": _2,
                  "motoyama": _2,
                  "muroto": _2,
                  "nahari": _2,
                  "nakamura": _2,
                  "nankoku": _2,
                  "nishitosa": _2,
                  "niyodogawa": _2,
                  "ochi": _2,
                  "okawa": _2,
                  "otoyo": _2,
                  "otsuki": _2,
                  "sakawa": _2,
                  "sukumo": _2,
                  "susaki": _2,
                  "tosa": _2,
                  "tosashimizu": _2,
                  "toyo": _2,
                  "tsuno": _2,
                  "umaji": _2,
                  "yasuda": _2,
                  "yusuhara": _2
                }
              },
              "kumamoto": {
                "$": 1,
                "succ": {
                  "amakusa": _2,
                  "arao": _2,
                  "aso": _2,
                  "choyo": _2,
                  "gyokuto": _2,
                  "kamiamakusa": _2,
                  "kikuchi": _2,
                  "kumamoto": _2,
                  "mashiki": _2,
                  "mifune": _2,
                  "minamata": _2,
                  "minamioguni": _2,
                  "nagasu": _2,
                  "nishihara": _2,
                  "oguni": _2,
                  "ozu": _2,
                  "sumoto": _2,
                  "takamori": _2,
                  "uki": _2,
                  "uto": _2,
                  "yamaga": _2,
                  "yamato": _2,
                  "yatsushiro": _2
                }
              },
              "kyoto": {
                "$": 1,
                "succ": {
                  "ayabe": _2,
                  "fukuchiyama": _2,
                  "higashiyama": _2,
                  "ide": _2,
                  "ine": _2,
                  "joyo": _2,
                  "kameoka": _2,
                  "kamo": _2,
                  "kita": _2,
                  "kizu": _2,
                  "kumiyama": _2,
                  "kyotamba": _2,
                  "kyotanabe": _2,
                  "kyotango": _2,
                  "maizuru": _2,
                  "minami": _2,
                  "minamiyamashiro": _2,
                  "miyazu": _2,
                  "muko": _2,
                  "nagaokakyo": _2,
                  "nakagyo": _2,
                  "nantan": _2,
                  "oyamazaki": _2,
                  "sakyo": _2,
                  "seika": _2,
                  "tanabe": _2,
                  "uji": _2,
                  "ujitawara": _2,
                  "wazuka": _2,
                  "yamashina": _2,
                  "yawata": _2
                }
              },
              "mie": {
                "$": 1,
                "succ": {
                  "asahi": _2,
                  "inabe": _2,
                  "ise": _2,
                  "kameyama": _2,
                  "kawagoe": _2,
                  "kiho": _2,
                  "kisosaki": _2,
                  "kiwa": _2,
                  "komono": _2,
                  "kumano": _2,
                  "kuwana": _2,
                  "matsusaka": _2,
                  "meiwa": _2,
                  "mihama": _2,
                  "minamiise": _2,
                  "misugi": _2,
                  "miyama": _2,
                  "nabari": _2,
                  "shima": _2,
                  "suzuka": _2,
                  "tado": _2,
                  "taiki": _2,
                  "taki": _2,
                  "tamaki": _2,
                  "toba": _2,
                  "tsu": _2,
                  "udono": _2,
                  "ureshino": _2,
                  "watarai": _2,
                  "yokkaichi": _2
                }
              },
              "miyagi": {
                "$": 1,
                "succ": {
                  "furukawa": _2,
                  "higashimatsushima": _2,
                  "ishinomaki": _2,
                  "iwanuma": _2,
                  "kakuda": _2,
                  "kami": _2,
                  "kawasaki": _2,
                  "marumori": _2,
                  "matsushima": _2,
                  "minamisanriku": _2,
                  "misato": _2,
                  "murata": _2,
                  "natori": _2,
                  "ogawara": _2,
                  "ohira": _2,
                  "onagawa": _2,
                  "osaki": _2,
                  "rifu": _2,
                  "semine": _2,
                  "shibata": _2,
                  "shichikashuku": _2,
                  "shikama": _2,
                  "shiogama": _2,
                  "shiroishi": _2,
                  "tagajo": _2,
                  "taiwa": _2,
                  "tome": _2,
                  "tomiya": _2,
                  "wakuya": _2,
                  "watari": _2,
                  "yamamoto": _2,
                  "zao": _2
                }
              },
              "miyazaki": {
                "$": 1,
                "succ": {
                  "aya": _2,
                  "ebino": _2,
                  "gokase": _2,
                  "hyuga": _2,
                  "kadogawa": _2,
                  "kawaminami": _2,
                  "kijo": _2,
                  "kitagawa": _2,
                  "kitakata": _2,
                  "kitaura": _2,
                  "kobayashi": _2,
                  "kunitomi": _2,
                  "kushima": _2,
                  "mimata": _2,
                  "miyakonojo": _2,
                  "miyazaki": _2,
                  "morotsuka": _2,
                  "nichinan": _2,
                  "nishimera": _2,
                  "nobeoka": _2,
                  "saito": _2,
                  "shiiba": _2,
                  "shintomi": _2,
                  "takaharu": _2,
                  "takanabe": _2,
                  "takazaki": _2,
                  "tsuno": _2
                }
              },
              "nagano": {
                "$": 1,
                "succ": {
                  "achi": _2,
                  "agematsu": _2,
                  "anan": _2,
                  "aoki": _2,
                  "asahi": _2,
                  "azumino": _2,
                  "chikuhoku": _2,
                  "chikuma": _2,
                  "chino": _2,
                  "fujimi": _2,
                  "hakuba": _2,
                  "hara": _2,
                  "hiraya": _2,
                  "iida": _2,
                  "iijima": _2,
                  "iiyama": _2,
                  "iizuna": _2,
                  "ikeda": _2,
                  "ikusaka": _2,
                  "ina": _2,
                  "karuizawa": _2,
                  "kawakami": _2,
                  "kiso": _2,
                  "kisofukushima": _2,
                  "kitaaiki": _2,
                  "komagane": _2,
                  "komoro": _2,
                  "matsukawa": _2,
                  "matsumoto": _2,
                  "miasa": _2,
                  "minamiaiki": _2,
                  "minamimaki": _2,
                  "minamiminowa": _2,
                  "minowa": _2,
                  "miyada": _2,
                  "miyota": _2,
                  "mochizuki": _2,
                  "nagano": _2,
                  "nagawa": _2,
                  "nagiso": _2,
                  "nakagawa": _2,
                  "nakano": _2,
                  "nozawaonsen": _2,
                  "obuse": _2,
                  "ogawa": _2,
                  "okaya": _2,
                  "omachi": _2,
                  "omi": _2,
                  "ookuwa": _2,
                  "ooshika": _2,
                  "otaki": _2,
                  "otari": _2,
                  "sakae": _2,
                  "sakaki": _2,
                  "saku": _2,
                  "sakuho": _2,
                  "shimosuwa": _2,
                  "shinanomachi": _2,
                  "shiojiri": _2,
                  "suwa": _2,
                  "suzaka": _2,
                  "takagi": _2,
                  "takamori": _2,
                  "takayama": _2,
                  "tateshina": _2,
                  "tatsuno": _2,
                  "togakushi": _2,
                  "togura": _2,
                  "tomi": _2,
                  "ueda": _2,
                  "wada": _2,
                  "yamagata": _2,
                  "yamanouchi": _2,
                  "yasaka": _2,
                  "yasuoka": _2
                }
              },
              "nagasaki": {
                "$": 1,
                "succ": {
                  "chijiwa": _2,
                  "futsu": _2,
                  "goto": _2,
                  "hasami": _2,
                  "hirado": _2,
                  "iki": _2,
                  "isahaya": _2,
                  "kawatana": _2,
                  "kuchinotsu": _2,
                  "matsuura": _2,
                  "nagasaki": _2,
                  "obama": _2,
                  "omura": _2,
                  "oseto": _2,
                  "saikai": _2,
                  "sasebo": _2,
                  "seihi": _2,
                  "shimabara": _2,
                  "shinkamigoto": _2,
                  "togitsu": _2,
                  "tsushima": _2,
                  "unzen": _2
                }
              },
              "nara": {
                "$": 1,
                "succ": {
                  "ando": _2,
                  "gose": _2,
                  "heguri": _2,
                  "higashiyoshino": _2,
                  "ikaruga": _2,
                  "ikoma": _2,
                  "kamikitayama": _2,
                  "kanmaki": _2,
                  "kashiba": _2,
                  "kashihara": _2,
                  "katsuragi": _2,
                  "kawai": _2,
                  "kawakami": _2,
                  "kawanishi": _2,
                  "koryo": _2,
                  "kurotaki": _2,
                  "mitsue": _2,
                  "miyake": _2,
                  "nara": _2,
                  "nosegawa": _2,
                  "oji": _2,
                  "ouda": _2,
                  "oyodo": _2,
                  "sakurai": _2,
                  "sango": _2,
                  "shimoichi": _2,
                  "shimokitayama": _2,
                  "shinjo": _2,
                  "soni": _2,
                  "takatori": _2,
                  "tawaramoto": _2,
                  "tenkawa": _2,
                  "tenri": _2,
                  "uda": _2,
                  "yamatokoriyama": _2,
                  "yamatotakada": _2,
                  "yamazoe": _2,
                  "yoshino": _2
                }
              },
              "niigata": {
                "$": 1,
                "succ": {
                  "aga": _2,
                  "agano": _2,
                  "gosen": _2,
                  "itoigawa": _2,
                  "izumozaki": _2,
                  "joetsu": _2,
                  "kamo": _2,
                  "kariwa": _2,
                  "kashiwazaki": _2,
                  "minamiuonuma": _2,
                  "mitsuke": _2,
                  "muika": _2,
                  "murakami": _2,
                  "myoko": _2,
                  "nagaoka": _2,
                  "niigata": _2,
                  "ojiya": _2,
                  "omi": _2,
                  "sado": _2,
                  "sanjo": _2,
                  "seiro": _2,
                  "seirou": _2,
                  "sekikawa": _2,
                  "shibata": _2,
                  "tagami": _2,
                  "tainai": _2,
                  "tochio": _2,
                  "tokamachi": _2,
                  "tsubame": _2,
                  "tsunan": _2,
                  "uonuma": _2,
                  "yahiko": _2,
                  "yoita": _2,
                  "yuzawa": _2
                }
              },
              "oita": {
                "$": 1,
                "succ": {
                  "beppu": _2,
                  "bungoono": _2,
                  "bungotakada": _2,
                  "hasama": _2,
                  "hiji": _2,
                  "himeshima": _2,
                  "hita": _2,
                  "kamitsue": _2,
                  "kokonoe": _2,
                  "kuju": _2,
                  "kunisaki": _2,
                  "kusu": _2,
                  "oita": _2,
                  "saiki": _2,
                  "taketa": _2,
                  "tsukumi": _2,
                  "usa": _2,
                  "usuki": _2,
                  "yufu": _2
                }
              },
              "okayama": {
                "$": 1,
                "succ": {
                  "akaiwa": _2,
                  "asakuchi": _2,
                  "bizen": _2,
                  "hayashima": _2,
                  "ibara": _2,
                  "kagamino": _2,
                  "kasaoka": _2,
                  "kibichuo": _2,
                  "kumenan": _2,
                  "kurashiki": _2,
                  "maniwa": _2,
                  "misaki": _2,
                  "nagi": _2,
                  "niimi": _2,
                  "nishiawakura": _2,
                  "okayama": _2,
                  "satosho": _2,
                  "setouchi": _2,
                  "shinjo": _2,
                  "shoo": _2,
                  "soja": _2,
                  "takahashi": _2,
                  "tamano": _2,
                  "tsuyama": _2,
                  "wake": _2,
                  "yakage": _2
                }
              },
              "okinawa": {
                "$": 1,
                "succ": {
                  "aguni": _2,
                  "ginowan": _2,
                  "ginoza": _2,
                  "gushikami": _2,
                  "haebaru": _2,
                  "higashi": _2,
                  "hirara": _2,
                  "iheya": _2,
                  "ishigaki": _2,
                  "ishikawa": _2,
                  "itoman": _2,
                  "izena": _2,
                  "kadena": _2,
                  "kin": _2,
                  "kitadaito": _2,
                  "kitanakagusuku": _2,
                  "kumejima": _2,
                  "kunigami": _2,
                  "minamidaito": _2,
                  "motobu": _2,
                  "nago": _2,
                  "naha": _2,
                  "nakagusuku": _2,
                  "nakijin": _2,
                  "nanjo": _2,
                  "nishihara": _2,
                  "ogimi": _2,
                  "okinawa": _2,
                  "onna": _2,
                  "shimoji": _2,
                  "taketomi": _2,
                  "tarama": _2,
                  "tokashiki": _2,
                  "tomigusuku": _2,
                  "tonaki": _2,
                  "urasoe": _2,
                  "uruma": _2,
                  "yaese": _2,
                  "yomitan": _2,
                  "yonabaru": _2,
                  "yonaguni": _2,
                  "zamami": _2
                }
              },
              "osaka": {
                "$": 1,
                "succ": {
                  "abeno": _2,
                  "chihayaakasaka": _2,
                  "chuo": _2,
                  "daito": _2,
                  "fujiidera": _2,
                  "habikino": _2,
                  "hannan": _2,
                  "higashiosaka": _2,
                  "higashisumiyoshi": _2,
                  "higashiyodogawa": _2,
                  "hirakata": _2,
                  "ibaraki": _2,
                  "ikeda": _2,
                  "izumi": _2,
                  "izumiotsu": _2,
                  "izumisano": _2,
                  "kadoma": _2,
                  "kaizuka": _2,
                  "kanan": _2,
                  "kashiwara": _2,
                  "katano": _2,
                  "kawachinagano": _2,
                  "kishiwada": _2,
                  "kita": _2,
                  "kumatori": _2,
                  "matsubara": _2,
                  "minato": _2,
                  "minoh": _2,
                  "misaki": _2,
                  "moriguchi": _2,
                  "neyagawa": _2,
                  "nishi": _2,
                  "nose": _2,
                  "osakasayama": _2,
                  "sakai": _2,
                  "sayama": _2,
                  "sennan": _2,
                  "settsu": _2,
                  "shijonawate": _2,
                  "shimamoto": _2,
                  "suita": _2,
                  "tadaoka": _2,
                  "taishi": _2,
                  "tajiri": _2,
                  "takaishi": _2,
                  "takatsuki": _2,
                  "tondabayashi": _2,
                  "toyonaka": _2,
                  "toyono": _2,
                  "yao": _2
                }
              },
              "saga": {
                "$": 1,
                "succ": {
                  "ariake": _2,
                  "arita": _2,
                  "fukudomi": _2,
                  "genkai": _2,
                  "hamatama": _2,
                  "hizen": _2,
                  "imari": _2,
                  "kamimine": _2,
                  "kanzaki": _2,
                  "karatsu": _2,
                  "kashima": _2,
                  "kitagata": _2,
                  "kitahata": _2,
                  "kiyama": _2,
                  "kouhoku": _2,
                  "kyuragi": _2,
                  "nishiarita": _2,
                  "ogi": _2,
                  "omachi": _2,
                  "ouchi": _2,
                  "saga": _2,
                  "shiroishi": _2,
                  "taku": _2,
                  "tara": _2,
                  "tosu": _2,
                  "yoshinogari": _2
                }
              },
              "saitama": {
                "$": 1,
                "succ": {
                  "arakawa": _2,
                  "asaka": _2,
                  "chichibu": _2,
                  "fujimi": _2,
                  "fujimino": _2,
                  "fukaya": _2,
                  "hanno": _2,
                  "hanyu": _2,
                  "hasuda": _2,
                  "hatogaya": _2,
                  "hatoyama": _2,
                  "hidaka": _2,
                  "higashichichibu": _2,
                  "higashimatsuyama": _2,
                  "honjo": _2,
                  "ina": _2,
                  "iruma": _2,
                  "iwatsuki": _2,
                  "kamiizumi": _2,
                  "kamikawa": _2,
                  "kamisato": _2,
                  "kasukabe": _2,
                  "kawagoe": _2,
                  "kawaguchi": _2,
                  "kawajima": _2,
                  "kazo": _2,
                  "kitamoto": _2,
                  "koshigaya": _2,
                  "kounosu": _2,
                  "kuki": _2,
                  "kumagaya": _2,
                  "matsubushi": _2,
                  "minano": _2,
                  "misato": _2,
                  "miyashiro": _2,
                  "miyoshi": _2,
                  "moroyama": _2,
                  "nagatoro": _2,
                  "namegawa": _2,
                  "niiza": _2,
                  "ogano": _2,
                  "ogawa": _2,
                  "ogose": _2,
                  "okegawa": _2,
                  "omiya": _2,
                  "otaki": _2,
                  "ranzan": _2,
                  "ryokami": _2,
                  "saitama": _2,
                  "sakado": _2,
                  "satte": _2,
                  "sayama": _2,
                  "shiki": _2,
                  "shiraoka": _2,
                  "soka": _2,
                  "sugito": _2,
                  "toda": _2,
                  "tokigawa": _2,
                  "tokorozawa": _2,
                  "tsurugashima": _2,
                  "urawa": _2,
                  "warabi": _2,
                  "yashio": _2,
                  "yokoze": _2,
                  "yono": _2,
                  "yorii": _2,
                  "yoshida": _2,
                  "yoshikawa": _2,
                  "yoshimi": _2
                }
              },
              "shiga": {
                "$": 1,
                "succ": {
                  "aisho": _2,
                  "gamo": _2,
                  "higashiomi": _2,
                  "hikone": _2,
                  "koka": _2,
                  "konan": _2,
                  "kosei": _2,
                  "koto": _2,
                  "kusatsu": _2,
                  "maibara": _2,
                  "moriyama": _2,
                  "nagahama": _2,
                  "nishiazai": _2,
                  "notogawa": _2,
                  "omihachiman": _2,
                  "otsu": _2,
                  "ritto": _2,
                  "ryuoh": _2,
                  "takashima": _2,
                  "takatsuki": _2,
                  "torahime": _2,
                  "toyosato": _2,
                  "yasu": _2
                }
              },
              "shimane": {
                "$": 1,
                "succ": {
                  "akagi": _2,
                  "ama": _2,
                  "gotsu": _2,
                  "hamada": _2,
                  "higashiizumo": _2,
                  "hikawa": _2,
                  "hikimi": _2,
                  "izumo": _2,
                  "kakinoki": _2,
                  "masuda": _2,
                  "matsue": _2,
                  "misato": _2,
                  "nishinoshima": _2,
                  "ohda": _2,
                  "okinoshima": _2,
                  "okuizumo": _2,
                  "shimane": _2,
                  "tamayu": _2,
                  "tsuwano": _2,
                  "unnan": _2,
                  "yakumo": _2,
                  "yasugi": _2,
                  "yatsuka": _2
                }
              },
              "shizuoka": {
                "$": 1,
                "succ": {
                  "arai": _2,
                  "atami": _2,
                  "fuji": _2,
                  "fujieda": _2,
                  "fujikawa": _2,
                  "fujinomiya": _2,
                  "fukuroi": _2,
                  "gotemba": _2,
                  "haibara": _2,
                  "hamamatsu": _2,
                  "higashiizu": _2,
                  "ito": _2,
                  "iwata": _2,
                  "izu": _2,
                  "izunokuni": _2,
                  "kakegawa": _2,
                  "kannami": _2,
                  "kawanehon": _2,
                  "kawazu": _2,
                  "kikugawa": _2,
                  "kosai": _2,
                  "makinohara": _2,
                  "matsuzaki": _2,
                  "minamiizu": _2,
                  "mishima": _2,
                  "morimachi": _2,
                  "nishiizu": _2,
                  "numazu": _2,
                  "omaezaki": _2,
                  "shimada": _2,
                  "shimizu": _2,
                  "shimoda": _2,
                  "shizuoka": _2,
                  "susono": _2,
                  "yaizu": _2,
                  "yoshida": _2
                }
              },
              "tochigi": {
                "$": 1,
                "succ": {
                  "ashikaga": _2,
                  "bato": _2,
                  "haga": _2,
                  "ichikai": _2,
                  "iwafune": _2,
                  "kaminokawa": _2,
                  "kanuma": _2,
                  "karasuyama": _2,
                  "kuroiso": _2,
                  "mashiko": _2,
                  "mibu": _2,
                  "moka": _2,
                  "motegi": _2,
                  "nasu": _2,
                  "nasushiobara": _2,
                  "nikko": _2,
                  "nishikata": _2,
                  "nogi": _2,
                  "ohira": _2,
                  "ohtawara": _2,
                  "oyama": _2,
                  "sakura": _2,
                  "sano": _2,
                  "shimotsuke": _2,
                  "shioya": _2,
                  "takanezawa": _2,
                  "tochigi": _2,
                  "tsuga": _2,
                  "ujiie": _2,
                  "utsunomiya": _2,
                  "yaita": _2
                }
              },
              "tokushima": {
                "$": 1,
                "succ": {
                  "aizumi": _2,
                  "anan": _2,
                  "ichiba": _2,
                  "itano": _2,
                  "kainan": _2,
                  "komatsushima": _2,
                  "matsushige": _2,
                  "mima": _2,
                  "minami": _2,
                  "miyoshi": _2,
                  "mugi": _2,
                  "nakagawa": _2,
                  "naruto": _2,
                  "sanagochi": _2,
                  "shishikui": _2,
                  "tokushima": _2,
                  "wajiki": _2
                }
              },
              "tokyo": {
                "$": 1,
                "succ": {
                  "adachi": _2,
                  "akiruno": _2,
                  "akishima": _2,
                  "aogashima": _2,
                  "arakawa": _2,
                  "bunkyo": _2,
                  "chiyoda": _2,
                  "chofu": _2,
                  "chuo": _2,
                  "edogawa": _2,
                  "fuchu": _2,
                  "fussa": _2,
                  "hachijo": _2,
                  "hachioji": _2,
                  "hamura": _2,
                  "higashikurume": _2,
                  "higashimurayama": _2,
                  "higashiyamato": _2,
                  "hino": _2,
                  "hinode": _2,
                  "hinohara": _2,
                  "inagi": _2,
                  "itabashi": _2,
                  "katsushika": _2,
                  "kita": _2,
                  "kiyose": _2,
                  "kodaira": _2,
                  "koganei": _2,
                  "kokubunji": _2,
                  "komae": _2,
                  "koto": _2,
                  "kouzushima": _2,
                  "kunitachi": _2,
                  "machida": _2,
                  "meguro": _2,
                  "minato": _2,
                  "mitaka": _2,
                  "mizuho": _2,
                  "musashimurayama": _2,
                  "musashino": _2,
                  "nakano": _2,
                  "nerima": _2,
                  "ogasawara": _2,
                  "okutama": _2,
                  "ome": _2,
                  "oshima": _2,
                  "ota": _2,
                  "setagaya": _2,
                  "shibuya": _2,
                  "shinagawa": _2,
                  "shinjuku": _2,
                  "suginami": _2,
                  "sumida": _2,
                  "tachikawa": _2,
                  "taito": _2,
                  "tama": _2,
                  "toshima": _2
                }
              },
              "tottori": {
                "$": 1,
                "succ": {
                  "chizu": _2,
                  "hino": _2,
                  "kawahara": _2,
                  "koge": _2,
                  "kotoura": _2,
                  "misasa": _2,
                  "nanbu": _2,
                  "nichinan": _2,
                  "sakaiminato": _2,
                  "tottori": _2,
                  "wakasa": _2,
                  "yazu": _2,
                  "yonago": _2
                }
              },
              "toyama": {
                "$": 1,
                "succ": {
                  "asahi": _2,
                  "fuchu": _2,
                  "fukumitsu": _2,
                  "funahashi": _2,
                  "himi": _2,
                  "imizu": _2,
                  "inami": _2,
                  "johana": _2,
                  "kamiichi": _2,
                  "kurobe": _2,
                  "nakaniikawa": _2,
                  "namerikawa": _2,
                  "nanto": _2,
                  "nyuzen": _2,
                  "oyabe": _2,
                  "taira": _2,
                  "takaoka": _2,
                  "tateyama": _2,
                  "toga": _2,
                  "tonami": _2,
                  "toyama": _2,
                  "unazuki": _2,
                  "uozu": _2,
                  "yamada": _2
                }
              },
              "wakayama": {
                "$": 1,
                "succ": {
                  "arida": _2,
                  "aridagawa": _2,
                  "gobo": _2,
                  "hashimoto": _2,
                  "hidaka": _2,
                  "hirogawa": _2,
                  "inami": _2,
                  "iwade": _2,
                  "kainan": _2,
                  "kamitonda": _2,
                  "katsuragi": _2,
                  "kimino": _2,
                  "kinokawa": _2,
                  "kitayama": _2,
                  "koya": _2,
                  "koza": _2,
                  "kozagawa": _2,
                  "kudoyama": _2,
                  "kushimoto": _2,
                  "mihama": _2,
                  "misato": _2,
                  "nachikatsuura": _2,
                  "shingu": _2,
                  "shirahama": _2,
                  "taiji": _2,
                  "tanabe": _2,
                  "wakayama": _2,
                  "yuasa": _2,
                  "yura": _2
                }
              },
              "yamagata": {
                "$": 1,
                "succ": {
                  "asahi": _2,
                  "funagata": _2,
                  "higashine": _2,
                  "iide": _2,
                  "kahoku": _2,
                  "kaminoyama": _2,
                  "kaneyama": _2,
                  "kawanishi": _2,
                  "mamurogawa": _2,
                  "mikawa": _2,
                  "murayama": _2,
                  "nagai": _2,
                  "nakayama": _2,
                  "nanyo": _2,
                  "nishikawa": _2,
                  "obanazawa": _2,
                  "oe": _2,
                  "oguni": _2,
                  "ohkura": _2,
                  "oishida": _2,
                  "sagae": _2,
                  "sakata": _2,
                  "sakegawa": _2,
                  "shinjo": _2,
                  "shirataka": _2,
                  "shonai": _2,
                  "takahata": _2,
                  "tendo": _2,
                  "tozawa": _2,
                  "tsuruoka": _2,
                  "yamagata": _2,
                  "yamanobe": _2,
                  "yonezawa": _2,
                  "yuza": _2
                }
              },
              "yamaguchi": {
                "$": 1,
                "succ": {
                  "abu": _2,
                  "hagi": _2,
                  "hikari": _2,
                  "hofu": _2,
                  "iwakuni": _2,
                  "kudamatsu": _2,
                  "mitou": _2,
                  "nagato": _2,
                  "oshima": _2,
                  "shimonoseki": _2,
                  "shunan": _2,
                  "tabuse": _2,
                  "tokuyama": _2,
                  "toyota": _2,
                  "ube": _2,
                  "yuu": _2
                }
              },
              "yamanashi": {
                "$": 1,
                "succ": {
                  "chuo": _2,
                  "doshi": _2,
                  "fuefuki": _2,
                  "fujikawa": _2,
                  "fujikawaguchiko": _2,
                  "fujiyoshida": _2,
                  "hayakawa": _2,
                  "hokuto": _2,
                  "ichikawamisato": _2,
                  "kai": _2,
                  "kofu": _2,
                  "koshu": _2,
                  "kosuge": _2,
                  "minami-alps": _2,
                  "minobu": _2,
                  "nakamichi": _2,
                  "nanbu": _2,
                  "narusawa": _2,
                  "nirasaki": _2,
                  "nishikatsura": _2,
                  "oshino": _2,
                  "otsuki": _2,
                  "showa": _2,
                  "tabayama": _2,
                  "tsuru": _2,
                  "uenohara": _2,
                  "yamanakako": _2,
                  "yamanashi": _2
                }
              },
              "xn--4pvxs": _2,
              "栃木": _2,
              "xn--vgu402c": _2,
              "愛知": _2,
              "xn--c3s14m": _2,
              "愛媛": _2,
              "xn--f6qx53a": _2,
              "兵庫": _2,
              "xn--8pvr4u": _2,
              "熊本": _2,
              "xn--uist22h": _2,
              "茨城": _2,
              "xn--djrs72d6uy": _2,
              "北海道": _2,
              "xn--mkru45i": _2,
              "千葉": _2,
              "xn--0trq7p7nn": _2,
              "和歌山": _2,
              "xn--8ltr62k": _2,
              "長崎": _2,
              "xn--2m4a15e": _2,
              "長野": _2,
              "xn--efvn9s": _2,
              "新潟": _2,
              "xn--32vp30h": _2,
              "青森": _2,
              "xn--4it797k": _2,
              "静岡": _2,
              "xn--1lqs71d": _2,
              "東京": _2,
              "xn--5rtp49c": _2,
              "石川": _2,
              "xn--5js045d": _2,
              "埼玉": _2,
              "xn--ehqz56n": _2,
              "三重": _2,
              "xn--1lqs03n": _2,
              "京都": _2,
              "xn--qqqt11m": _2,
              "佐賀": _2,
              "xn--kbrq7o": _2,
              "大分": _2,
              "xn--pssu33l": _2,
              "大阪": _2,
              "xn--ntsq17g": _2,
              "奈良": _2,
              "xn--uisz3g": _2,
              "宮城": _2,
              "xn--6btw5a": _2,
              "宮崎": _2,
              "xn--1ctwo": _2,
              "富山": _2,
              "xn--6orx2r": _2,
              "山口": _2,
              "xn--rht61e": _2,
              "山形": _2,
              "xn--rht27z": _2,
              "山梨": _2,
              "xn--djty4k": _2,
              "岩手": _2,
              "xn--nit225k": _2,
              "岐阜": _2,
              "xn--rht3d": _2,
              "岡山": _2,
              "xn--klty5x": _2,
              "島根": _2,
              "xn--kltx9a": _2,
              "広島": _2,
              "xn--kltp7d": _2,
              "徳島": _2,
              "xn--uuwu58a": _2,
              "沖縄": _2,
              "xn--zbx025d": _2,
              "滋賀": _2,
              "xn--ntso0iqx3a": _2,
              "神奈川": _2,
              "xn--elqq16h": _2,
              "福井": _2,
              "xn--4it168d": _2,
              "福岡": _2,
              "xn--klt787d": _2,
              "福島": _2,
              "xn--rny31h": _2,
              "秋田": _2,
              "xn--7t0a264c": _2,
              "群馬": _2,
              "xn--5rtq34k": _2,
              "香川": _2,
              "xn--k7yn95e": _2,
              "高知": _2,
              "xn--tor131o": _2,
              "鳥取": _2,
              "xn--d5qv7z876c": _2,
              "鹿児島": _2,
              "kawasaki": _8,
              "kitakyushu": _8,
              "kobe": _8,
              "nagoya": _8,
              "sapporo": _8,
              "sendai": _8,
              "yokohama": _8,
              "buyshop": _3,
              "fashionstore": _3,
              "handcrafted": _3,
              "kawaiishop": _3,
              "supersale": _3,
              "theshop": _3,
              "usercontent": _3,
              "angry": _3,
              "babyblue": _3,
              "babymilk": _3,
              "backdrop": _3,
              "bambina": _3,
              "bitter": _3,
              "blush": _3,
              "boo": _3,
              "boy": _3,
              "boyfriend": _3,
              "but": _3,
              "candypop": _3,
              "capoo": _3,
              "catfood": _3,
              "cheap": _3,
              "chicappa": _3,
              "chillout": _3,
              "chips": _3,
              "chowder": _3,
              "chu": _3,
              "ciao": _3,
              "cocotte": _3,
              "coolblog": _3,
              "cranky": _3,
              "cutegirl": _3,
              "daa": _3,
              "deca": _3,
              "deci": _3,
              "digick": _3,
              "egoism": _3,
              "fakefur": _3,
              "fem": _3,
              "flier": _3,
              "floppy": _3,
              "fool": _3,
              "frenchkiss": _3,
              "girlfriend": _3,
              "girly": _3,
              "gloomy": _3,
              "gonna": _3,
              "greater": _3,
              "hacca": _3,
              "heavy": _3,
              "her": _3,
              "hiho": _3,
              "hippy": _3,
              "holy": _3,
              "hungry": _3,
              "icurus": _3,
              "itigo": _3,
              "jellybean": _3,
              "kikirara": _3,
              "kill": _3,
              "kilo": _3,
              "kuron": _3,
              "littlestar": _3,
              "lolipopmc": _3,
              "lolitapunk": _3,
              "lomo": _3,
              "lovepop": _3,
              "lovesick": _3,
              "main": _3,
              "mods": _3,
              "mond": _3,
              "mongolian": _3,
              "moo": _3,
              "namaste": _3,
              "nikita": _3,
              "nobushi": _3,
              "noor": _3,
              "oops": _3,
              "parallel": _3,
              "parasite": _3,
              "pecori": _3,
              "peewee": _3,
              "penne": _3,
              "pepper": _3,
              "perma": _3,
              "pigboat": _3,
              "pinoko": _3,
              "punyu": _3,
              "pupu": _3,
              "pussycat": _3,
              "pya": _3,
              "raindrop": _3,
              "readymade": _3,
              "sadist": _3,
              "schoolbus": _3,
              "secret": _3,
              "staba": _3,
              "stripper": _3,
              "sub": _3,
              "sunnyday": _3,
              "thick": _3,
              "tonkotsu": _3,
              "under": _3,
              "upper": _3,
              "velvet": _3,
              "verse": _3,
              "versus": _3,
              "vivian": _3,
              "watson": _3,
              "weblike": _3,
              "whitesnow": _3,
              "zombie": _3,
              "blogspot": _3,
              "2-d": _3,
              "bona": _3,
              "crap": _3,
              "daynight": _3,
              "eek": _3,
              "flop": _3,
              "halfmoon": _3,
              "jeez": _3,
              "matrix": _3,
              "mimoza": _3,
              "netgamers": _3,
              "nyanta": _3,
              "o0o0": _3,
              "rdy": _3,
              "rgr": _3,
              "rulez": _3,
              "sakurastorage": {
                "$": 0,
                "succ": {
                  "isk01": _12,
                  "isk02": _12
                }
              },
              "saloon": _3,
              "sblo": _3,
              "skr": _3,
              "tank": _3,
              "uh-oh": _3,
              "undo": _3,
              "webaccel": {
                "$": 0,
                "succ": {
                  "rs": _3,
                  "user": _3
                }
              },
              "websozai": _3,
              "xii": _3
            }
          },
          "ke": {
            "$": 1,
            "succ": {
              "ac": _2,
              "co": _6,
              "go": _2,
              "info": _2,
              "me": _2,
              "mobi": _2,
              "ne": _2,
              "or": _2,
              "sc": _2
            }
          },
          "kg": {
            "$": 1,
            "succ": {
              "org": _2,
              "net": _2,
              "com": _2,
              "edu": _2,
              "gov": _2,
              "mil": _2,
              "blog": _3,
              "io": _3,
              "jp": _3,
              "tv": _3,
              "uk": _3,
              "us": _3
            }
          },
          "kh": _8,
          "ki": _33,
          "km": {
            "$": 1,
            "succ": {
              "org": _2,
              "nom": _2,
              "gov": _2,
              "prd": _2,
              "tm": _2,
              "edu": _2,
              "mil": _2,
              "ass": _2,
              "com": _2,
              "coop": _2,
              "asso": _2,
              "presse": _2,
              "medecin": _2,
              "notaires": _2,
              "pharmaciens": _2,
              "veterinaire": _2,
              "gouv": _2
            }
          },
          "kn": {
            "$": 1,
            "succ": {
              "net": _2,
              "org": _2,
              "edu": _2,
              "gov": _2
            }
          },
          "kp": {
            "$": 1,
            "succ": {
              "com": _2,
              "edu": _2,
              "gov": _2,
              "org": _2,
              "rep": _2,
              "tra": _2
            }
          },
          "kr": {
            "$": 1,
            "succ": {
              "ac": _2,
              "co": _2,
              "es": _2,
              "go": _2,
              "hs": _2,
              "kg": _2,
              "mil": _2,
              "ms": _2,
              "ne": _2,
              "or": _2,
              "pe": _2,
              "re": _2,
              "sc": _2,
              "busan": _2,
              "chungbuk": _2,
              "chungnam": _2,
              "daegu": _2,
              "daejeon": _2,
              "gangwon": _2,
              "gwangju": _2,
              "gyeongbuk": _2,
              "gyeonggi": _2,
              "gyeongnam": _2,
              "incheon": _2,
              "jeju": _2,
              "jeonbuk": _2,
              "jeonnam": _2,
              "seoul": _2,
              "ulsan": _2,
              "blogspot": _3
            }
          },
          "kw": {
            "$": 1,
            "succ": {
              "com": _2,
              "edu": _2,
              "emb": _2,
              "gov": _2,
              "ind": _2,
              "net": _2,
              "org": _2
            }
          },
          "ky": _25,
          "kz": {
            "$": 1,
            "succ": {
              "org": _2,
              "edu": _2,
              "net": _2,
              "gov": _2,
              "mil": _2,
              "com": _2,
              "jcloud": _3,
              "kazteleport": {
                "$": 0,
                "succ": {
                  "upaas": _3
                }
              }
            }
          },
          "la": {
            "$": 1,
            "succ": {
              "int": _2,
              "net": _2,
              "info": _2,
              "edu": _2,
              "gov": _2,
              "per": _2,
              "com": _2,
              "org": _2,
              "bnr": _3,
              "c": _3
            }
          },
          "lb": _4,
          "lc": {
            "$": 1,
            "succ": {
              "com": _2,
              "net": _2,
              "co": _2,
              "org": _2,
              "edu": _2,
              "gov": _2,
              "oy": _3
            }
          },
          "li": {
            "$": 1,
            "succ": {
              "blogspot": _3,
              "caa": _3
            }
          },
          "lk": {
            "$": 1,
            "succ": {
              "gov": _2,
              "sch": _2,
              "net": _2,
              "int": _2,
              "com": _2,
              "org": _2,
              "edu": _2,
              "ngo": _2,
              "soc": _2,
              "web": _2,
              "ltd": _2,
              "assn": _2,
              "grp": _2,
              "hotel": _2,
              "ac": _2
            }
          },
          "lr": _4,
          "ls": {
            "$": 1,
            "succ": {
              "ac": _2,
              "biz": _2,
              "co": _2,
              "edu": _2,
              "gov": _2,
              "info": _2,
              "net": _2,
              "org": _2,
              "sc": _2,
              "de": _3
            }
          },
          "lt": _34,
          "lu": {
            "$": 1,
            "succ": {
              "blogspot": _3,
              "123website": _3
            }
          },
          "lv": {
            "$": 1,
            "succ": {
              "com": _2,
              "edu": _2,
              "gov": _2,
              "org": _2,
              "mil": _2,
              "id": _2,
              "net": _2,
              "asn": _2,
              "conf": _2
            }
          },
          "ly": {
            "$": 1,
            "succ": {
              "com": _2,
              "net": _2,
              "gov": _2,
              "plc": _2,
              "edu": _2,
              "sch": _2,
              "med": _2,
              "org": _2,
              "id": _2
            }
          },
          "ma": {
            "$": 1,
            "succ": {
              "co": _2,
              "net": _2,
              "gov": _2,
              "org": _2,
              "ac": _2,
              "press": _2
            }
          },
          "mc": {
            "$": 1,
            "succ": {
              "tm": _2,
              "asso": _2
            }
          },
          "md": {
            "$": 1,
            "succ": {
              "blogspot": _3,
              "at": _3,
              "de": _3,
              "jp": _3,
              "to": _3
            }
          },
          "me": {
            "$": 1,
            "succ": {
              "co": _2,
              "net": _2,
              "org": _2,
              "edu": _2,
              "ac": _2,
              "gov": _2,
              "its": _2,
              "priv": _2,
              "c66": _3,
              "daplie": {
                "$": 2,
                "succ": {
                  "localhost": _3
                }
              },
              "edgestack": _3,
              "filegear": _3,
              "filegear-au": _3,
              "filegear-de": _3,
              "filegear-gb": _3,
              "filegear-ie": _3,
              "filegear-jp": _3,
              "filegear-sg": _3,
              "glitch": _3,
              "ravendb": _3,
              "lohmus": _3,
              "barsy": _3,
              "mcpe": _3,
              "mcdir": _3,
              "soundcast": _3,
              "tcp4": _3,
              "brasilia": _3,
              "ddns": _3,
              "dnsfor": _3,
              "hopto": _3,
              "loginto": _3,
              "noip": _3,
              "webhop": _3,
              "vp4": _3,
              "diskstation": _3,
              "dscloud": _3,
              "i234": _3,
              "myds": _3,
              "synology": _3,
              "transip": _23,
              "wedeploy": _3,
              "yombo": _3,
              "nohost": _3
            }
          },
          "mg": {
            "$": 1,
            "succ": {
              "org": _2,
              "nom": _2,
              "gov": _2,
              "prd": _2,
              "tm": _2,
              "edu": _2,
              "mil": _2,
              "com": _2,
              "co": _2
            }
          },
          "mh": _2,
          "mil": _2,
          "mk": {
            "$": 1,
            "succ": {
              "com": _2,
              "org": _2,
              "net": _2,
              "edu": _2,
              "gov": _2,
              "inf": _2,
              "name": _2,
              "blogspot": _3
            }
          },
          "ml": {
            "$": 1,
            "succ": {
              "com": _2,
              "edu": _2,
              "gouv": _2,
              "gov": _2,
              "net": _2,
              "org": _2,
              "presse": _2
            }
          },
          "mm": _8,
          "mn": {
            "$": 1,
            "succ": {
              "gov": _2,
              "edu": _2,
              "org": _2,
              "nyc": _3
            }
          },
          "mo": _4,
          "mobi": {
            "$": 1,
            "succ": {
              "barsy": _3,
              "dscloud": _3
            }
          },
          "mp": {
            "$": 1,
            "succ": {
              "ju": _3
            }
          },
          "mq": _2,
          "mr": _34,
          "ms": {
            "$": 1,
            "succ": {
              "com": _2,
              "edu": _2,
              "gov": _2,
              "net": _2,
              "org": _2,
              "lab": _3,
              "minisite": _3
            }
          },
          "mt": {
            "$": 1,
            "succ": {
              "com": _6,
              "edu": _2,
              "net": _2,
              "org": _2
            }
          },
          "mu": {
            "$": 1,
            "succ": {
              "com": _2,
              "net": _2,
              "org": _2,
              "gov": _2,
              "ac": _2,
              "co": _2,
              "or": _2
            }
          },
          "museum": {
            "$": 1,
            "succ": {
              "academy": _2,
              "agriculture": _2,
              "air": _2,
              "airguard": _2,
              "alabama": _2,
              "alaska": _2,
              "amber": _2,
              "ambulance": _2,
              "american": _2,
              "americana": _2,
              "americanantiques": _2,
              "americanart": _2,
              "amsterdam": _2,
              "and": _2,
              "annefrank": _2,
              "anthro": _2,
              "anthropology": _2,
              "antiques": _2,
              "aquarium": _2,
              "arboretum": _2,
              "archaeological": _2,
              "archaeology": _2,
              "architecture": _2,
              "art": _2,
              "artanddesign": _2,
              "artcenter": _2,
              "artdeco": _2,
              "arteducation": _2,
              "artgallery": _2,
              "arts": _2,
              "artsandcrafts": _2,
              "asmatart": _2,
              "assassination": _2,
              "assisi": _2,
              "association": _2,
              "astronomy": _2,
              "atlanta": _2,
              "austin": _2,
              "australia": _2,
              "automotive": _2,
              "aviation": _2,
              "axis": _2,
              "badajoz": _2,
              "baghdad": _2,
              "bahn": _2,
              "bale": _2,
              "baltimore": _2,
              "barcelona": _2,
              "baseball": _2,
              "basel": _2,
              "baths": _2,
              "bauern": _2,
              "beauxarts": _2,
              "beeldengeluid": _2,
              "bellevue": _2,
              "bergbau": _2,
              "berkeley": _2,
              "berlin": _2,
              "bern": _2,
              "bible": _2,
              "bilbao": _2,
              "bill": _2,
              "birdart": _2,
              "birthplace": _2,
              "bonn": _2,
              "boston": _2,
              "botanical": _2,
              "botanicalgarden": _2,
              "botanicgarden": _2,
              "botany": _2,
              "brandywinevalley": _2,
              "brasil": _2,
              "bristol": _2,
              "british": _2,
              "britishcolumbia": _2,
              "broadcast": _2,
              "brunel": _2,
              "brussel": _2,
              "brussels": _2,
              "bruxelles": _2,
              "building": _2,
              "burghof": _2,
              "bus": _2,
              "bushey": _2,
              "cadaques": _2,
              "california": _2,
              "cambridge": _2,
              "can": _2,
              "canada": _2,
              "capebreton": _2,
              "carrier": _2,
              "cartoonart": _2,
              "casadelamoneda": _2,
              "castle": _2,
              "castres": _2,
              "celtic": _2,
              "center": _2,
              "chattanooga": _2,
              "cheltenham": _2,
              "chesapeakebay": _2,
              "chicago": _2,
              "children": _2,
              "childrens": _2,
              "childrensgarden": _2,
              "chiropractic": _2,
              "chocolate": _2,
              "christiansburg": _2,
              "cincinnati": _2,
              "cinema": _2,
              "circus": _2,
              "civilisation": _2,
              "civilization": _2,
              "civilwar": _2,
              "clinton": _2,
              "clock": _2,
              "coal": _2,
              "coastaldefence": _2,
              "cody": _2,
              "coldwar": _2,
              "collection": _2,
              "colonialwilliamsburg": _2,
              "coloradoplateau": _2,
              "columbia": _2,
              "columbus": _2,
              "communication": _2,
              "communications": _2,
              "community": _2,
              "computer": _2,
              "computerhistory": _2,
              "xn--comunicaes-v6a2o": _2,
              "comunicações": _2,
              "contemporary": _2,
              "contemporaryart": _2,
              "convent": _2,
              "copenhagen": _2,
              "corporation": _2,
              "xn--correios-e-telecomunicaes-ghc29a": _2,
              "correios-e-telecomunicações": _2,
              "corvette": _2,
              "costume": _2,
              "countryestate": _2,
              "county": _2,
              "crafts": _2,
              "cranbrook": _2,
              "creation": _2,
              "cultural": _2,
              "culturalcenter": _2,
              "culture": _2,
              "cyber": _2,
              "cymru": _2,
              "dali": _2,
              "dallas": _2,
              "database": _2,
              "ddr": _2,
              "decorativearts": _2,
              "delaware": _2,
              "delmenhorst": _2,
              "denmark": _2,
              "depot": _2,
              "design": _2,
              "detroit": _2,
              "dinosaur": _2,
              "discovery": _2,
              "dolls": _2,
              "donostia": _2,
              "durham": _2,
              "eastafrica": _2,
              "eastcoast": _2,
              "education": _2,
              "educational": _2,
              "egyptian": _2,
              "eisenbahn": _2,
              "elburg": _2,
              "elvendrell": _2,
              "embroidery": _2,
              "encyclopedic": _2,
              "england": _2,
              "entomology": _2,
              "environment": _2,
              "environmentalconservation": _2,
              "epilepsy": _2,
              "essex": _2,
              "estate": _2,
              "ethnology": _2,
              "exeter": _2,
              "exhibition": _2,
              "family": _2,
              "farm": _2,
              "farmequipment": _2,
              "farmers": _2,
              "farmstead": _2,
              "field": _2,
              "figueres": _2,
              "filatelia": _2,
              "film": _2,
              "fineart": _2,
              "finearts": _2,
              "finland": _2,
              "flanders": _2,
              "florida": _2,
              "force": _2,
              "fortmissoula": _2,
              "fortworth": _2,
              "foundation": _2,
              "francaise": _2,
              "frankfurt": _2,
              "franziskaner": _2,
              "freemasonry": _2,
              "freiburg": _2,
              "fribourg": _2,
              "frog": _2,
              "fundacio": _2,
              "furniture": _2,
              "gallery": _2,
              "garden": _2,
              "gateway": _2,
              "geelvinck": _2,
              "gemological": _2,
              "geology": _2,
              "georgia": _2,
              "giessen": _2,
              "glas": _2,
              "glass": _2,
              "gorge": _2,
              "grandrapids": _2,
              "graz": _2,
              "guernsey": _2,
              "halloffame": _2,
              "hamburg": _2,
              "handson": _2,
              "harvestcelebration": _2,
              "hawaii": _2,
              "health": _2,
              "heimatunduhren": _2,
              "hellas": _2,
              "helsinki": _2,
              "hembygdsforbund": _2,
              "heritage": _2,
              "histoire": _2,
              "historical": _2,
              "historicalsociety": _2,
              "historichouses": _2,
              "historisch": _2,
              "historisches": _2,
              "history": _2,
              "historyofscience": _2,
              "horology": _2,
              "house": _2,
              "humanities": _2,
              "illustration": _2,
              "imageandsound": _2,
              "indian": _2,
              "indiana": _2,
              "indianapolis": _2,
              "indianmarket": _2,
              "intelligence": _2,
              "interactive": _2,
              "iraq": _2,
              "iron": _2,
              "isleofman": _2,
              "jamison": _2,
              "jefferson": _2,
              "jerusalem": _2,
              "jewelry": _2,
              "jewish": _2,
              "jewishart": _2,
              "jfk": _2,
              "journalism": _2,
              "judaica": _2,
              "judygarland": _2,
              "juedisches": _2,
              "juif": _2,
              "karate": _2,
              "karikatur": _2,
              "kids": _2,
              "koebenhavn": _2,
              "koeln": _2,
              "kunst": _2,
              "kunstsammlung": _2,
              "kunstunddesign": _2,
              "labor": _2,
              "labour": _2,
              "lajolla": _2,
              "lancashire": _2,
              "landes": _2,
              "lans": _2,
              "xn--lns-qla": _2,
              "läns": _2,
              "larsson": _2,
              "lewismiller": _2,
              "lincoln": _2,
              "linz": _2,
              "living": _2,
              "livinghistory": _2,
              "localhistory": _2,
              "london": _2,
              "losangeles": _2,
              "louvre": _2,
              "loyalist": _2,
              "lucerne": _2,
              "luxembourg": _2,
              "luzern": _2,
              "mad": _2,
              "madrid": _2,
              "mallorca": _2,
              "manchester": _2,
              "mansion": _2,
              "mansions": _2,
              "manx": _2,
              "marburg": _2,
              "maritime": _2,
              "maritimo": _2,
              "maryland": _2,
              "marylhurst": _2,
              "media": _2,
              "medical": _2,
              "medizinhistorisches": _2,
              "meeres": _2,
              "memorial": _2,
              "mesaverde": _2,
              "michigan": _2,
              "midatlantic": _2,
              "military": _2,
              "mill": _2,
              "miners": _2,
              "mining": _2,
              "minnesota": _2,
              "missile": _2,
              "missoula": _2,
              "modern": _2,
              "moma": _2,
              "money": _2,
              "monmouth": _2,
              "monticello": _2,
              "montreal": _2,
              "moscow": _2,
              "motorcycle": _2,
              "muenchen": _2,
              "muenster": _2,
              "mulhouse": _2,
              "muncie": _2,
              "museet": _2,
              "museumcenter": _2,
              "museumvereniging": _2,
              "music": _2,
              "national": _2,
              "nationalfirearms": _2,
              "nationalheritage": _2,
              "nativeamerican": _2,
              "naturalhistory": _2,
              "naturalhistorymuseum": _2,
              "naturalsciences": _2,
              "nature": _2,
              "naturhistorisches": _2,
              "natuurwetenschappen": _2,
              "naumburg": _2,
              "naval": _2,
              "nebraska": _2,
              "neues": _2,
              "newhampshire": _2,
              "newjersey": _2,
              "newmexico": _2,
              "newport": _2,
              "newspaper": _2,
              "newyork": _2,
              "niepce": _2,
              "norfolk": _2,
              "north": _2,
              "nrw": _2,
              "nyc": _2,
              "nyny": _2,
              "oceanographic": _2,
              "oceanographique": _2,
              "omaha": _2,
              "online": _2,
              "ontario": _2,
              "openair": _2,
              "oregon": _2,
              "oregontrail": _2,
              "otago": _2,
              "oxford": _2,
              "pacific": _2,
              "paderborn": _2,
              "palace": _2,
              "paleo": _2,
              "palmsprings": _2,
              "panama": _2,
              "paris": _2,
              "pasadena": _2,
              "pharmacy": _2,
              "philadelphia": _2,
              "philadelphiaarea": _2,
              "philately": _2,
              "phoenix": _2,
              "photography": _2,
              "pilots": _2,
              "pittsburgh": _2,
              "planetarium": _2,
              "plantation": _2,
              "plants": _2,
              "plaza": _2,
              "portal": _2,
              "portland": _2,
              "portlligat": _2,
              "posts-and-telecommunications": _2,
              "preservation": _2,
              "presidio": _2,
              "press": _2,
              "project": _2,
              "public": _2,
              "pubol": _2,
              "quebec": _2,
              "railroad": _2,
              "railway": _2,
              "research": _2,
              "resistance": _2,
              "riodejaneiro": _2,
              "rochester": _2,
              "rockart": _2,
              "roma": _2,
              "russia": _2,
              "saintlouis": _2,
              "salem": _2,
              "salvadordali": _2,
              "salzburg": _2,
              "sandiego": _2,
              "sanfrancisco": _2,
              "santabarbara": _2,
              "santacruz": _2,
              "santafe": _2,
              "saskatchewan": _2,
              "satx": _2,
              "savannahga": _2,
              "schlesisches": _2,
              "schoenbrunn": _2,
              "schokoladen": _2,
              "school": _2,
              "schweiz": _2,
              "science": _2,
              "scienceandhistory": _2,
              "scienceandindustry": _2,
              "sciencecenter": _2,
              "sciencecenters": _2,
              "science-fiction": _2,
              "sciencehistory": _2,
              "sciences": _2,
              "sciencesnaturelles": _2,
              "scotland": _2,
              "seaport": _2,
              "settlement": _2,
              "settlers": _2,
              "shell": _2,
              "sherbrooke": _2,
              "sibenik": _2,
              "silk": _2,
              "ski": _2,
              "skole": _2,
              "society": _2,
              "sologne": _2,
              "soundandvision": _2,
              "southcarolina": _2,
              "southwest": _2,
              "space": _2,
              "spy": _2,
              "square": _2,
              "stadt": _2,
              "stalbans": _2,
              "starnberg": _2,
              "state": _2,
              "stateofdelaware": _2,
              "station": _2,
              "steam": _2,
              "steiermark": _2,
              "stjohn": _2,
              "stockholm": _2,
              "stpetersburg": _2,
              "stuttgart": _2,
              "suisse": _2,
              "surgeonshall": _2,
              "surrey": _2,
              "svizzera": _2,
              "sweden": _2,
              "sydney": _2,
              "tank": _2,
              "tcm": _2,
              "technology": _2,
              "telekommunikation": _2,
              "television": _2,
              "texas": _2,
              "textile": _2,
              "theater": _2,
              "time": _2,
              "timekeeping": _2,
              "topology": _2,
              "torino": _2,
              "touch": _2,
              "town": _2,
              "transport": _2,
              "tree": _2,
              "trolley": _2,
              "trust": _2,
              "trustee": _2,
              "uhren": _2,
              "ulm": _2,
              "undersea": _2,
              "university": _2,
              "usa": _2,
              "usantiques": _2,
              "usarts": _2,
              "uscountryestate": _2,
              "usculture": _2,
              "usdecorativearts": _2,
              "usgarden": _2,
              "ushistory": _2,
              "ushuaia": _2,
              "uslivinghistory": _2,
              "utah": _2,
              "uvic": _2,
              "valley": _2,
              "vantaa": _2,
              "versailles": _2,
              "viking": _2,
              "village": _2,
              "virginia": _2,
              "virtual": _2,
              "virtuel": _2,
              "vlaanderen": _2,
              "volkenkunde": _2,
              "wales": _2,
              "wallonie": _2,
              "war": _2,
              "washingtondc": _2,
              "watchandclock": _2,
              "watch-and-clock": _2,
              "western": _2,
              "westfalen": _2,
              "whaling": _2,
              "wildlife": _2,
              "williamsburg": _2,
              "windmill": _2,
              "workshop": _2,
              "york": _2,
              "yorkshire": _2,
              "yosemite": _2,
              "youth": _2,
              "zoological": _2,
              "zoology": _2,
              "xn--9dbhblg6di": _2,
              "ירושלים": _2,
              "xn--h1aegh": _2,
              "иком": _2
            }
          },
          "mv": {
            "$": 1,
            "succ": {
              "aero": _2,
              "biz": _2,
              "com": _2,
              "coop": _2,
              "edu": _2,
              "gov": _2,
              "info": _2,
              "int": _2,
              "mil": _2,
              "museum": _2,
              "name": _2,
              "net": _2,
              "org": _2,
              "pro": _2
            }
          },
          "mw": {
            "$": 1,
            "succ": {
              "ac": _2,
              "biz": _2,
              "co": _2,
              "com": _2,
              "coop": _2,
              "edu": _2,
              "gov": _2,
              "int": _2,
              "museum": _2,
              "net": _2,
              "org": _2
            }
          },
          "mx": {
            "$": 1,
            "succ": {
              "com": _2,
              "org": _2,
              "gob": _2,
              "edu": _2,
              "net": _2,
              "blogspot": _3
            }
          },
          "my": {
            "$": 1,
            "succ": {
              "biz": _2,
              "com": _2,
              "edu": _2,
              "gov": _2,
              "mil": _2,
              "name": _2,
              "net": _2,
              "org": _2,
              "blogspot": _3
            }
          },
          "mz": {
            "$": 1,
            "succ": {
              "ac": _2,
              "adv": _2,
              "co": _2,
              "edu": _2,
              "gov": _2,
              "mil": _2,
              "net": _2,
              "org": _2
            }
          },
          "na": {
            "$": 1,
            "succ": {
              "info": _2,
              "pro": _2,
              "name": _2,
              "school": _2,
              "or": _2,
              "dr": _2,
              "us": _2,
              "mx": _2,
              "ca": _2,
              "in": _2,
              "cc": _2,
              "tv": _2,
              "ws": _2,
              "mobi": _2,
              "co": _2,
              "com": _2,
              "org": _2
            }
          },
          "name": {
            "$": 1,
            "succ": {
              "her": _37,
              "his": _37
            }
          },
          "nc": {
            "$": 1,
            "succ": {
              "asso": _2,
              "nom": _2
            }
          },
          "ne": _2,
          "net": {
            "$": 1,
            "succ": {
              "adobeaemcloud": _3,
              "adobeio-static": _3,
              "adobeioruntime": _3,
              "akadns": _3,
              "akamai": _3,
              "akamai-staging": _3,
              "akamaiedge": _3,
              "akamaiedge-staging": _3,
              "akamaihd": _3,
              "akamaihd-staging": _3,
              "akamaiorigin": _3,
              "akamaiorigin-staging": _3,
              "akamaized": _3,
              "akamaized-staging": _3,
              "edgekey": _3,
              "edgekey-staging": _3,
              "edgesuite": _3,
              "edgesuite-staging": _3,
              "alwaysdata": _3,
              "myamaze": _3,
              "cloudfront": _3,
              "t3l3p0rt": _3,
              "appudo": _3,
              "atlassian-dev": {
                "$": 0,
                "succ": {
                  "prod": {
                    "$": 0,
                    "succ": {
                      "cdn": _3
                    }
                  }
                }
              },
              "myfritz": _3,
              "onavstack": _3,
              "shopselect": _3,
              "blackbaudcdn": _3,
              "boomla": _3,
              "bplaced": _3,
              "square7": _3,
              "gb": _3,
              "hu": _3,
              "jp": _3,
              "se": _3,
              "uk": _3,
              "in": _3,
              "clickrising": _3,
              "cloudaccess": _3,
              "cdn77-ssl": _3,
              "cdn77": {
                "$": 0,
                "succ": {
                  "r": _3
                }
              },
              "feste-ip": _3,
              "knx-server": _3,
              "static-access": _3,
              "cryptonomic": _5,
              "dattolocal": _3,
              "mydatto": _3,
              "debian": _3,
              "bitbridge": _3,
              "at-band-camp": _3,
              "blogdns": _3,
              "broke-it": _3,
              "buyshouses": _3,
              "dnsalias": _3,
              "dnsdojo": _3,
              "does-it": _3,
              "dontexist": _3,
              "dynalias": _3,
              "dynathome": _3,
              "endofinternet": _3,
              "from-az": _3,
              "from-co": _3,
              "from-la": _3,
              "from-ny": _3,
              "gets-it": _3,
              "ham-radio-op": _3,
              "homeftp": _3,
              "homeip": _3,
              "homelinux": _3,
              "homeunix": _3,
              "in-the-band": _3,
              "is-a-chef": _3,
              "is-a-geek": _3,
              "isa-geek": _3,
              "kicks-ass": _3,
              "office-on-the": _3,
              "podzone": _3,
              "scrapper-site": _3,
              "selfip": _3,
              "sells-it": _3,
              "servebbs": _3,
              "serveftp": _3,
              "thruhere": _3,
              "webhop": _3,
              "definima": _3,
              "casacam": _3,
              "dynu": _3,
              "dynv6": _3,
              "twmail": _3,
              "ru": _3,
              "channelsdvr": {
                "$": 2,
                "succ": {
                  "u": _3
                }
              },
              "fastlylb": {
                "$": 2,
                "succ": {
                  "map": _3
                }
              },
              "fastly": {
                "$": 0,
                "succ": {
                  "freetls": _3,
                  "map": _3,
                  "prod": {
                    "$": 0,
                    "succ": {
                      "a": _3,
                      "global": _3
                    }
                  },
                  "ssl": {
                    "$": 0,
                    "succ": {
                      "a": _3,
                      "b": _3,
                      "global": _3
                    }
                  }
                }
              },
              "edgeapp": _3,
              "flynnhosting": _3,
              "cdn-edges": _3,
              "heteml": _3,
              "cloudfunctions": _3,
              "moonscale": _3,
              "in-dsl": _3,
              "in-vpn": _3,
              "ipifony": _3,
              "iobb": _3,
              "cloudjiffy": {
                "$": 2,
                "succ": {
                  "fra1-de": _3,
                  "west1-us": _3
                }
              },
              "elastx": {
                "$": 0,
                "succ": {
                  "jls-sto1": _3,
                  "jls-sto2": _3,
                  "jls-sto3": _3
                }
              },
              "faststacks": _3,
              "massivegrid": {
                "$": 0,
                "succ": {
                  "paas": {
                    "$": 0,
                    "succ": {
                      "fr-1": _3,
                      "lon-1": _3,
                      "lon-2": _3,
                      "ny-1": _3,
                      "ny-2": _3,
                      "sg-1": _3
                    }
                  }
                }
              },
              "saveincloud": {
                "$": 0,
                "succ": {
                  "jelastic": _3,
                  "nordeste-idc": _3
                }
              },
              "scaleforce": _26,
              "tsukaeru": _27,
              "kinghost": _3,
              "uni5": _3,
              "krellian": _3,
              "barsy": _3,
              "memset": _3,
              "azurewebsites": _3,
              "azure-mobile": _3,
              "cloudapp": _3,
              "azurestaticapps": {
                "$": 2,
                "succ": {
                  "1": _3,
                  "2": _3,
                  "3": _3,
                  "centralus": _3,
                  "eastasia": _3,
                  "eastus2": _3,
                  "westeurope": _3,
                  "westus2": _3
                }
              },
              "dnsup": _3,
              "hicam": _3,
              "now-dns": _3,
              "ownip": _3,
              "vpndns": _3,
              "eating-organic": _3,
              "mydissent": _3,
              "myeffect": _3,
              "mymediapc": _3,
              "mypsx": _3,
              "mysecuritycamera": _3,
              "nhlfan": _3,
              "no-ip": _3,
              "pgafan": _3,
              "privatizehealthinsurance": _3,
              "bounceme": _3,
              "ddns": _3,
              "redirectme": _3,
              "serveblog": _3,
              "serveminecraft": _3,
              "sytes": _3,
              "cloudycluster": _3,
              "ovh": {
                "$": 0,
                "succ": {
                  "webpaas": _5,
                  "hosting": _5
                }
              },
              "bar0": _3,
              "bar1": _3,
              "bar2": _3,
              "rackmaze": _3,
              "squares": _3,
              "schokokeks": _3,
              "firewall-gateway": _3,
              "seidat": _3,
              "senseering": _3,
              "siteleaf": _3,
              "vps-host": {
                "$": 2,
                "succ": {
                  "jelastic": {
                    "$": 0,
                    "succ": {
                      "atl": _3,
                      "njs": _3,
                      "ric": _3
                    }
                  }
                }
              },
              "myspreadshop": _3,
              "srcf": {
                "$": 0,
                "succ": {
                  "soc": _3,
                  "user": _3
                }
              },
              "supabase": _3,
              "dsmynas": _3,
              "familyds": _3,
              "tailscale": {
                "$": 0,
                "succ": {
                  "beta": _3
                }
              },
              "ts": _3,
              "torproject": {
                "$": 2,
                "succ": {
                  "pages": _3
                }
              },
              "reserve-online": _3,
              "community-pro": _3,
              "meinforum": _3,
              "yandexcloud": {
                "$": 2,
                "succ": {
                  "storage": _3,
                  "website": _3
                }
              },
              "za": _3
            }
          },
          "nf": {
            "$": 1,
            "succ": {
              "com": _2,
              "net": _2,
              "per": _2,
              "rec": _2,
              "web": _2,
              "arts": _2,
              "firm": _2,
              "info": _2,
              "other": _2,
              "store": _2
            }
          },
          "ng": {
            "$": 1,
            "succ": {
              "com": _6,
              "edu": _2,
              "gov": _2,
              "i": _2,
              "mil": _2,
              "mobi": _2,
              "name": _2,
              "net": _2,
              "org": _2,
              "sch": _2,
              "col": _3,
              "firm": _3,
              "gen": _3,
              "ltd": _3,
              "ngo": _3
            }
          },
          "ni": {
            "$": 1,
            "succ": {
              "ac": _2,
              "biz": _2,
              "co": _2,
              "com": _2,
              "edu": _2,
              "gob": _2,
              "in": _2,
              "info": _2,
              "int": _2,
              "mil": _2,
              "net": _2,
              "nom": _2,
              "org": _2,
              "web": _2
            }
          },
          "nl": {
            "$": 1,
            "succ": {
              "co": _3,
              "hosting-cluster": _3,
              "blogspot": _3,
              "gov": _3,
              "khplay": _3,
              "123website": _3,
              "myspreadshop": _3,
              "transurl": _5,
              "cistron": _3,
              "demon": _3
            }
          },
          "no": {
            "$": 1,
            "succ": {
              "fhs": _2,
              "vgs": _2,
              "fylkesbibl": _2,
              "folkebibl": _2,
              "museum": _2,
              "idrett": _2,
              "priv": _2,
              "mil": _2,
              "stat": _2,
              "dep": _2,
              "kommune": _2,
              "herad": _2,
              "aa": _38,
              "ah": _38,
              "bu": _38,
              "fm": _38,
              "hl": _38,
              "hm": _38,
              "jan-mayen": _38,
              "mr": _38,
              "nl": _38,
              "nt": _38,
              "of": _38,
              "ol": _38,
              "oslo": _38,
              "rl": _38,
              "sf": _38,
              "st": _38,
              "svalbard": _38,
              "tm": _38,
              "tr": _38,
              "va": _38,
              "vf": _38,
              "akrehamn": _2,
              "xn--krehamn-dxa": _2,
              "åkrehamn": _2,
              "algard": _2,
              "xn--lgrd-poac": _2,
              "ålgård": _2,
              "arna": _2,
              "brumunddal": _2,
              "bryne": _2,
              "bronnoysund": _2,
              "xn--brnnysund-m8ac": _2,
              "brønnøysund": _2,
              "drobak": _2,
              "xn--drbak-wua": _2,
              "drøbak": _2,
              "egersund": _2,
              "fetsund": _2,
              "floro": _2,
              "xn--flor-jra": _2,
              "florø": _2,
              "fredrikstad": _2,
              "hokksund": _2,
              "honefoss": _2,
              "xn--hnefoss-q1a": _2,
              "hønefoss": _2,
              "jessheim": _2,
              "jorpeland": _2,
              "xn--jrpeland-54a": _2,
              "jørpeland": _2,
              "kirkenes": _2,
              "kopervik": _2,
              "krokstadelva": _2,
              "langevag": _2,
              "xn--langevg-jxa": _2,
              "langevåg": _2,
              "leirvik": _2,
              "mjondalen": _2,
              "xn--mjndalen-64a": _2,
              "mjøndalen": _2,
              "mo-i-rana": _2,
              "mosjoen": _2,
              "xn--mosjen-eya": _2,
              "mosjøen": _2,
              "nesoddtangen": _2,
              "orkanger": _2,
              "osoyro": _2,
              "xn--osyro-wua": _2,
              "osøyro": _2,
              "raholt": _2,
              "xn--rholt-mra": _2,
              "råholt": _2,
              "sandnessjoen": _2,
              "xn--sandnessjen-ogb": _2,
              "sandnessjøen": _2,
              "skedsmokorset": _2,
              "slattum": _2,
              "spjelkavik": _2,
              "stathelle": _2,
              "stavern": _2,
              "stjordalshalsen": _2,
              "xn--stjrdalshalsen-sqb": _2,
              "stjørdalshalsen": _2,
              "tananger": _2,
              "tranby": _2,
              "vossevangen": _2,
              "afjord": _2,
              "xn--fjord-lra": _2,
              "åfjord": _2,
              "agdenes": _2,
              "al": _2,
              "xn--l-1fa": _2,
              "ål": _2,
              "alesund": _2,
              "xn--lesund-hua": _2,
              "ålesund": _2,
              "alstahaug": _2,
              "alta": _2,
              "xn--lt-liac": _2,
              "áltá": _2,
              "alaheadju": _2,
              "xn--laheadju-7ya": _2,
              "álaheadju": _2,
              "alvdal": _2,
              "amli": _2,
              "xn--mli-tla": _2,
              "åmli": _2,
              "amot": _2,
              "xn--mot-tla": _2,
              "åmot": _2,
              "andebu": _2,
              "andoy": _2,
              "xn--andy-ira": _2,
              "andøy": _2,
              "andasuolo": _2,
              "ardal": _2,
              "xn--rdal-poa": _2,
              "årdal": _2,
              "aremark": _2,
              "arendal": _2,
              "xn--s-1fa": _2,
              "ås": _2,
              "aseral": _2,
              "xn--seral-lra": _2,
              "åseral": _2,
              "asker": _2,
              "askim": _2,
              "askvoll": _2,
              "askoy": _2,
              "xn--asky-ira": _2,
              "askøy": _2,
              "asnes": _2,
              "xn--snes-poa": _2,
              "åsnes": _2,
              "audnedaln": _2,
              "aukra": _2,
              "aure": _2,
              "aurland": _2,
              "aurskog-holand": _2,
              "xn--aurskog-hland-jnb": _2,
              "aurskog-høland": _2,
              "austevoll": _2,
              "austrheim": _2,
              "averoy": _2,
              "xn--avery-yua": _2,
              "averøy": _2,
              "balestrand": _2,
              "ballangen": _2,
              "balat": _2,
              "xn--blt-elab": _2,
              "bálát": _2,
              "balsfjord": _2,
              "bahccavuotna": _2,
              "xn--bhccavuotna-k7a": _2,
              "báhccavuotna": _2,
              "bamble": _2,
              "bardu": _2,
              "beardu": _2,
              "beiarn": _2,
              "bajddar": _2,
              "xn--bjddar-pta": _2,
              "bájddar": _2,
              "baidar": _2,
              "xn--bidr-5nac": _2,
              "báidár": _2,
              "berg": _2,
              "bergen": _2,
              "berlevag": _2,
              "xn--berlevg-jxa": _2,
              "berlevåg": _2,
              "bearalvahki": _2,
              "xn--bearalvhki-y4a": _2,
              "bearalváhki": _2,
              "bindal": _2,
              "birkenes": _2,
              "bjarkoy": _2,
              "xn--bjarky-fya": _2,
              "bjarkøy": _2,
              "bjerkreim": _2,
              "bjugn": _2,
              "bodo": _2,
              "xn--bod-2na": _2,
              "bodø": _2,
              "badaddja": _2,
              "xn--bdddj-mrabd": _2,
              "bådåddjå": _2,
              "budejju": _2,
              "bokn": _2,
              "bremanger": _2,
              "bronnoy": _2,
              "xn--brnny-wuac": _2,
              "brønnøy": _2,
              "bygland": _2,
              "bykle": _2,
              "barum": _2,
              "xn--brum-voa": _2,
              "bærum": _2,
              "telemark": {
                "$": 0,
                "succ": {
                  "bo": _2,
                  "xn--b-5ga": _2,
                  "bø": _2
                }
              },
              "nordland": {
                "$": 0,
                "succ": {
                  "bo": _2,
                  "xn--b-5ga": _2,
                  "bø": _2,
                  "heroy": _2,
                  "xn--hery-ira": _2,
                  "herøy": _2
                }
              },
              "bievat": _2,
              "xn--bievt-0qa": _2,
              "bievát": _2,
              "bomlo": _2,
              "xn--bmlo-gra": _2,
              "bømlo": _2,
              "batsfjord": _2,
              "xn--btsfjord-9za": _2,
              "båtsfjord": _2,
              "bahcavuotna": _2,
              "xn--bhcavuotna-s4a": _2,
              "báhcavuotna": _2,
              "dovre": _2,
              "drammen": _2,
              "drangedal": _2,
              "dyroy": _2,
              "xn--dyry-ira": _2,
              "dyrøy": _2,
              "donna": _2,
              "xn--dnna-gra": _2,
              "dønna": _2,
              "eid": _2,
              "eidfjord": _2,
              "eidsberg": _2,
              "eidskog": _2,
              "eidsvoll": _2,
              "eigersund": _2,
              "elverum": _2,
              "enebakk": _2,
              "engerdal": _2,
              "etne": _2,
              "etnedal": _2,
              "evenes": _2,
              "evenassi": _2,
              "xn--eveni-0qa01ga": _2,
              "evenášši": _2,
              "evje-og-hornnes": _2,
              "farsund": _2,
              "fauske": _2,
              "fuossko": _2,
              "fuoisku": _2,
              "fedje": _2,
              "fet": _2,
              "finnoy": _2,
              "xn--finny-yua": _2,
              "finnøy": _2,
              "fitjar": _2,
              "fjaler": _2,
              "fjell": _2,
              "flakstad": _2,
              "flatanger": _2,
              "flekkefjord": _2,
              "flesberg": _2,
              "flora": _2,
              "fla": _2,
              "xn--fl-zia": _2,
              "flå": _2,
              "folldal": _2,
              "forsand": _2,
              "fosnes": _2,
              "frei": _2,
              "frogn": _2,
              "froland": _2,
              "frosta": _2,
              "frana": _2,
              "xn--frna-woa": _2,
              "fræna": _2,
              "froya": _2,
              "xn--frya-hra": _2,
              "frøya": _2,
              "fusa": _2,
              "fyresdal": _2,
              "forde": _2,
              "xn--frde-gra": _2,
              "førde": _2,
              "gamvik": _2,
              "gangaviika": _2,
              "xn--ggaviika-8ya47h": _2,
              "gáŋgaviika": _2,
              "gaular": _2,
              "gausdal": _2,
              "gildeskal": _2,
              "xn--gildeskl-g0a": _2,
              "gildeskål": _2,
              "giske": _2,
              "gjemnes": _2,
              "gjerdrum": _2,
              "gjerstad": _2,
              "gjesdal": _2,
              "gjovik": _2,
              "xn--gjvik-wua": _2,
              "gjøvik": _2,
              "gloppen": _2,
              "gol": _2,
              "gran": _2,
              "grane": _2,
              "granvin": _2,
              "gratangen": _2,
              "grimstad": _2,
              "grong": _2,
              "kraanghke": _2,
              "xn--kranghke-b0a": _2,
              "kråanghke": _2,
              "grue": _2,
              "gulen": _2,
              "hadsel": _2,
              "halden": _2,
              "halsa": _2,
              "hamar": _2,
              "hamaroy": _2,
              "habmer": _2,
              "xn--hbmer-xqa": _2,
              "hábmer": _2,
              "hapmir": _2,
              "xn--hpmir-xqa": _2,
              "hápmir": _2,
              "hammerfest": _2,
              "hammarfeasta": _2,
              "xn--hmmrfeasta-s4ac": _2,
              "hámmárfeasta": _2,
              "haram": _2,
              "hareid": _2,
              "harstad": _2,
              "hasvik": _2,
              "aknoluokta": _2,
              "xn--koluokta-7ya57h": _2,
              "ákŋoluokta": _2,
              "hattfjelldal": _2,
              "aarborte": _2,
              "haugesund": _2,
              "hemne": _2,
              "hemnes": _2,
              "hemsedal": _2,
              "more-og-romsdal": {
                "$": 0,
                "succ": {
                  "heroy": _2,
                  "sande": _2
                }
              },
              "xn--mre-og-romsdal-qqb": {
                "$": 0,
                "succ": {
                  "xn--hery-ira": _2,
                  "sande": _2
                }
              },
              "møre-og-romsdal": {
                "$": 0,
                "succ": {
                  "herøy": _2,
                  "sande": _2
                }
              },
              "hitra": _2,
              "hjartdal": _2,
              "hjelmeland": _2,
              "hobol": _2,
              "xn--hobl-ira": _2,
              "hobøl": _2,
              "hof": _2,
              "hol": _2,
              "hole": _2,
              "holmestrand": _2,
              "holtalen": _2,
              "xn--holtlen-hxa": _2,
              "holtålen": _2,
              "hornindal": _2,
              "horten": _2,
              "hurdal": _2,
              "hurum": _2,
              "hvaler": _2,
              "hyllestad": _2,
              "hagebostad": _2,
              "xn--hgebostad-g3a": _2,
              "hægebostad": _2,
              "hoyanger": _2,
              "xn--hyanger-q1a": _2,
              "høyanger": _2,
              "hoylandet": _2,
              "xn--hylandet-54a": _2,
              "høylandet": _2,
              "ha": _2,
              "xn--h-2fa": _2,
              "hå": _2,
              "ibestad": _2,
              "inderoy": _2,
              "xn--indery-fya": _2,
              "inderøy": _2,
              "iveland": _2,
              "jevnaker": _2,
              "jondal": _2,
              "jolster": _2,
              "xn--jlster-bya": _2,
              "jølster": _2,
              "karasjok": _2,
              "karasjohka": _2,
              "xn--krjohka-hwab49j": _2,
              "kárášjohka": _2,
              "karlsoy": _2,
              "galsa": _2,
              "xn--gls-elac": _2,
              "gálsá": _2,
              "karmoy": _2,
              "xn--karmy-yua": _2,
              "karmøy": _2,
              "kautokeino": _2,
              "guovdageaidnu": _2,
              "klepp": _2,
              "klabu": _2,
              "xn--klbu-woa": _2,
              "klæbu": _2,
              "kongsberg": _2,
              "kongsvinger": _2,
              "kragero": _2,
              "xn--krager-gya": _2,
              "kragerø": _2,
              "kristiansand": _2,
              "kristiansund": _2,
              "krodsherad": _2,
              "xn--krdsherad-m8a": _2,
              "krødsherad": _2,
              "kvalsund": _2,
              "rahkkeravju": _2,
              "xn--rhkkervju-01af": _2,
              "ráhkkerávju": _2,
              "kvam": _2,
              "kvinesdal": _2,
              "kvinnherad": _2,
              "kviteseid": _2,
              "kvitsoy": _2,
              "xn--kvitsy-fya": _2,
              "kvitsøy": _2,
              "kvafjord": _2,
              "xn--kvfjord-nxa": _2,
              "kvæfjord": _2,
              "giehtavuoatna": _2,
              "kvanangen": _2,
              "xn--kvnangen-k0a": _2,
              "kvænangen": _2,
              "navuotna": _2,
              "xn--nvuotna-hwa": _2,
              "návuotna": _2,
              "kafjord": _2,
              "xn--kfjord-iua": _2,
              "kåfjord": _2,
              "gaivuotna": _2,
              "xn--givuotna-8ya": _2,
              "gáivuotna": _2,
              "larvik": _2,
              "lavangen": _2,
              "lavagis": _2,
              "loabat": _2,
              "xn--loabt-0qa": _2,
              "loabát": _2,
              "lebesby": _2,
              "davvesiida": _2,
              "leikanger": _2,
              "leirfjord": _2,
              "leka": _2,
              "leksvik": _2,
              "lenvik": _2,
              "leangaviika": _2,
              "xn--leagaviika-52b": _2,
              "leaŋgaviika": _2,
              "lesja": _2,
              "levanger": _2,
              "lier": _2,
              "lierne": _2,
              "lillehammer": _2,
              "lillesand": _2,
              "lindesnes": _2,
              "lindas": _2,
              "xn--linds-pra": _2,
              "lindås": _2,
              "lom": _2,
              "loppa": _2,
              "lahppi": _2,
              "xn--lhppi-xqa": _2,
              "láhppi": _2,
              "lund": _2,
              "lunner": _2,
              "luroy": _2,
              "xn--lury-ira": _2,
              "lurøy": _2,
              "luster": _2,
              "lyngdal": _2,
              "lyngen": _2,
              "ivgu": _2,
              "lardal": _2,
              "lerdal": _2,
              "xn--lrdal-sra": _2,
              "lærdal": _2,
              "lodingen": _2,
              "xn--ldingen-q1a": _2,
              "lødingen": _2,
              "lorenskog": _2,
              "xn--lrenskog-54a": _2,
              "lørenskog": _2,
              "loten": _2,
              "xn--lten-gra": _2,
              "løten": _2,
              "malvik": _2,
              "masoy": _2,
              "xn--msy-ula0h": _2,
              "måsøy": _2,
              "muosat": _2,
              "xn--muost-0qa": _2,
              "muosát": _2,
              "mandal": _2,
              "marker": _2,
              "marnardal": _2,
              "masfjorden": _2,
              "meland": _2,
              "meldal": _2,
              "melhus": _2,
              "meloy": _2,
              "xn--mely-ira": _2,
              "meløy": _2,
              "meraker": _2,
              "xn--merker-kua": _2,
              "meråker": _2,
              "moareke": _2,
              "xn--moreke-jua": _2,
              "moåreke": _2,
              "midsund": _2,
              "midtre-gauldal": _2,
              "modalen": _2,
              "modum": _2,
              "molde": _2,
              "moskenes": _2,
              "moss": _2,
              "mosvik": _2,
              "malselv": _2,
              "xn--mlselv-iua": _2,
              "målselv": _2,
              "malatvuopmi": _2,
              "xn--mlatvuopmi-s4a": _2,
              "málatvuopmi": _2,
              "namdalseid": _2,
              "aejrie": _2,
              "namsos": _2,
              "namsskogan": _2,
              "naamesjevuemie": _2,
              "xn--nmesjevuemie-tcba": _2,
              "nååmesjevuemie": _2,
              "laakesvuemie": _2,
              "nannestad": _2,
              "narvik": _2,
              "narviika": _2,
              "naustdal": _2,
              "nedre-eiker": _2,
              "akershus": _39,
              "buskerud": _39,
              "nesna": _2,
              "nesodden": _2,
              "nesseby": _2,
              "unjarga": _2,
              "xn--unjrga-rta": _2,
              "unjárga": _2,
              "nesset": _2,
              "nissedal": _2,
              "nittedal": _2,
              "nord-aurdal": _2,
              "nord-fron": _2,
              "nord-odal": _2,
              "norddal": _2,
              "nordkapp": _2,
              "davvenjarga": _2,
              "xn--davvenjrga-y4a": _2,
              "davvenjárga": _2,
              "nordre-land": _2,
              "nordreisa": _2,
              "raisa": _2,
              "xn--risa-5na": _2,
              "ráisa": _2,
              "nore-og-uvdal": _2,
              "notodden": _2,
              "naroy": _2,
              "xn--nry-yla5g": _2,
              "nærøy": _2,
              "notteroy": _2,
              "xn--nttery-byae": _2,
              "nøtterøy": _2,
              "odda": _2,
              "oksnes": _2,
              "xn--ksnes-uua": _2,
              "øksnes": _2,
              "oppdal": _2,
              "oppegard": _2,
              "xn--oppegrd-ixa": _2,
              "oppegård": _2,
              "orkdal": _2,
              "orland": _2,
              "xn--rland-uua": _2,
              "ørland": _2,
              "orskog": _2,
              "xn--rskog-uua": _2,
              "ørskog": _2,
              "orsta": _2,
              "xn--rsta-fra": _2,
              "ørsta": _2,
              "hedmark": {
                "$": 0,
                "succ": {
                  "os": _2,
                  "valer": _2,
                  "xn--vler-qoa": _2,
                  "våler": _2
                }
              },
              "hordaland": {
                "$": 0,
                "succ": {
                  "os": _2
                }
              },
              "osen": _2,
              "osteroy": _2,
              "xn--ostery-fya": _2,
              "osterøy": _2,
              "ostre-toten": _2,
              "xn--stre-toten-zcb": _2,
              "østre-toten": _2,
              "overhalla": _2,
              "ovre-eiker": _2,
              "xn--vre-eiker-k8a": _2,
              "øvre-eiker": _2,
              "oyer": _2,
              "xn--yer-zna": _2,
              "øyer": _2,
              "oygarden": _2,
              "xn--ygarden-p1a": _2,
              "øygarden": _2,
              "oystre-slidre": _2,
              "xn--ystre-slidre-ujb": _2,
              "øystre-slidre": _2,
              "porsanger": _2,
              "porsangu": _2,
              "xn--porsgu-sta26f": _2,
              "porsáŋgu": _2,
              "porsgrunn": _2,
              "radoy": _2,
              "xn--rady-ira": _2,
              "radøy": _2,
              "rakkestad": _2,
              "rana": _2,
              "ruovat": _2,
              "randaberg": _2,
              "rauma": _2,
              "rendalen": _2,
              "rennebu": _2,
              "rennesoy": _2,
              "xn--rennesy-v1a": _2,
              "rennesøy": _2,
              "rindal": _2,
              "ringebu": _2,
              "ringerike": _2,
              "ringsaker": _2,
              "rissa": _2,
              "risor": _2,
              "xn--risr-ira": _2,
              "risør": _2,
              "roan": _2,
              "rollag": _2,
              "rygge": _2,
              "ralingen": _2,
              "xn--rlingen-mxa": _2,
              "rælingen": _2,
              "rodoy": _2,
              "xn--rdy-0nab": _2,
              "rødøy": _2,
              "romskog": _2,
              "xn--rmskog-bya": _2,
              "rømskog": _2,
              "roros": _2,
              "xn--rros-gra": _2,
              "røros": _2,
              "rost": _2,
              "xn--rst-0na": _2,
              "røst": _2,
              "royken": _2,
              "xn--ryken-vua": _2,
              "røyken": _2,
              "royrvik": _2,
              "xn--ryrvik-bya": _2,
              "røyrvik": _2,
              "rade": _2,
              "xn--rde-ula": _2,
              "råde": _2,
              "salangen": _2,
              "siellak": _2,
              "saltdal": _2,
              "salat": _2,
              "xn--slt-elab": _2,
              "sálát": _2,
              "xn--slat-5na": _2,
              "sálat": _2,
              "samnanger": _2,
              "vestfold": {
                "$": 0,
                "succ": {
                  "sande": _2
                }
              },
              "sandefjord": _2,
              "sandnes": _2,
              "sandoy": _2,
              "xn--sandy-yua": _2,
              "sandøy": _2,
              "sarpsborg": _2,
              "sauda": _2,
              "sauherad": _2,
              "sel": _2,
              "selbu": _2,
              "selje": _2,
              "seljord": _2,
              "sigdal": _2,
              "siljan": _2,
              "sirdal": _2,
              "skaun": _2,
              "skedsmo": _2,
              "ski": _2,
              "skien": _2,
              "skiptvet": _2,
              "skjervoy": _2,
              "xn--skjervy-v1a": _2,
              "skjervøy": _2,
              "skierva": _2,
              "xn--skierv-uta": _2,
              "skiervá": _2,
              "skjak": _2,
              "xn--skjk-soa": _2,
              "skjåk": _2,
              "skodje": _2,
              "skanland": _2,
              "xn--sknland-fxa": _2,
              "skånland": _2,
              "skanit": _2,
              "xn--sknit-yqa": _2,
              "skánit": _2,
              "smola": _2,
              "xn--smla-hra": _2,
              "smøla": _2,
              "snillfjord": _2,
              "snasa": _2,
              "xn--snsa-roa": _2,
              "snåsa": _2,
              "snoasa": _2,
              "snaase": _2,
              "xn--snase-nra": _2,
              "snåase": _2,
              "sogndal": _2,
              "sokndal": _2,
              "sola": _2,
              "solund": _2,
              "songdalen": _2,
              "sortland": _2,
              "spydeberg": _2,
              "stange": _2,
              "stavanger": _2,
              "steigen": _2,
              "steinkjer": _2,
              "stjordal": _2,
              "xn--stjrdal-s1a": _2,
              "stjørdal": _2,
              "stokke": _2,
              "stor-elvdal": _2,
              "stord": _2,
              "stordal": _2,
              "storfjord": _2,
              "omasvuotna": _2,
              "strand": _2,
              "stranda": _2,
              "stryn": _2,
              "sula": _2,
              "suldal": _2,
              "sund": _2,
              "sunndal": _2,
              "surnadal": _2,
              "sveio": _2,
              "svelvik": _2,
              "sykkylven": _2,
              "sogne": _2,
              "xn--sgne-gra": _2,
              "søgne": _2,
              "somna": _2,
              "xn--smna-gra": _2,
              "sømna": _2,
              "sondre-land": _2,
              "xn--sndre-land-0cb": _2,
              "søndre-land": _2,
              "sor-aurdal": _2,
              "xn--sr-aurdal-l8a": _2,
              "sør-aurdal": _2,
              "sor-fron": _2,
              "xn--sr-fron-q1a": _2,
              "sør-fron": _2,
              "sor-odal": _2,
              "xn--sr-odal-q1a": _2,
              "sør-odal": _2,
              "sor-varanger": _2,
              "xn--sr-varanger-ggb": _2,
              "sør-varanger": _2,
              "matta-varjjat": _2,
              "xn--mtta-vrjjat-k7af": _2,
              "mátta-várjjat": _2,
              "sorfold": _2,
              "xn--srfold-bya": _2,
              "sørfold": _2,
              "sorreisa": _2,
              "xn--srreisa-q1a": _2,
              "sørreisa": _2,
              "sorum": _2,
              "xn--srum-gra": _2,
              "sørum": _2,
              "tana": _2,
              "deatnu": _2,
              "time": _2,
              "tingvoll": _2,
              "tinn": _2,
              "tjeldsund": _2,
              "dielddanuorri": _2,
              "tjome": _2,
              "xn--tjme-hra": _2,
              "tjøme": _2,
              "tokke": _2,
              "tolga": _2,
              "torsken": _2,
              "tranoy": _2,
              "xn--trany-yua": _2,
              "tranøy": _2,
              "tromso": _2,
              "xn--troms-zua": _2,
              "tromsø": _2,
              "tromsa": _2,
              "romsa": _2,
              "trondheim": _2,
              "troandin": _2,
              "trysil": _2,
              "trana": _2,
              "xn--trna-woa": _2,
              "træna": _2,
              "trogstad": _2,
              "xn--trgstad-r1a": _2,
              "trøgstad": _2,
              "tvedestrand": _2,
              "tydal": _2,
              "tynset": _2,
              "tysfjord": _2,
              "divtasvuodna": _2,
              "divttasvuotna": _2,
              "tysnes": _2,
              "tysvar": _2,
              "xn--tysvr-vra": _2,
              "tysvær": _2,
              "tonsberg": _2,
              "xn--tnsberg-q1a": _2,
              "tønsberg": _2,
              "ullensaker": _2,
              "ullensvang": _2,
              "ulvik": _2,
              "utsira": _2,
              "vadso": _2,
              "xn--vads-jra": _2,
              "vadsø": _2,
              "cahcesuolo": _2,
              "xn--hcesuolo-7ya35b": _2,
              "čáhcesuolo": _2,
              "vaksdal": _2,
              "valle": _2,
              "vang": _2,
              "vanylven": _2,
              "vardo": _2,
              "xn--vard-jra": _2,
              "vardø": _2,
              "varggat": _2,
              "xn--vrggt-xqad": _2,
              "várggát": _2,
              "vefsn": _2,
              "vaapste": _2,
              "vega": _2,
              "vegarshei": _2,
              "xn--vegrshei-c0a": _2,
              "vegårshei": _2,
              "vennesla": _2,
              "verdal": _2,
              "verran": _2,
              "vestby": _2,
              "vestnes": _2,
              "vestre-slidre": _2,
              "vestre-toten": _2,
              "vestvagoy": _2,
              "xn--vestvgy-ixa6o": _2,
              "vestvågøy": _2,
              "vevelstad": _2,
              "vik": _2,
              "vikna": _2,
              "vindafjord": _2,
              "volda": _2,
              "voss": _2,
              "varoy": _2,
              "xn--vry-yla5g": _2,
              "værøy": _2,
              "vagan": _2,
              "xn--vgan-qoa": _2,
              "vågan": _2,
              "voagat": _2,
              "vagsoy": _2,
              "xn--vgsy-qoa0j": _2,
              "vågsøy": _2,
              "vaga": _2,
              "xn--vg-yiab": _2,
              "vågå": _2,
              "ostfold": {
                "$": 0,
                "succ": {
                  "valer": _2
                }
              },
              "xn--stfold-9xa": {
                "$": 0,
                "succ": {
                  "xn--vler-qoa": _2
                }
              },
              "østfold": {
                "$": 0,
                "succ": {
                  "våler": _2
                }
              },
              "co": _3,
              "blogspot": _3,
              "123hjemmeside": _3,
              "myspreadshop": _3
            }
          },
          "np": _8,
          "nr": _33,
          "nu": {
            "$": 1,
            "succ": {
              "merseine": _3,
              "mine": _3,
              "shacknet": _3,
              "enterprisecloud": _3
            }
          },
          "nz": {
            "$": 1,
            "succ": {
              "ac": _2,
              "co": _6,
              "cri": _2,
              "geek": _2,
              "gen": _2,
              "govt": _2,
              "health": _2,
              "iwi": _2,
              "kiwi": _2,
              "maori": _2,
              "mil": _2,
              "xn--mori-qsa": _2,
              "māori": _2,
              "net": _2,
              "org": _2,
              "parliament": _2,
              "school": _2
            }
          },
          "om": {
            "$": 1,
            "succ": {
              "co": _2,
              "com": _2,
              "edu": _2,
              "gov": _2,
              "med": _2,
              "museum": _2,
              "net": _2,
              "org": _2,
              "pro": _2
            }
          },
          "onion": _2,
          "org": {
            "$": 1,
            "succ": {
              "altervista": _3,
              "amune": {
                "$": 0,
                "succ": {
                  "tele": _3
                }
              },
              "pimienta": _3,
              "poivron": _3,
              "potager": _3,
              "sweetpepper": _3,
              "ae": _3,
              "us": _3,
              "certmgr": _3,
              "cdn77": {
                "$": 0,
                "succ": {
                  "c": _3,
                  "rsc": _3
                }
              },
              "cdn77-secure": {
                "$": 0,
                "succ": {
                  "origin": {
                    "$": 0,
                    "succ": {
                      "ssl": _3
                    }
                  }
                }
              },
              "cloudns": _3,
              "duckdns": _3,
              "tunk": _3,
              "dyndns": {
                "$": 2,
                "succ": {
                  "go": _3,
                  "home": _3
                }
              },
              "blogdns": _3,
              "blogsite": _3,
              "boldlygoingnowhere": _3,
              "dnsalias": _3,
              "dnsdojo": _3,
              "doesntexist": _3,
              "dontexist": _3,
              "doomdns": _3,
              "dvrdns": _3,
              "dynalias": _3,
              "endofinternet": _3,
              "endoftheinternet": _3,
              "from-me": _3,
              "game-host": _3,
              "gotdns": _3,
              "hobby-site": _3,
              "homedns": _3,
              "homeftp": _3,
              "homelinux": _3,
              "homeunix": _3,
              "is-a-bruinsfan": _3,
              "is-a-candidate": _3,
              "is-a-celticsfan": _3,
              "is-a-chef": _3,
              "is-a-geek": _3,
              "is-a-knight": _3,
              "is-a-linux-user": _3,
              "is-a-patsfan": _3,
              "is-a-soxfan": _3,
              "is-found": _3,
              "is-lost": _3,
              "is-saved": _3,
              "is-very-bad": _3,
              "is-very-evil": _3,
              "is-very-good": _3,
              "is-very-nice": _3,
              "is-very-sweet": _3,
              "isa-geek": _3,
              "kicks-ass": _3,
              "misconfused": _3,
              "podzone": _3,
              "readmyblog": _3,
              "selfip": _3,
              "sellsyourhome": _3,
              "servebbs": _3,
              "serveftp": _3,
              "servegame": _3,
              "stuff-4-sale": _3,
              "webhop": _3,
              "ddnss": _3,
              "accesscam": _3,
              "camdvr": _3,
              "freeddns": _3,
              "mywire": _3,
              "webredirect": _3,
              "eu": {
                "$": 2,
                "succ": {
                  "al": _3,
                  "asso": _3,
                  "at": _3,
                  "au": _3,
                  "be": _3,
                  "bg": _3,
                  "ca": _3,
                  "cd": _3,
                  "ch": _3,
                  "cn": _3,
                  "cy": _3,
                  "cz": _3,
                  "de": _3,
                  "dk": _3,
                  "edu": _3,
                  "ee": _3,
                  "es": _3,
                  "fi": _3,
                  "fr": _3,
                  "gr": _3,
                  "hr": _3,
                  "hu": _3,
                  "ie": _3,
                  "il": _3,
                  "in": _3,
                  "int": _3,
                  "is": _3,
                  "it": _3,
                  "jp": _3,
                  "kr": _3,
                  "lt": _3,
                  "lu": _3,
                  "lv": _3,
                  "mc": _3,
                  "me": _3,
                  "mk": _3,
                  "mt": _3,
                  "my": _3,
                  "net": _3,
                  "ng": _3,
                  "nl": _3,
                  "no": _3,
                  "nz": _3,
                  "paris": _3,
                  "pl": _3,
                  "pt": _3,
                  "q-a": _3,
                  "ro": _3,
                  "ru": _3,
                  "se": _3,
                  "si": _3,
                  "sk": _3,
                  "tr": _3,
                  "uk": _3,
                  "us": _3
                }
              },
              "twmail": _3,
              "fedorainfracloud": _3,
              "fedorapeople": _3,
              "fedoraproject": {
                "$": 0,
                "succ": {
                  "cloud": _3,
                  "os": _21,
                  "stg": {
                    "$": 0,
                    "succ": {
                      "os": _21
                    }
                  }
                }
              },
              "freedesktop": _3,
              "hepforge": _3,
              "in-dsl": _3,
              "in-vpn": _3,
              "js": _3,
              "barsy": _3,
              "mayfirst": _3,
              "mozilla-iot": _3,
              "bmoattachments": _3,
              "dynserv": _3,
              "now-dns": _3,
              "cable-modem": _3,
              "collegefan": _3,
              "couchpotatofries": _3,
              "mlbfan": _3,
              "mysecuritycamera": _3,
              "nflfan": _3,
              "read-books": _3,
              "ufcfan": _3,
              "hopto": _3,
              "myftp": _3,
              "no-ip": _3,
              "zapto": _3,
              "httpbin": _3,
              "pubtls": _3,
              "jpn": _3,
              "my-firewall": _3,
              "myfirewall": _3,
              "spdns": _3,
              "small-web": _3,
              "dsmynas": _3,
              "familyds": _3,
              "teckids": _12,
              "tuxfamily": _3,
              "diskstation": _3,
              "hk": _3,
              "wmflabs": _3,
              "toolforge": _3,
              "wmcloud": _3,
              "za": _3
            }
          },
          "pa": {
            "$": 1,
            "succ": {
              "ac": _2,
              "gob": _2,
              "com": _2,
              "org": _2,
              "sld": _2,
              "edu": _2,
              "net": _2,
              "ing": _2,
              "abo": _2,
              "med": _2,
              "nom": _2
            }
          },
          "pe": {
            "$": 1,
            "succ": {
              "edu": _2,
              "gob": _2,
              "nom": _2,
              "mil": _2,
              "org": _2,
              "com": _2,
              "net": _2,
              "blogspot": _3
            }
          },
          "pf": {
            "$": 1,
            "succ": {
              "com": _2,
              "org": _2,
              "edu": _2
            }
          },
          "pg": _8,
          "ph": {
            "$": 1,
            "succ": {
              "com": _2,
              "net": _2,
              "org": _2,
              "gov": _2,
              "edu": _2,
              "ngo": _2,
              "mil": _2,
              "i": _2
            }
          },
          "pk": {
            "$": 1,
            "succ": {
              "com": _2,
              "net": _2,
              "edu": _2,
              "org": _2,
              "fam": _2,
              "biz": _2,
              "web": _2,
              "gov": _2,
              "gob": _2,
              "gok": _2,
              "gon": _2,
              "gop": _2,
              "gos": _2,
              "info": _2
            }
          },
          "pl": {
            "$": 1,
            "succ": {
              "com": _2,
              "net": _2,
              "org": _2,
              "aid": _2,
              "agro": _2,
              "atm": _2,
              "auto": _2,
              "biz": _2,
              "edu": _2,
              "gmina": _2,
              "gsm": _2,
              "info": _2,
              "mail": _2,
              "miasta": _2,
              "media": _2,
              "mil": _2,
              "nieruchomosci": _2,
              "nom": _2,
              "pc": _2,
              "powiat": _2,
              "priv": _2,
              "realestate": _2,
              "rel": _2,
              "sex": _2,
              "shop": _2,
              "sklep": _2,
              "sos": _2,
              "szkola": _2,
              "targi": _2,
              "tm": _2,
              "tourism": _2,
              "travel": _2,
              "turystyka": _2,
              "gov": {
                "$": 1,
                "succ": {
                  "ap": _2,
                  "ic": _2,
                  "is": _2,
                  "us": _2,
                  "kmpsp": _2,
                  "kppsp": _2,
                  "kwpsp": _2,
                  "psp": _2,
                  "wskr": _2,
                  "kwp": _2,
                  "mw": _2,
                  "ug": _2,
                  "um": _2,
                  "umig": _2,
                  "ugim": _2,
                  "upow": _2,
                  "uw": _2,
                  "starostwo": _2,
                  "pa": _2,
                  "po": _2,
                  "psse": _2,
                  "pup": _2,
                  "rzgw": _2,
                  "sa": _2,
                  "so": _2,
                  "sr": _2,
                  "wsa": _2,
                  "sko": _2,
                  "uzs": _2,
                  "wiih": _2,
                  "winb": _2,
                  "pinb": _2,
                  "wios": _2,
                  "witd": _2,
                  "wzmiuw": _2,
                  "piw": _2,
                  "wiw": _2,
                  "griw": _2,
                  "wif": _2,
                  "oum": _2,
                  "sdn": _2,
                  "zp": _2,
                  "uppo": _2,
                  "mup": _2,
                  "wuoz": _2,
                  "konsulat": _2,
                  "oirm": _2
                }
              },
              "augustow": _2,
              "babia-gora": _2,
              "bedzin": _2,
              "beskidy": _2,
              "bialowieza": _2,
              "bialystok": _2,
              "bielawa": _2,
              "bieszczady": _2,
              "boleslawiec": _2,
              "bydgoszcz": _2,
              "bytom": _2,
              "cieszyn": _2,
              "czeladz": _2,
              "czest": _2,
              "dlugoleka": _2,
              "elblag": _2,
              "elk": _2,
              "glogow": _2,
              "gniezno": _2,
              "gorlice": _2,
              "grajewo": _2,
              "ilawa": _2,
              "jaworzno": _2,
              "jelenia-gora": _2,
              "jgora": _2,
              "kalisz": _2,
              "kazimierz-dolny": _2,
              "karpacz": _2,
              "kartuzy": _2,
              "kaszuby": _2,
              "katowice": _2,
              "kepno": _2,
              "ketrzyn": _2,
              "klodzko": _2,
              "kobierzyce": _2,
              "kolobrzeg": _2,
              "konin": _2,
              "konskowola": _2,
              "kutno": _2,
              "lapy": _2,
              "lebork": _2,
              "legnica": _2,
              "lezajsk": _2,
              "limanowa": _2,
              "lomza": _2,
              "lowicz": _2,
              "lubin": _2,
              "lukow": _2,
              "malbork": _2,
              "malopolska": _2,
              "mazowsze": _2,
              "mazury": _2,
              "mielec": _2,
              "mielno": _2,
              "mragowo": _2,
              "naklo": _2,
              "nowaruda": _2,
              "nysa": _2,
              "olawa": _2,
              "olecko": _2,
              "olkusz": _2,
              "olsztyn": _2,
              "opoczno": _2,
              "opole": _2,
              "ostroda": _2,
              "ostroleka": _2,
              "ostrowiec": _2,
              "ostrowwlkp": _2,
              "pila": _2,
              "pisz": _2,
              "podhale": _2,
              "podlasie": _2,
              "polkowice": _2,
              "pomorze": _2,
              "pomorskie": _2,
              "prochowice": _2,
              "pruszkow": _2,
              "przeworsk": _2,
              "pulawy": _2,
              "radom": _2,
              "rawa-maz": _2,
              "rybnik": _2,
              "rzeszow": _2,
              "sanok": _2,
              "sejny": _2,
              "slask": _2,
              "slupsk": _2,
              "sosnowiec": _2,
              "stalowa-wola": _2,
              "skoczow": _2,
              "starachowice": _2,
              "stargard": _2,
              "suwalki": _2,
              "swidnica": _2,
              "swiebodzin": _2,
              "swinoujscie": _2,
              "szczecin": _2,
              "szczytno": _2,
              "tarnobrzeg": _2,
              "tgory": _2,
              "turek": _2,
              "tychy": _2,
              "ustka": _2,
              "walbrzych": _2,
              "warmia": _2,
              "warszawa": _2,
              "waw": _2,
              "wegrow": _2,
              "wielun": _2,
              "wlocl": _2,
              "wloclawek": _2,
              "wodzislaw": _2,
              "wolomin": _2,
              "wroclaw": _2,
              "zachpomor": _2,
              "zagan": _2,
              "zarow": _2,
              "zgora": _2,
              "zgorzelec": _2,
              "beep": _3,
              "ecommerce-shop": _3,
              "shoparena": _3,
              "homesklep": _3,
              "sdscloud": _3,
              "unicloud": _3,
              "krasnik": _3,
              "leczna": _3,
              "lubartow": _3,
              "lublin": _3,
              "poniatowa": _3,
              "swidnik": _3,
              "co": _3,
              "simplesite": _3,
              "art": _3,
              "gliwice": _3,
              "krakow": _3,
              "poznan": _3,
              "wroc": _3,
              "zakopane": _3,
              "myspreadshop": _3,
              "gda": _3,
              "gdansk": _3,
              "gdynia": _3,
              "med": _3,
              "sopot": _3
            }
          },
          "pm": {
            "$": 1,
            "succ": {
              "own": _3,
              "name": _3
            }
          },
          "pn": {
            "$": 1,
            "succ": {
              "gov": _2,
              "co": _2,
              "org": _2,
              "edu": _2,
              "net": _2
            }
          },
          "post": _2,
          "pr": {
            "$": 1,
            "succ": {
              "com": _2,
              "net": _2,
              "org": _2,
              "gov": _2,
              "edu": _2,
              "isla": _2,
              "pro": _2,
              "biz": _2,
              "info": _2,
              "name": _2,
              "est": _2,
              "prof": _2,
              "ac": _2
            }
          },
          "pro": {
            "$": 1,
            "succ": {
              "aaa": _2,
              "aca": _2,
              "acct": _2,
              "avocat": _2,
              "bar": _2,
              "cpa": _2,
              "eng": _2,
              "jur": _2,
              "law": _2,
              "med": _2,
              "recht": _2,
              "cloudns": _3,
              "dnstrace": {
                "$": 0,
                "succ": {
                  "bci": _3
                }
              },
              "barsy": _3
            }
          },
          "ps": {
            "$": 1,
            "succ": {
              "edu": _2,
              "gov": _2,
              "sec": _2,
              "plo": _2,
              "com": _2,
              "org": _2,
              "net": _2
            }
          },
          "pt": {
            "$": 1,
            "succ": {
              "net": _2,
              "gov": _2,
              "org": _2,
              "edu": _2,
              "int": _2,
              "publ": _2,
              "com": _2,
              "nome": _2,
              "blogspot": _3,
              "123paginaweb": _3
            }
          },
          "pw": {
            "$": 1,
            "succ": {
              "co": _2,
              "ne": _2,
              "or": _2,
              "ed": _2,
              "go": _2,
              "belau": _2,
              "cloudns": _3,
              "x443": _3
            }
          },
          "py": {
            "$": 1,
            "succ": {
              "com": _2,
              "coop": _2,
              "edu": _2,
              "gov": _2,
              "mil": _2,
              "net": _2,
              "org": _2
            }
          },
          "qa": {
            "$": 1,
            "succ": {
              "com": _2,
              "edu": _2,
              "gov": _2,
              "mil": _2,
              "name": _2,
              "net": _2,
              "org": _2,
              "sch": _2,
              "blogspot": _3
            }
          },
          "re": {
            "$": 1,
            "succ": {
              "asso": _2,
              "com": _2,
              "nom": _2,
              "blogspot": _3
            }
          },
          "ro": {
            "$": 1,
            "succ": {
              "arts": _2,
              "com": _2,
              "firm": _2,
              "info": _2,
              "nom": _2,
              "nt": _2,
              "org": _2,
              "rec": _2,
              "store": _2,
              "tm": _2,
              "www": _2,
              "co": _3,
              "shop": _3,
              "blogspot": _3,
              "barsy": _3
            }
          },
          "rs": {
            "$": 1,
            "succ": {
              "ac": _2,
              "co": _2,
              "edu": _2,
              "gov": _2,
              "in": _2,
              "org": _2,
              "brendly": {
                "$": 0,
                "succ": {
                  "shop": _3
                }
              },
              "blogspot": _3,
              "ua": _3,
              "ox": _3
            }
          },
          "ru": {
            "$": 1,
            "succ": {
              "ac": _3,
              "edu": _3,
              "gov": _3,
              "int": _3,
              "mil": _3,
              "test": _3,
              "eurodir": _3,
              "adygeya": _3,
              "bashkiria": _3,
              "bir": _3,
              "cbg": _3,
              "com": _3,
              "dagestan": _3,
              "grozny": _3,
              "kalmykia": _3,
              "kustanai": _3,
              "marine": _3,
              "mordovia": _3,
              "msk": _3,
              "mytis": _3,
              "nalchik": _3,
              "nov": _3,
              "pyatigorsk": _3,
              "spb": _3,
              "vladikavkaz": _3,
              "vladimir": _3,
              "blogspot": _3,
              "na4u": _3,
              "mircloud": _3,
              "regruhosting": _27,
              "myjino": {
                "$": 2,
                "succ": {
                  "hosting": _5,
                  "landing": _5,
                  "spectrum": _5,
                  "vps": _5
                }
              },
              "cldmail": {
                "$": 0,
                "succ": {
                  "hb": _3
                }
              },
              "mcdir": {
                "$": 2,
                "succ": {
                  "vps": _3
                }
              },
              "mcpre": _3,
              "net": _3,
              "org": _3,
              "pp": _3,
              "123sait": _3,
              "lk3": _3,
              "ras": _3
            }
          },
          "rw": {
            "$": 1,
            "succ": {
              "ac": _2,
              "co": _2,
              "coop": _2,
              "gov": _2,
              "mil": _2,
              "net": _2,
              "org": _2
            }
          },
          "sa": {
            "$": 1,
            "succ": {
              "com": _2,
              "net": _2,
              "org": _2,
              "gov": _2,
              "med": _2,
              "pub": _2,
              "edu": _2,
              "sch": _2
            }
          },
          "sb": _4,
          "sc": _4,
          "sd": {
            "$": 1,
            "succ": {
              "com": _2,
              "net": _2,
              "org": _2,
              "edu": _2,
              "med": _2,
              "tv": _2,
              "gov": _2,
              "info": _2
            }
          },
          "se": {
            "$": 1,
            "succ": {
              "a": _2,
              "ac": _2,
              "b": _2,
              "bd": _2,
              "brand": _2,
              "c": _2,
              "d": _2,
              "e": _2,
              "f": _2,
              "fh": _2,
              "fhsk": _2,
              "fhv": _2,
              "g": _2,
              "h": _2,
              "i": _2,
              "k": _2,
              "komforb": _2,
              "kommunalforbund": _2,
              "komvux": _2,
              "l": _2,
              "lanbib": _2,
              "m": _2,
              "n": _2,
              "naturbruksgymn": _2,
              "o": _2,
              "org": _2,
              "p": _2,
              "parti": _2,
              "pp": _2,
              "press": _2,
              "r": _2,
              "s": _2,
              "t": _2,
              "tm": _2,
              "u": _2,
              "w": _2,
              "x": _2,
              "y": _2,
              "z": _2,
              "com": _3,
              "blogspot": _3,
              "conf": _3,
              "iopsys": _3,
              "123minsida": _3,
              "itcouldbewor": _3,
              "myspreadshop": _3,
              "paba": {
                "$": 0,
                "succ": {
                  "su": _3
                }
              }
            }
          },
          "sg": {
            "$": 1,
            "succ": {
              "com": _2,
              "net": _2,
              "org": _2,
              "gov": _2,
              "edu": _2,
              "per": _2,
              "blogspot": _3,
              "enscaled": _3
            }
          },
          "sh": {
            "$": 1,
            "succ": {
              "com": _2,
              "net": _2,
              "gov": _2,
              "org": _2,
              "mil": _2,
              "bip": _3,
              "hashbang": _3,
              "platform": {
                "$": 0,
                "succ": {
                  "bc": _3,
                  "ent": _3,
                  "eu": _3,
                  "us": _3
                }
              },
              "now": _3,
              "vxl": _3,
              "wedeploy": _3
            }
          },
          "si": {
            "$": 1,
            "succ": {
              "gitapp": _3,
              "gitpage": _3,
              "blogspot": _3
            }
          },
          "sj": _2,
          "sk": _6,
          "sl": _4,
          "sm": _2,
          "sn": {
            "$": 1,
            "succ": {
              "art": _2,
              "com": _2,
              "edu": _2,
              "gouv": _2,
              "org": _2,
              "perso": _2,
              "univ": _2,
              "blogspot": _3
            }
          },
          "so": {
            "$": 1,
            "succ": {
              "com": _2,
              "edu": _2,
              "gov": _2,
              "me": _2,
              "net": _2,
              "org": _2,
              "sch": _3
            }
          },
          "sr": _2,
          "ss": {
            "$": 1,
            "succ": {
              "biz": _2,
              "com": _2,
              "edu": _2,
              "gov": _2,
              "me": _2,
              "net": _2,
              "org": _2,
              "sch": _2
            }
          },
          "st": {
            "$": 1,
            "succ": {
              "co": _2,
              "com": _2,
              "consulado": _2,
              "edu": _2,
              "embaixada": _2,
              "mil": _2,
              "net": _2,
              "org": _2,
              "principe": _2,
              "saotome": _2,
              "store": _2,
              "kirara": _3,
              "noho": _3
            }
          },
          "su": {
            "$": 1,
            "succ": {
              "abkhazia": _3,
              "adygeya": _3,
              "aktyubinsk": _3,
              "arkhangelsk": _3,
              "armenia": _3,
              "ashgabad": _3,
              "azerbaijan": _3,
              "balashov": _3,
              "bashkiria": _3,
              "bryansk": _3,
              "bukhara": _3,
              "chimkent": _3,
              "dagestan": _3,
              "east-kazakhstan": _3,
              "exnet": _3,
              "georgia": _3,
              "grozny": _3,
              "ivanovo": _3,
              "jambyl": _3,
              "kalmykia": _3,
              "kaluga": _3,
              "karacol": _3,
              "karaganda": _3,
              "karelia": _3,
              "khakassia": _3,
              "krasnodar": _3,
              "kurgan": _3,
              "kustanai": _3,
              "lenug": _3,
              "mangyshlak": _3,
              "mordovia": _3,
              "msk": _3,
              "murmansk": _3,
              "nalchik": _3,
              "navoi": _3,
              "north-kazakhstan": _3,
              "nov": _3,
              "obninsk": _3,
              "penza": _3,
              "pokrovsk": _3,
              "sochi": _3,
              "spb": _3,
              "tashkent": _3,
              "termez": _3,
              "togliatti": _3,
              "troitsk": _3,
              "tselinograd": _3,
              "tula": _3,
              "tuva": _3,
              "vladikavkaz": _3,
              "vladimir": _3,
              "vologda": _3
            }
          },
          "sv": {
            "$": 1,
            "succ": {
              "com": _2,
              "edu": _2,
              "gob": _2,
              "org": _2,
              "red": _2
            }
          },
          "sx": _7,
          "sy": _32,
          "sz": {
            "$": 1,
            "succ": {
              "co": _2,
              "ac": _2,
              "org": _2
            }
          },
          "tc": {
            "$": 1,
            "succ": {
              "ch": _3,
              "me": _3,
              "we": _3
            }
          },
          "td": _6,
          "tel": _2,
          "tf": {
            "$": 1,
            "succ": {
              "sch": _3
            }
          },
          "tg": _2,
          "th": {
            "$": 1,
            "succ": {
              "ac": _2,
              "co": _2,
              "go": _2,
              "in": _2,
              "mi": _2,
              "net": _2,
              "or": _2,
              "online": _3,
              "shop": _3
            }
          },
          "tj": {
            "$": 1,
            "succ": {
              "ac": _2,
              "biz": _2,
              "co": _2,
              "com": _2,
              "edu": _2,
              "go": _2,
              "gov": _2,
              "int": _2,
              "mil": _2,
              "name": _2,
              "net": _2,
              "nic": _2,
              "org": _2,
              "test": _2,
              "web": _2
            }
          },
          "tk": _2,
          "tl": _7,
          "tm": {
            "$": 1,
            "succ": {
              "com": _2,
              "co": _2,
              "org": _2,
              "net": _2,
              "nom": _2,
              "gov": _2,
              "mil": _2,
              "edu": _2
            }
          },
          "tn": {
            "$": 1,
            "succ": {
              "com": _2,
              "ens": _2,
              "fin": _2,
              "gov": _2,
              "ind": _2,
              "info": _2,
              "intl": _2,
              "mincom": _2,
              "nat": _2,
              "net": _2,
              "org": _2,
              "perso": _2,
              "tourism": _2,
              "orangecloud": _3
            }
          },
          "to": {
            "$": 1,
            "succ": {
              "611": _3,
              "com": _2,
              "gov": _2,
              "net": _2,
              "org": _2,
              "edu": _2,
              "mil": _2,
              "oya": _3,
              "rdv": _3,
              "x0": _3,
              "vpnplus": _3,
              "quickconnect": _13,
              "nyan": _3
            }
          },
          "tr": {
            "$": 1,
            "succ": {
              "av": _2,
              "bbs": _2,
              "bel": _2,
              "biz": _2,
              "com": _6,
              "dr": _2,
              "edu": _2,
              "gen": _2,
              "gov": _2,
              "info": _2,
              "mil": _2,
              "k12": _2,
              "kep": _2,
              "name": _2,
              "net": _2,
              "org": _2,
              "pol": _2,
              "tel": _2,
              "tsk": _2,
              "tv": _2,
              "web": _2,
              "nc": _7
            }
          },
          "tt": {
            "$": 1,
            "succ": {
              "co": _2,
              "com": _2,
              "org": _2,
              "net": _2,
              "biz": _2,
              "info": _2,
              "pro": _2,
              "int": _2,
              "coop": _2,
              "jobs": _2,
              "mobi": _2,
              "travel": _2,
              "museum": _2,
              "aero": _2,
              "name": _2,
              "gov": _2,
              "edu": _2
            }
          },
          "tv": {
            "$": 1,
            "succ": {
              "dyndns": _3,
              "better-than": _3,
              "on-the-web": _3,
              "worse-than": _3,
              "from": _3,
              "sakura": _3
            }
          },
          "tw": {
            "$": 1,
            "succ": {
              "edu": _2,
              "gov": _2,
              "mil": _2,
              "com": {
                "$": 1,
                "succ": {
                  "mymailer": _3
                }
              },
              "net": _2,
              "org": _2,
              "idv": _2,
              "game": _2,
              "ebiz": _2,
              "club": _2,
              "xn--zf0ao64a": _2,
              "網路": _2,
              "xn--uc0atv": _2,
              "組織": _2,
              "xn--czrw28b": _2,
              "商業": _2,
              "url": _3,
              "blogspot": _3
            }
          },
          "tz": {
            "$": 1,
            "succ": {
              "ac": _2,
              "co": _2,
              "go": _2,
              "hotel": _2,
              "info": _2,
              "me": _2,
              "mil": _2,
              "mobi": _2,
              "ne": _2,
              "or": _2,
              "sc": _2,
              "tv": _2
            }
          },
          "ua": {
            "$": 1,
            "succ": {
              "com": _2,
              "edu": _2,
              "gov": _2,
              "in": _2,
              "net": _2,
              "org": _2,
              "cherkassy": _2,
              "cherkasy": _2,
              "chernigov": _2,
              "chernihiv": _2,
              "chernivtsi": _2,
              "chernovtsy": _2,
              "ck": _2,
              "cn": _2,
              "cr": _2,
              "crimea": _2,
              "cv": _2,
              "dn": _2,
              "dnepropetrovsk": _2,
              "dnipropetrovsk": _2,
              "donetsk": _2,
              "dp": _2,
              "if": _2,
              "ivano-frankivsk": _2,
              "kh": _2,
              "kharkiv": _2,
              "kharkov": _2,
              "kherson": _2,
              "khmelnitskiy": _2,
              "khmelnytskyi": _2,
              "kiev": _2,
              "kirovograd": _2,
              "km": _2,
              "kr": _2,
              "krym": _2,
              "ks": _2,
              "kv": _2,
              "kyiv": _2,
              "lg": _2,
              "lt": _2,
              "lugansk": _2,
              "lutsk": _2,
              "lv": _2,
              "lviv": _2,
              "mk": _2,
              "mykolaiv": _2,
              "nikolaev": _2,
              "od": _2,
              "odesa": _2,
              "odessa": _2,
              "pl": _2,
              "poltava": _2,
              "rivne": _2,
              "rovno": _2,
              "rv": _2,
              "sb": _2,
              "sebastopol": _2,
              "sevastopol": _2,
              "sm": _2,
              "sumy": _2,
              "te": _2,
              "ternopil": _2,
              "uz": _2,
              "uzhgorod": _2,
              "vinnica": _2,
              "vinnytsia": _2,
              "vn": _2,
              "volyn": _2,
              "yalta": _2,
              "zaporizhzhe": _2,
              "zaporizhzhia": _2,
              "zhitomir": _2,
              "zhytomyr": _2,
              "zp": _2,
              "zt": _2,
              "cc": _3,
              "inf": _3,
              "ltd": _3,
              "cx": _3,
              "ie": _3,
              "biz": _3,
              "co": _3,
              "pp": _3,
              "v": _3
            }
          },
          "ug": {
            "$": 1,
            "succ": {
              "co": _2,
              "or": _2,
              "ac": _2,
              "sc": _2,
              "go": _2,
              "ne": _2,
              "com": _2,
              "org": _2,
              "blogspot": _3
            }
          },
          "uk": {
            "$": 1,
            "succ": {
              "ac": _2,
              "co": {
                "$": 1,
                "succ": {
                  "bytemark": {
                    "$": 0,
                    "succ": {
                      "dh": _3,
                      "vm": _3
                    }
                  },
                  "blogspot": _3,
                  "layershift": _26,
                  "barsy": _3,
                  "barsyonline": _3,
                  "retrosnub": _31,
                  "nh-serv": _3,
                  "no-ip": _3,
                  "wellbeingzone": _3,
                  "adimo": _3,
                  "myspreadshop": _3
                }
              },
              "gov": {
                "$": 1,
                "succ": {
                  "campaign": _3,
                  "service": _3,
                  "api": _3,
                  "homeoffice": _3
                }
              },
              "ltd": _2,
              "me": _2,
              "net": _2,
              "nhs": _2,
              "org": {
                "$": 1,
                "succ": {
                  "glug": _3,
                  "lug": _3,
                  "lugs": _3,
                  "affinitylottery": _3,
                  "raffleentry": _3,
                  "weeklylottery": _3
                }
              },
              "plc": _2,
              "police": _2,
              "sch": _8,
              "conn": _3,
              "copro": _3,
              "hosp": _3,
              "independent-commission": _3,
              "independent-inquest": _3,
              "independent-inquiry": _3,
              "independent-panel": _3,
              "independent-review": _3,
              "public-inquiry": _3,
              "royal-commission": _3,
              "pymnt": _3,
              "barsy": _3
            }
          },
          "us": {
            "$": 1,
            "succ": {
              "dni": _2,
              "fed": _2,
              "isa": _2,
              "kids": _2,
              "nsn": _2,
              "ak": _40,
              "al": _40,
              "ar": _40,
              "as": _40,
              "az": _40,
              "ca": _40,
              "co": _40,
              "ct": _40,
              "dc": _40,
              "de": {
                "$": 1,
                "succ": {
                  "k12": _2,
                  "cc": _2,
                  "lib": _3
                }
              },
              "fl": _40,
              "ga": _40,
              "gu": _40,
              "hi": _41,
              "ia": _40,
              "id": _40,
              "il": _40,
              "in": _40,
              "ks": _40,
              "ky": _40,
              "la": _40,
              "ma": {
                "$": 1,
                "succ": {
                  "k12": {
                    "$": 1,
                    "succ": {
                      "pvt": _2,
                      "chtr": _2,
                      "paroch": _2
                    }
                  },
                  "cc": _2,
                  "lib": _2
                }
              },
              "md": _40,
              "me": _40,
              "mi": {
                "$": 1,
                "succ": {
                  "k12": _2,
                  "cc": _2,
                  "lib": _2,
                  "ann-arbor": _2,
                  "cog": _2,
                  "dst": _2,
                  "eaton": _2,
                  "gen": _2,
                  "mus": _2,
                  "tec": _2,
                  "washtenaw": _2
                }
              },
              "mn": _40,
              "mo": _40,
              "ms": _40,
              "mt": _40,
              "nc": _40,
              "nd": _41,
              "ne": _40,
              "nh": _40,
              "nj": _40,
              "nm": _40,
              "nv": _40,
              "ny": _40,
              "oh": _40,
              "ok": _40,
              "or": _40,
              "pa": _40,
              "pr": _40,
              "ri": _41,
              "sc": _40,
              "sd": _41,
              "tn": _40,
              "tx": _40,
              "ut": _40,
              "vi": _40,
              "vt": _40,
              "va": _40,
              "wa": _40,
              "wi": _40,
              "wv": {
                "$": 1,
                "succ": {
                  "cc": _2
                }
              },
              "wy": _40,
              "graphox": _3,
              "cloudns": _3,
              "drud": _3,
              "is-by": _3,
              "land-4-sale": _3,
              "stuff-4-sale": _3,
              "enscaled": {
                "$": 0,
                "succ": {
                  "phx": _3
                }
              },
              "mircloud": _3,
              "freeddns": _3,
              "golffan": _3,
              "noip": _3,
              "pointto": _3,
              "platterp": _3
            }
          },
          "uy": {
            "$": 1,
            "succ": {
              "com": _6,
              "edu": _2,
              "gub": _2,
              "mil": _2,
              "net": _2,
              "org": _2
            }
          },
          "uz": {
            "$": 1,
            "succ": {
              "co": _2,
              "com": _2,
              "net": _2,
              "org": _2
            }
          },
          "va": _2,
          "vc": {
            "$": 1,
            "succ": {
              "com": _2,
              "net": _2,
              "org": _2,
              "gov": _2,
              "mil": _2,
              "edu": _2,
              "gv": {
                "$": 2,
                "succ": {
                  "d": _3
                }
              },
              "0e": _3
            }
          },
          "ve": {
            "$": 1,
            "succ": {
              "arts": _2,
              "bib": _2,
              "co": _2,
              "com": _2,
              "e12": _2,
              "edu": _2,
              "firm": _2,
              "gob": _2,
              "gov": _2,
              "info": _2,
              "int": _2,
              "mil": _2,
              "net": _2,
              "nom": _2,
              "org": _2,
              "rar": _2,
              "rec": _2,
              "store": _2,
              "tec": _2,
              "web": _2
            }
          },
          "vg": {
            "$": 1,
            "succ": {
              "at": _3
            }
          },
          "vi": {
            "$": 1,
            "succ": {
              "co": _2,
              "com": _2,
              "k12": _2,
              "net": _2,
              "org": _2
            }
          },
          "vn": {
            "$": 1,
            "succ": {
              "com": _2,
              "net": _2,
              "org": _2,
              "edu": _2,
              "gov": _2,
              "int": _2,
              "ac": _2,
              "biz": _2,
              "info": _2,
              "name": _2,
              "pro": _2,
              "health": _2,
              "blogspot": _3
            }
          },
          "vu": {
            "$": 1,
            "succ": {
              "com": _2,
              "edu": _2,
              "net": _2,
              "org": _2,
              "cn": _3,
              "blog": _3,
              "dev": _3,
              "me": _3
            }
          },
          "wf": {
            "$": 1,
            "succ": {
              "biz": _3,
              "sch": _3
            }
          },
          "ws": {
            "$": 1,
            "succ": {
              "com": _2,
              "net": _2,
              "org": _2,
              "gov": _2,
              "edu": _2,
              "advisor": _5,
              "cloud66": _3,
              "dyndns": _3,
              "mypets": _3
            }
          },
          "yt": {
            "$": 1,
            "succ": {
              "org": _3
            }
          },
          "xn--mgbaam7a8h": _2,
          "امارات": _2,
          "xn--y9a3aq": _2,
          "հայ": _2,
          "xn--54b7fta0cc": _2,
          "বাংলা": _2,
          "xn--90ae": _2,
          "бг": _2,
          "xn--mgbcpq6gpa1a": _2,
          "البحرين": _2,
          "xn--90ais": _2,
          "бел": _2,
          "xn--fiqs8s": _2,
          "中国": _2,
          "xn--fiqz9s": _2,
          "中國": _2,
          "xn--lgbbat1ad8j": _2,
          "الجزائر": _2,
          "xn--wgbh1c": _2,
          "مصر": _2,
          "xn--e1a4c": _2,
          "ею": _2,
          "xn--qxa6a": _2,
          "ευ": _2,
          "xn--mgbah1a3hjkrd": _2,
          "موريتانيا": _2,
          "xn--node": _2,
          "გე": _2,
          "xn--qxam": _2,
          "ελ": _2,
          "xn--j6w193g": {
            "$": 1,
            "succ": {
              "xn--55qx5d": _2,
              "xn--wcvs22d": _2,
              "xn--mxtq1m": _2,
              "xn--gmqw5a": _2,
              "xn--od0alg": _2,
              "xn--uc0atv": _2
            }
          },
          "香港": {
            "$": 1,
            "succ": {
              "公司": _2,
              "教育": _2,
              "政府": _2,
              "個人": _2,
              "網絡": _2,
              "組織": _2
            }
          },
          "xn--2scrj9c": _2,
          "ಭಾರತ": _2,
          "xn--3hcrj9c": _2,
          "ଭାରତ": _2,
          "xn--45br5cyl": _2,
          "ভাৰত": _2,
          "xn--h2breg3eve": _2,
          "भारतम्": _2,
          "xn--h2brj9c8c": _2,
          "भारोत": _2,
          "xn--mgbgu82a": _2,
          "ڀارت": _2,
          "xn--rvc1e0am3e": _2,
          "ഭാരതം": _2,
          "xn--h2brj9c": _2,
          "भारत": _2,
          "xn--mgbbh1a": _2,
          "بارت": _2,
          "xn--mgbbh1a71e": _2,
          "بھارت": _2,
          "xn--fpcrj9c3d": _2,
          "భారత్": _2,
          "xn--gecrj9c": _2,
          "ભારત": _2,
          "xn--s9brj9c": _2,
          "ਭਾਰਤ": _2,
          "xn--45brj9c": _2,
          "ভারত": _2,
          "xn--xkc2dl3a5ee0h": _2,
          "இந்தியா": _2,
          "xn--mgba3a4f16a": _2,
          "ایران": _2,
          "xn--mgba3a4fra": _2,
          "ايران": _2,
          "xn--mgbtx2b": _2,
          "عراق": _2,
          "xn--mgbayh7gpa": _2,
          "الاردن": _2,
          "xn--3e0b707e": _2,
          "한국": _2,
          "xn--80ao21a": _2,
          "қаз": _2,
          "xn--q7ce6a": _2,
          "ລາວ": _2,
          "xn--fzc2c9e2c": _2,
          "ලංකා": _2,
          "xn--xkc2al3hye2a": _2,
          "இலங்கை": _2,
          "xn--mgbc0a9azcg": _2,
          "المغرب": _2,
          "xn--d1alf": _2,
          "мкд": _2,
          "xn--l1acc": _2,
          "мон": _2,
          "xn--mix891f": _2,
          "澳門": _2,
          "xn--mix082f": _2,
          "澳门": _2,
          "xn--mgbx4cd0ab": _2,
          "مليسيا": _2,
          "xn--mgb9awbf": _2,
          "عمان": _2,
          "xn--mgbai9azgqp6j": _2,
          "پاکستان": _2,
          "xn--mgbai9a5eva00b": _2,
          "پاكستان": _2,
          "xn--ygbi2ammx": _2,
          "فلسطين": _2,
          "xn--90a3ac": {
            "$": 1,
            "succ": {
              "xn--o1ac": _2,
              "xn--c1avg": _2,
              "xn--90azh": _2,
              "xn--d1at": _2,
              "xn--o1ach": _2,
              "xn--80au": _2
            }
          },
          "срб": {
            "$": 1,
            "succ": {
              "пр": _2,
              "орг": _2,
              "обр": _2,
              "од": _2,
              "упр": _2,
              "ак": _2
            }
          },
          "xn--p1ai": _2,
          "рф": _2,
          "xn--wgbl6a": _2,
          "قطر": _2,
          "xn--mgberp4a5d4ar": _2,
          "السعودية": _2,
          "xn--mgberp4a5d4a87g": _2,
          "السعودیة": _2,
          "xn--mgbqly7c0a67fbc": _2,
          "السعودیۃ": _2,
          "xn--mgbqly7cvafr": _2,
          "السعوديه": _2,
          "xn--mgbpl2fh": _2,
          "سودان": _2,
          "xn--yfro4i67o": _2,
          "新加坡": _2,
          "xn--clchc0ea0b2g2a9gcd": _2,
          "சிங்கப்பூர்": _2,
          "xn--ogbpf8fl": _2,
          "سورية": _2,
          "xn--mgbtf8fl": _2,
          "سوريا": _2,
          "xn--o3cw4h": {
            "$": 1,
            "succ": {
              "xn--12c1fe0br": _2,
              "xn--12co0c3b4eva": _2,
              "xn--h3cuzk1di": _2,
              "xn--o3cyx2a": _2,
              "xn--m3ch0j3a": _2,
              "xn--12cfi8ixb8l": _2
            }
          },
          "ไทย": {
            "$": 1,
            "succ": {
              "ศึกษา": _2,
              "ธุรกิจ": _2,
              "รัฐบาล": _2,
              "ทหาร": _2,
              "เน็ต": _2,
              "องค์กร": _2
            }
          },
          "xn--pgbs0dh": _2,
          "تونس": _2,
          "xn--kpry57d": _2,
          "台灣": _2,
          "xn--kprw13d": _2,
          "台湾": _2,
          "xn--nnx388a": _2,
          "臺灣": _2,
          "xn--j1amh": _2,
          "укр": _2,
          "xn--mgb2ddes": _2,
          "اليمن": _2,
          "xxx": _2,
          "ye": _32,
          "za": {
            "$": 0,
            "succ": {
              "ac": _2,
              "agric": _2,
              "alt": _2,
              "co": _6,
              "edu": _2,
              "gov": _2,
              "grondar": _2,
              "law": _2,
              "mil": _2,
              "net": _2,
              "ngo": _2,
              "nic": _2,
              "nis": _2,
              "nom": _2,
              "org": _2,
              "school": _2,
              "tm": _2,
              "web": _2
            }
          },
          "zm": {
            "$": 1,
            "succ": {
              "ac": _2,
              "biz": _2,
              "co": _2,
              "com": _2,
              "edu": _2,
              "gov": _2,
              "info": _2,
              "mil": _2,
              "net": _2,
              "org": _2,
              "sch": _2
            }
          },
          "zw": {
            "$": 1,
            "succ": {
              "ac": _2,
              "co": _2,
              "gov": _2,
              "mil": _2,
              "org": _2
            }
          },
          "aaa": _2,
          "aarp": _2,
          "abarth": _2,
          "abb": _2,
          "abbott": _2,
          "abbvie": _2,
          "abc": _2,
          "able": _2,
          "abogado": _2,
          "abudhabi": _2,
          "academy": {
            "$": 1,
            "succ": {
              "official": _3
            }
          },
          "accenture": _2,
          "accountant": _2,
          "accountants": _2,
          "aco": _2,
          "actor": _2,
          "ads": _2,
          "adult": _2,
          "aeg": _2,
          "aetna": _2,
          "afl": _2,
          "africa": _2,
          "agakhan": _2,
          "agency": _2,
          "aig": _2,
          "airbus": _2,
          "airforce": _2,
          "airtel": _2,
          "akdn": _2,
          "alfaromeo": _2,
          "alibaba": _2,
          "alipay": _2,
          "allfinanz": _2,
          "allstate": _2,
          "ally": _2,
          "alsace": _2,
          "alstom": _2,
          "amazon": _2,
          "americanexpress": _2,
          "americanfamily": _2,
          "amex": _2,
          "amfam": _2,
          "amica": _2,
          "amsterdam": _2,
          "analytics": _2,
          "android": _2,
          "anquan": _2,
          "anz": _2,
          "aol": _2,
          "apartments": _2,
          "app": {
            "$": 1,
            "succ": {
              "beget": _5,
              "clerk": _3,
              "clerkstage": _3,
              "wnext": _3,
              "platform0": _3,
              "deta": _3,
              "ondigitalocean": _3,
              "easypanel": _3,
              "encr": _3,
              "edgecompute": _3,
              "fireweb": _3,
              "onflashdrive": _3,
              "framer": _3,
              "run": {
                "$": 2,
                "succ": {
                  "a": _3
                }
              },
              "web": _3,
              "hasura": _3,
              "loginline": _3,
              "messerli": _3,
              "netlify": _3,
              "ngrok": _3,
              "ngrok-free": _3,
              "developer": _5,
              "noop": _3,
              "northflank": _5,
              "snowflake": {
                "$": 2,
                "succ": {
                  "privatelink": _3
                }
              },
              "streamlit": _3,
              "telebit": _3,
              "typedream": _3,
              "vercel": _3,
              "bookonline": _3
            }
          },
          "apple": _2,
          "aquarelle": _2,
          "arab": _2,
          "aramco": _2,
          "archi": _2,
          "army": _2,
          "art": _2,
          "arte": _2,
          "asda": _2,
          "associates": _2,
          "athleta": _2,
          "attorney": _2,
          "auction": _2,
          "audi": _2,
          "audible": _2,
          "audio": _2,
          "auspost": _2,
          "author": _2,
          "auto": _2,
          "autos": _2,
          "avianca": _2,
          "aws": _2,
          "axa": _2,
          "azure": _2,
          "baby": _2,
          "baidu": _2,
          "banamex": _2,
          "bananarepublic": _2,
          "band": _2,
          "bank": _2,
          "bar": _2,
          "barcelona": _2,
          "barclaycard": _2,
          "barclays": _2,
          "barefoot": _2,
          "bargains": _2,
          "baseball": _2,
          "basketball": {
            "$": 1,
            "succ": {
              "aus": _3,
              "nz": _3
            }
          },
          "bauhaus": _2,
          "bayern": _2,
          "bbc": _2,
          "bbt": _2,
          "bbva": _2,
          "bcg": _2,
          "bcn": _2,
          "beats": _2,
          "beauty": _2,
          "beer": _2,
          "bentley": _2,
          "berlin": _2,
          "best": _2,
          "bestbuy": _2,
          "bet": _2,
          "bharti": _2,
          "bible": _2,
          "bid": _2,
          "bike": _2,
          "bing": _2,
          "bingo": _2,
          "bio": _2,
          "black": _2,
          "blackfriday": _2,
          "blockbuster": _2,
          "blog": _2,
          "bloomberg": _2,
          "blue": _2,
          "bms": _2,
          "bmw": _2,
          "bnpparibas": _2,
          "boats": _2,
          "boehringer": _2,
          "bofa": _2,
          "bom": _2,
          "bond": _2,
          "boo": _2,
          "book": _2,
          "booking": _2,
          "bosch": _2,
          "bostik": _2,
          "boston": _2,
          "bot": _2,
          "boutique": _2,
          "box": _2,
          "bradesco": _2,
          "bridgestone": _2,
          "broadway": _2,
          "broker": _2,
          "brother": _2,
          "brussels": _2,
          "build": _2,
          "builders": {
            "$": 1,
            "succ": {
              "cloudsite": _3
            }
          },
          "business": _10,
          "buy": _2,
          "buzz": _2,
          "bzh": _2,
          "cab": _2,
          "cafe": _2,
          "cal": _2,
          "call": _2,
          "calvinklein": _2,
          "cam": _2,
          "camera": _2,
          "camp": _2,
          "canon": _2,
          "capetown": _2,
          "capital": _2,
          "capitalone": _2,
          "car": _2,
          "caravan": _2,
          "cards": _2,
          "care": _2,
          "career": _2,
          "careers": _2,
          "cars": _2,
          "casa": {
            "$": 1,
            "succ": {
              "nabu": {
                "$": 0,
                "succ": {
                  "ui": _3
                }
              }
            }
          },
          "case": _2,
          "cash": _2,
          "casino": _2,
          "catering": _2,
          "catholic": _2,
          "cba": _2,
          "cbn": _2,
          "cbre": _2,
          "cbs": _2,
          "center": _2,
          "ceo": _2,
          "cern": _2,
          "cfa": _2,
          "cfd": _2,
          "chanel": _2,
          "channel": _2,
          "charity": _2,
          "chase": _2,
          "chat": _2,
          "cheap": _2,
          "chintai": _2,
          "christmas": _2,
          "chrome": _2,
          "church": _2,
          "cipriani": _2,
          "circle": _2,
          "cisco": _2,
          "citadel": _2,
          "citi": _2,
          "citic": _2,
          "city": _2,
          "cityeats": _2,
          "claims": _2,
          "cleaning": _2,
          "click": _2,
          "clinic": _2,
          "clinique": _2,
          "clothing": _2,
          "cloud": {
            "$": 1,
            "succ": {
              "banzai": _5,
              "elementor": _3,
              "encoway": {
                "$": 0,
                "succ": {
                  "eu": _3
                }
              },
              "statics": _5,
              "ravendb": _3,
              "axarnet": {
                "$": 0,
                "succ": {
                  "es-1": _3
                }
              },
              "diadem": _3,
              "jelastic": {
                "$": 0,
                "succ": {
                  "vip": _3
                }
              },
              "jele": _3,
              "jenv-aruba": {
                "$": 0,
                "succ": {
                  "aruba": {
                    "$": 0,
                    "succ": {
                      "eur": {
                        "$": 0,
                        "succ": {
                          "it1": _3
                        }
                      }
                    }
                  },
                  "it1": _3
                }
              },
              "keliweb": {
                "$": 2,
                "succ": {
                  "cs": _3
                }
              },
              "oxa": {
                "$": 2,
                "succ": {
                  "tn": _3,
                  "uk": _3
                }
              },
              "primetel": {
                "$": 2,
                "succ": {
                  "uk": _3
                }
              },
              "reclaim": {
                "$": 0,
                "succ": {
                  "ca": _3,
                  "uk": _3,
                  "us": _3
                }
              },
              "trendhosting": {
                "$": 0,
                "succ": {
                  "ch": _3,
                  "de": _3
                }
              },
              "jotelulu": _3,
              "kuleuven": _3,
              "linkyard": _3,
              "magentosite": _5,
              "perspecta": _3,
              "vapor": _3,
              "on-rancher": _5,
              "scw": {
                "$": 0,
                "succ": {
                  "baremetal": {
                    "$": 0,
                    "succ": {
                      "fr-par-1": _3,
                      "fr-par-2": _3,
                      "nl-ams-1": _3
                    }
                  },
                  "fr-par": {
                    "$": 0,
                    "succ": {
                      "fnc": {
                        "$": 2,
                        "succ": {
                          "functions": _3
                        }
                      },
                      "k8s": _11,
                      "s3": _3,
                      "s3-website": _3,
                      "whm": _3
                    }
                  },
                  "instances": {
                    "$": 0,
                    "succ": {
                      "priv": _3,
                      "pub": _3
                    }
                  },
                  "k8s": _3,
                  "nl-ams": {
                    "$": 0,
                    "succ": {
                      "k8s": _11,
                      "s3": _3,
                      "s3-website": _3,
                      "whm": _3
                    }
                  },
                  "pl-waw": {
                    "$": 0,
                    "succ": {
                      "k8s": _11,
                      "s3": _3,
                      "s3-website": _3
                    }
                  },
                  "scalebook": _3,
                  "smartlabeling": _3
                }
              },
              "sensiosite": _5,
              "trafficplex": _3,
              "urown": _3,
              "voorloper": _3
            }
          },
          "club": {
            "$": 1,
            "succ": {
              "cloudns": _3,
              "jele": _3,
              "barsy": _3
            }
          },
          "clubmed": _2,
          "coach": _2,
          "codes": {
            "$": 1,
            "succ": {
              "owo": _5
            }
          },
          "coffee": _2,
          "college": _2,
          "cologne": _2,
          "comcast": _2,
          "commbank": _2,
          "community": {
            "$": 1,
            "succ": {
              "nog": _3,
              "ravendb": _3,
              "myforum": _3
            }
          },
          "company": _2,
          "compare": _2,
          "computer": _2,
          "comsec": _2,
          "condos": _2,
          "construction": _2,
          "consulting": _2,
          "contact": _2,
          "contractors": _2,
          "cooking": _2,
          "cookingchannel": _2,
          "cool": {
            "$": 1,
            "succ": {
              "elementor": _3,
              "de": _3
            }
          },
          "corsica": _2,
          "country": _2,
          "coupon": _2,
          "coupons": _2,
          "courses": _2,
          "cpa": _2,
          "credit": _2,
          "creditcard": _2,
          "creditunion": _2,
          "cricket": _2,
          "crown": _2,
          "crs": _2,
          "cruise": _2,
          "cruises": _2,
          "cuisinella": _2,
          "cymru": _2,
          "cyou": _2,
          "dabur": _2,
          "dad": _2,
          "dance": _2,
          "data": _2,
          "date": _2,
          "dating": _2,
          "datsun": _2,
          "day": _2,
          "dclk": _2,
          "dds": _2,
          "deal": _2,
          "dealer": _2,
          "deals": _2,
          "degree": _2,
          "delivery": _2,
          "dell": _2,
          "deloitte": _2,
          "delta": _2,
          "democrat": _2,
          "dental": _2,
          "dentist": _2,
          "desi": _2,
          "design": {
            "$": 1,
            "succ": {
              "bss": _3
            }
          },
          "dev": {
            "$": 1,
            "succ": {
              "autocode": _3,
              "lcl": _5,
              "lclstage": _5,
              "stg": _5,
              "stgstage": _5,
              "pages": _3,
              "r2": _3,
              "workers": _3,
              "curv": _3,
              "deno": _3,
              "deno-staging": _3,
              "deta": _3,
              "fly": _3,
              "githubpreview": _3,
              "gateway": _5,
              "iserv": _3,
              "localcert": {
                "$": 0,
                "succ": {
                  "user": _5
                }
              },
              "loginline": _3,
              "mediatech": _3,
              "ngrok": _3,
              "ngrok-free": _3,
              "platter-app": _3,
              "shiftcrypto": _3,
              "vercel": _3,
              "webhare": _5
            }
          },
          "dhl": _2,
          "diamonds": _2,
          "diet": _2,
          "digital": {
            "$": 1,
            "succ": {
              "cloudapps": {
                "$": 2,
                "succ": {
                  "london": _3
                }
              }
            }
          },
          "direct": _2,
          "directory": _2,
          "discount": _2,
          "discover": _2,
          "dish": _2,
          "diy": _2,
          "dnp": _2,
          "docs": _2,
          "doctor": _2,
          "dog": _2,
          "domains": _2,
          "dot": _2,
          "download": _2,
          "drive": _2,
          "dtv": _2,
          "dubai": _2,
          "dunlop": _2,
          "dupont": _2,
          "durban": _2,
          "dvag": _2,
          "dvr": _2,
          "earth": {
            "$": 1,
            "succ": {
              "dapps": {
                "$": 0,
                "succ": {
                  "*": _3,
                  "bzz": _5
                }
              }
            }
          },
          "eat": _2,
          "eco": _2,
          "edeka": _2,
          "education": _10,
          "email": _2,
          "emerck": _2,
          "energy": _2,
          "engineer": _2,
          "engineering": _2,
          "enterprises": _2,
          "epson": _2,
          "equipment": _2,
          "ericsson": _2,
          "erni": _2,
          "esq": _2,
          "estate": {
            "$": 1,
            "succ": {
              "compute": _5
            }
          },
          "etisalat": _2,
          "eurovision": _2,
          "eus": {
            "$": 1,
            "succ": {
              "party": _28
            }
          },
          "events": {
            "$": 1,
            "succ": {
              "koobin": _3,
              "co": _3
            }
          },
          "exchange": _2,
          "expert": _2,
          "exposed": _2,
          "express": _2,
          "extraspace": _2,
          "fage": _2,
          "fail": _2,
          "fairwinds": _2,
          "faith": _29,
          "family": _2,
          "fan": _2,
          "fans": _2,
          "farm": {
            "$": 1,
            "succ": {
              "storj": _3
            }
          },
          "farmers": _2,
          "fashion": _2,
          "fast": _2,
          "fedex": _2,
          "feedback": _2,
          "ferrari": _2,
          "ferrero": _2,
          "fiat": _2,
          "fidelity": _2,
          "fido": _2,
          "film": _2,
          "final": _2,
          "finance": _2,
          "financial": _10,
          "fire": _2,
          "firestone": _2,
          "firmdale": _2,
          "fish": _2,
          "fishing": _2,
          "fit": _2,
          "fitness": _2,
          "flickr": _2,
          "flights": _2,
          "flir": _2,
          "florist": _2,
          "flowers": _2,
          "fly": _2,
          "foo": _2,
          "food": _2,
          "foodnetwork": _2,
          "football": _2,
          "ford": _2,
          "forex": _2,
          "forsale": _2,
          "forum": _2,
          "foundation": _2,
          "fox": _2,
          "free": _2,
          "fresenius": _2,
          "frl": _2,
          "frogans": _2,
          "frontdoor": _2,
          "frontier": _2,
          "ftr": _2,
          "fujitsu": _2,
          "fun": _2,
          "fund": _2,
          "furniture": _2,
          "futbol": _2,
          "fyi": _2,
          "gal": _2,
          "gallery": _2,
          "gallo": _2,
          "gallup": _2,
          "game": _2,
          "games": _2,
          "gap": _2,
          "garden": _2,
          "gay": _2,
          "gbiz": _2,
          "gdn": {
            "$": 1,
            "succ": {
              "cnpy": _3
            }
          },
          "gea": _2,
          "gent": _2,
          "genting": _2,
          "george": _2,
          "ggee": _2,
          "gift": _2,
          "gifts": _2,
          "gives": _2,
          "giving": _2,
          "glass": _2,
          "gle": _2,
          "global": _2,
          "globo": _2,
          "gmail": _2,
          "gmbh": _2,
          "gmo": _2,
          "gmx": _2,
          "godaddy": _2,
          "gold": _2,
          "goldpoint": _2,
          "golf": _2,
          "goo": _2,
          "goodyear": _2,
          "goog": {
            "$": 1,
            "succ": {
              "cloud": _3,
              "translate": _3,
              "usercontent": _5
            }
          },
          "google": _2,
          "gop": _2,
          "got": _2,
          "grainger": _2,
          "graphics": _2,
          "gratis": _2,
          "green": _2,
          "gripe": _2,
          "grocery": _2,
          "group": {
            "$": 1,
            "succ": {
              "discourse": _3
            }
          },
          "guardian": _2,
          "gucci": _2,
          "guge": _2,
          "guide": _2,
          "guitars": _2,
          "guru": _2,
          "hair": _2,
          "hamburg": _2,
          "hangout": _2,
          "haus": _2,
          "hbo": _2,
          "hdfc": _2,
          "hdfcbank": _2,
          "health": {
            "$": 1,
            "succ": {
              "hra": _3
            }
          },
          "healthcare": _2,
          "help": _2,
          "helsinki": _2,
          "here": _2,
          "hermes": _2,
          "hgtv": _2,
          "hiphop": _2,
          "hisamitsu": _2,
          "hitachi": _2,
          "hiv": _2,
          "hkt": _2,
          "hockey": _2,
          "holdings": _2,
          "holiday": _2,
          "homedepot": _2,
          "homegoods": _2,
          "homes": _2,
          "homesense": _2,
          "honda": _2,
          "horse": _2,
          "hospital": _2,
          "host": {
            "$": 1,
            "succ": {
              "cloudaccess": _3,
              "freesite": _3,
              "easypanel": _3,
              "fastvps": _3,
              "myfast": _3,
              "tempurl": _3,
              "wpmudev": _3,
              "jele": _3,
              "mircloud": _3,
              "pcloud": _3,
              "half": _3
            }
          },
          "hosting": {
            "$": 1,
            "succ": {
              "opencraft": _3
            }
          },
          "hot": _2,
          "hoteles": _2,
          "hotels": _2,
          "hotmail": _2,
          "house": _2,
          "how": _2,
          "hsbc": _2,
          "hughes": _2,
          "hyatt": _2,
          "hyundai": _2,
          "ibm": _2,
          "icbc": _2,
          "ice": _2,
          "icu": _2,
          "ieee": _2,
          "ifm": _2,
          "ikano": _2,
          "imamat": _2,
          "imdb": _2,
          "immo": _2,
          "immobilien": _2,
          "inc": _2,
          "industries": _2,
          "infiniti": _2,
          "ing": _2,
          "ink": _2,
          "institute": _2,
          "insurance": _2,
          "insure": _2,
          "international": _2,
          "intuit": _2,
          "investments": _2,
          "ipiranga": _2,
          "irish": _2,
          "ismaili": _2,
          "ist": _2,
          "istanbul": _2,
          "itau": _2,
          "itv": _2,
          "jaguar": _2,
          "java": _2,
          "jcb": _2,
          "jeep": _2,
          "jetzt": _2,
          "jewelry": _2,
          "jio": _2,
          "jll": _2,
          "jmp": _2,
          "jnj": _2,
          "joburg": _2,
          "jot": _2,
          "joy": _2,
          "jpmorgan": _2,
          "jprs": _2,
          "juegos": _2,
          "juniper": _2,
          "kaufen": _2,
          "kddi": _2,
          "kerryhotels": _2,
          "kerrylogistics": _2,
          "kerryproperties": _2,
          "kfh": _2,
          "kia": _2,
          "kids": _2,
          "kim": _2,
          "kinder": _2,
          "kindle": _2,
          "kitchen": _2,
          "kiwi": _2,
          "koeln": _2,
          "komatsu": _2,
          "kosher": _2,
          "kpmg": _2,
          "kpn": _2,
          "krd": {
            "$": 1,
            "succ": {
              "co": _3,
              "edu": _3
            }
          },
          "kred": _2,
          "kuokgroup": _2,
          "kyoto": _2,
          "lacaixa": _2,
          "lamborghini": _2,
          "lamer": _2,
          "lancaster": _2,
          "lancia": _2,
          "land": {
            "$": 1,
            "succ": {
              "static": {
                "$": 2,
                "succ": {
                  "dev": _3,
                  "sites": _3
                }
              }
            }
          },
          "landrover": _2,
          "lanxess": _2,
          "lasalle": _2,
          "lat": _2,
          "latino": _2,
          "latrobe": _2,
          "law": _2,
          "lawyer": _2,
          "lds": _2,
          "lease": _2,
          "leclerc": _2,
          "lefrak": _2,
          "legal": _2,
          "lego": _2,
          "lexus": _2,
          "lgbt": _2,
          "lidl": _2,
          "life": _2,
          "lifeinsurance": _2,
          "lifestyle": _2,
          "lighting": _2,
          "like": _2,
          "lilly": _2,
          "limited": _2,
          "limo": _2,
          "lincoln": _2,
          "link": {
            "$": 1,
            "succ": {
              "cyon": _3,
              "mypep": _3,
              "dweb": _5
            }
          },
          "lipsy": _2,
          "live": {
            "$": 1,
            "succ": {
              "hlx": _3
            }
          },
          "living": _2,
          "llc": _2,
          "llp": _2,
          "loan": _2,
          "loans": _2,
          "locker": _2,
          "locus": _2,
          "lol": {
            "$": 1,
            "succ": {
              "omg": _3
            }
          },
          "london": _2,
          "lotte": _2,
          "lotto": _2,
          "love": _2,
          "lpl": _2,
          "lplfinancial": _2,
          "ltd": _2,
          "ltda": _2,
          "lundbeck": _2,
          "luxe": _2,
          "luxury": _2,
          "madrid": _2,
          "maif": _2,
          "maison": _2,
          "makeup": _2,
          "man": _2,
          "management": {
            "$": 1,
            "succ": {
              "router": _3
            }
          },
          "mango": _2,
          "map": _2,
          "market": _2,
          "marketing": _2,
          "markets": _2,
          "marriott": _2,
          "marshalls": _2,
          "maserati": _2,
          "mattel": _2,
          "mba": _2,
          "mckinsey": _2,
          "med": _2,
          "media": _35,
          "meet": _2,
          "melbourne": _2,
          "meme": _2,
          "memorial": _2,
          "men": _2,
          "menu": _36,
          "merckmsd": _2,
          "miami": _2,
          "microsoft": _2,
          "mini": _2,
          "mint": _2,
          "mit": _2,
          "mitsubishi": _2,
          "mlb": _2,
          "mls": _2,
          "mma": _2,
          "mobile": _2,
          "moda": _2,
          "moe": _2,
          "moi": _2,
          "mom": _2,
          "monash": _2,
          "money": _2,
          "monster": _2,
          "mormon": _2,
          "mortgage": _2,
          "moscow": _2,
          "moto": _2,
          "motorcycles": _2,
          "mov": _2,
          "movie": _2,
          "msd": _2,
          "mtn": _2,
          "mtr": _2,
          "music": _2,
          "mutual": _2,
          "nab": _2,
          "nagoya": _2,
          "natura": _2,
          "navy": _2,
          "nba": _2,
          "nec": _2,
          "netbank": _2,
          "netflix": _2,
          "network": {
            "$": 1,
            "succ": {
              "alces": _5,
              "co": _3,
              "arvo": _3,
              "azimuth": _3,
              "tlon": _3
            }
          },
          "neustar": _2,
          "new": _2,
          "news": {
            "$": 1,
            "succ": {
              "noticeable": _3
            }
          },
          "next": _2,
          "nextdirect": _2,
          "nexus": _2,
          "nfl": _2,
          "ngo": _2,
          "nhk": _2,
          "nico": _2,
          "nike": _2,
          "nikon": _2,
          "ninja": _2,
          "nissan": _2,
          "nissay": _2,
          "nokia": _2,
          "northwesternmutual": _2,
          "norton": _2,
          "now": _2,
          "nowruz": _2,
          "nowtv": _2,
          "nra": _2,
          "nrw": _2,
          "ntt": _2,
          "nyc": _2,
          "obi": _2,
          "observer": _2,
          "office": _2,
          "okinawa": _2,
          "olayan": _2,
          "olayangroup": _2,
          "oldnavy": _2,
          "ollo": _2,
          "omega": _2,
          "one": {
            "$": 1,
            "succ": {
              "onred": {
                "$": 2,
                "succ": {
                  "staging": _3
                }
              },
              "service": _3,
              "homelink": _3
            }
          },
          "ong": _2,
          "onl": _2,
          "online": {
            "$": 1,
            "succ": {
              "eero": _3,
              "eero-stage": _3,
              "barsy": _3
            }
          },
          "ooo": _2,
          "open": _2,
          "oracle": _2,
          "orange": {
            "$": 1,
            "succ": {
              "tech": _3
            }
          },
          "organic": _2,
          "origins": _2,
          "osaka": _2,
          "otsuka": _2,
          "ott": _2,
          "ovh": {
            "$": 1,
            "succ": {
              "nerdpol": _3
            }
          },
          "page": {
            "$": 1,
            "succ": {
              "hlx": _3,
              "hlx3": _3,
              "translated": _3,
              "codeberg": _3,
              "pdns": _3,
              "plesk": _3,
              "prvcy": _3,
              "rocky": _3,
              "magnet": _3
            }
          },
          "panasonic": _2,
          "paris": _2,
          "pars": _2,
          "partners": _2,
          "parts": _2,
          "party": _29,
          "passagens": _2,
          "pay": _2,
          "pccw": _2,
          "pet": _2,
          "pfizer": _2,
          "pharmacy": _2,
          "phd": _2,
          "philips": _2,
          "phone": _2,
          "photo": _2,
          "photography": _2,
          "photos": _35,
          "physio": _2,
          "pics": _2,
          "pictet": _2,
          "pictures": {
            "$": 1,
            "succ": {
              "1337": _3
            }
          },
          "pid": _2,
          "pin": _2,
          "ping": _2,
          "pink": _2,
          "pioneer": _2,
          "pizza": {
            "$": 1,
            "succ": {
              "ngrok": _3
            }
          },
          "place": _10,
          "play": _2,
          "playstation": _2,
          "plumbing": _2,
          "plus": _2,
          "pnc": _2,
          "pohl": _2,
          "poker": _2,
          "politie": _2,
          "porn": {
            "$": 1,
            "succ": {
              "indie": _3
            }
          },
          "pramerica": _2,
          "praxi": _2,
          "press": _2,
          "prime": _2,
          "prod": _2,
          "productions": _2,
          "prof": _2,
          "progressive": _2,
          "promo": _2,
          "properties": _2,
          "property": _2,
          "protection": _2,
          "pru": _2,
          "prudential": _2,
          "pub": _36,
          "pwc": _2,
          "qpon": _2,
          "quebec": _2,
          "quest": _2,
          "racing": _2,
          "radio": _2,
          "read": _2,
          "realestate": _2,
          "realtor": _2,
          "realty": _2,
          "recipes": _2,
          "red": _2,
          "redstone": _2,
          "redumbrella": _2,
          "rehab": _2,
          "reise": _2,
          "reisen": _2,
          "reit": _2,
          "reliance": _2,
          "ren": _2,
          "rent": _2,
          "rentals": _2,
          "repair": _2,
          "report": _2,
          "republican": _2,
          "rest": _2,
          "restaurant": _2,
          "review": _29,
          "reviews": _2,
          "rexroth": _2,
          "rich": _2,
          "richardli": _2,
          "ricoh": _2,
          "ril": _2,
          "rio": _2,
          "rip": {
            "$": 1,
            "succ": {
              "clan": _3
            }
          },
          "rocher": _2,
          "rocks": {
            "$": 1,
            "succ": {
              "myddns": _3,
              "lima-city": _3,
              "webspace": _3
            }
          },
          "rodeo": _2,
          "rogers": _2,
          "room": _2,
          "rsvp": _2,
          "rugby": _2,
          "ruhr": _2,
          "run": {
            "$": 1,
            "succ": {
              "hs": _3,
              "development": _3,
              "ravendb": _3,
              "servers": _3,
              "build": _5,
              "code": _5,
              "database": _5,
              "migration": _5,
              "onporter": _3,
              "repl": _3
            }
          },
          "rwe": _2,
          "ryukyu": _2,
          "saarland": _2,
          "safe": _2,
          "safety": _2,
          "sakura": _2,
          "sale": _2,
          "salon": _2,
          "samsclub": _2,
          "samsung": _2,
          "sandvik": _2,
          "sandvikcoromant": _2,
          "sanofi": _2,
          "sap": _2,
          "sarl": _2,
          "sas": _2,
          "save": _2,
          "saxo": _2,
          "sbi": _2,
          "sbs": _2,
          "sca": _2,
          "scb": _2,
          "schaeffler": _2,
          "schmidt": _2,
          "scholarships": _2,
          "school": _2,
          "schule": _2,
          "schwarz": _2,
          "science": _29,
          "scot": {
            "$": 1,
            "succ": {
              "edu": _3,
              "gov": {
                "$": 2,
                "succ": {
                  "service": _3
                }
              }
            }
          },
          "search": _2,
          "seat": _2,
          "secure": _2,
          "security": _2,
          "seek": _2,
          "select": _2,
          "sener": _2,
          "services": {
            "$": 1,
            "succ": {
              "loginline": _3
            }
          },
          "seven": _2,
          "sew": _2,
          "sex": _2,
          "sexy": _2,
          "sfr": _2,
          "shangrila": _2,
          "sharp": _2,
          "shaw": _2,
          "shell": _2,
          "shia": _2,
          "shiksha": _2,
          "shoes": _2,
          "shop": {
            "$": 1,
            "succ": {
              "base": _3,
              "hoplix": _3,
              "barsy": _3
            }
          },
          "shopping": _2,
          "shouji": _2,
          "show": _2,
          "showtime": _2,
          "silk": _2,
          "sina": _2,
          "singles": _2,
          "site": {
            "$": 1,
            "succ": {
              "cloudera": _5,
              "cyon": _3,
              "fnwk": _3,
              "folionetwork": _3,
              "fastvps": _3,
              "jele": _3,
              "lelux": _3,
              "loginline": _3,
              "barsy": _3,
              "mintere": _3,
              "omniwe": _3,
              "opensocial": _3,
              "platformsh": _5,
              "tst": _5,
              "byen": _3,
              "srht": _3,
              "novecore": _3
            }
          },
          "ski": _2,
          "skin": _2,
          "sky": _2,
          "skype": _2,
          "sling": _2,
          "smart": _2,
          "smile": _2,
          "sncf": _2,
          "soccer": _2,
          "social": _2,
          "softbank": _2,
          "software": _2,
          "sohu": _2,
          "solar": _2,
          "solutions": {
            "$": 1,
            "succ": {
              "diher": _5
            }
          },
          "song": _2,
          "sony": _2,
          "soy": _2,
          "spa": _2,
          "space": {
            "$": 1,
            "succ": {
              "myfast": _3,
              "uber": _3,
              "xs4all": _3
            }
          },
          "sport": _2,
          "spot": _2,
          "srl": _2,
          "stada": _2,
          "staples": _2,
          "star": _2,
          "statebank": _2,
          "statefarm": _2,
          "stc": _2,
          "stcgroup": _2,
          "stockholm": _2,
          "storage": _2,
          "store": {
            "$": 1,
            "succ": {
              "sellfy": _3,
              "shopware": _3,
              "storebase": _3
            }
          },
          "stream": _2,
          "studio": _2,
          "study": _2,
          "style": _2,
          "sucks": _2,
          "supplies": _2,
          "supply": _2,
          "support": _36,
          "surf": _2,
          "surgery": _2,
          "suzuki": _2,
          "swatch": _2,
          "swiss": _2,
          "sydney": _2,
          "systems": {
            "$": 1,
            "succ": {
              "knightpoint": _3
            }
          },
          "tab": _2,
          "taipei": _2,
          "talk": _2,
          "taobao": _2,
          "target": _2,
          "tatamotors": _2,
          "tatar": _2,
          "tattoo": _2,
          "tax": _2,
          "taxi": _2,
          "tci": _2,
          "tdk": _2,
          "team": {
            "$": 1,
            "succ": {
              "discourse": _3,
              "jelastic": _3
            }
          },
          "tech": _2,
          "technology": _10,
          "temasek": _2,
          "tennis": _2,
          "teva": _2,
          "thd": _2,
          "theater": _2,
          "theatre": _2,
          "tiaa": _2,
          "tickets": _2,
          "tienda": _2,
          "tiffany": _2,
          "tips": _2,
          "tires": _2,
          "tirol": _2,
          "tjmaxx": _2,
          "tjx": _2,
          "tkmaxx": _2,
          "tmall": _2,
          "today": {
            "$": 1,
            "succ": {
              "prequalifyme": _3
            }
          },
          "tokyo": _2,
          "tools": _2,
          "top": {
            "$": 1,
            "succ": {
              "now-dns": _3,
              "ntdll": _3
            }
          },
          "toray": _2,
          "toshiba": _2,
          "total": _2,
          "tours": _2,
          "town": _2,
          "toyota": _2,
          "toys": _2,
          "trade": _29,
          "trading": _2,
          "training": _2,
          "travel": _2,
          "travelchannel": _2,
          "travelers": _2,
          "travelersinsurance": _2,
          "trust": _2,
          "trv": _2,
          "tube": _2,
          "tui": _2,
          "tunes": _2,
          "tushu": _2,
          "tvs": _2,
          "ubank": _2,
          "ubs": _2,
          "unicom": _2,
          "university": _2,
          "uno": _2,
          "uol": _2,
          "ups": _2,
          "vacations": _2,
          "vana": _2,
          "vanguard": _2,
          "vegas": _2,
          "ventures": _2,
          "verisign": _2,
          "versicherung": _2,
          "vet": _2,
          "viajes": _2,
          "video": _2,
          "vig": _2,
          "viking": _2,
          "villas": _2,
          "vin": _2,
          "vip": _2,
          "virgin": _2,
          "visa": _2,
          "vision": _2,
          "viva": _2,
          "vivo": _2,
          "vlaanderen": _2,
          "vodka": _2,
          "volkswagen": _2,
          "volvo": _2,
          "vote": _2,
          "voting": _2,
          "voto": _2,
          "voyage": _2,
          "vuelos": _2,
          "wales": _2,
          "walmart": _2,
          "walter": _2,
          "wang": _2,
          "wanggou": _2,
          "watch": _2,
          "watches": _2,
          "weather": _2,
          "weatherchannel": _2,
          "webcam": _2,
          "weber": _2,
          "website": _35,
          "wedding": _2,
          "weibo": _2,
          "weir": _2,
          "whoswho": _2,
          "wien": _2,
          "wiki": _35,
          "williamhill": _2,
          "win": _2,
          "windows": _2,
          "wine": _2,
          "winners": _2,
          "wme": _2,
          "wolterskluwer": _2,
          "woodside": _2,
          "work": _2,
          "works": _2,
          "world": _2,
          "wow": _2,
          "wtc": _2,
          "wtf": _2,
          "xbox": _2,
          "xerox": _2,
          "xfinity": _2,
          "xihuan": _2,
          "xin": _2,
          "xn--11b4c3d": _2,
          "कॉम": _2,
          "xn--1ck2e1b": _2,
          "セール": _2,
          "xn--1qqw23a": _2,
          "佛山": _2,
          "xn--30rr7y": _2,
          "慈善": _2,
          "xn--3bst00m": _2,
          "集团": _2,
          "xn--3ds443g": _2,
          "在线": _2,
          "xn--3pxu8k": _2,
          "点看": _2,
          "xn--42c2d9a": _2,
          "คอม": _2,
          "xn--45q11c": _2,
          "八卦": _2,
          "xn--4gbrim": _2,
          "موقع": _2,
          "xn--55qw42g": _2,
          "公益": _2,
          "xn--55qx5d": _2,
          "公司": _2,
          "xn--5su34j936bgsg": _2,
          "香格里拉": _2,
          "xn--5tzm5g": _2,
          "网站": _2,
          "xn--6frz82g": _2,
          "移动": _2,
          "xn--6qq986b3xl": _2,
          "我爱你": _2,
          "xn--80adxhks": _2,
          "москва": _2,
          "xn--80aqecdr1a": _2,
          "католик": _2,
          "xn--80asehdb": _2,
          "онлайн": _2,
          "xn--80aswg": _2,
          "сайт": _2,
          "xn--8y0a063a": _2,
          "联通": _2,
          "xn--9dbq2a": _2,
          "קום": _2,
          "xn--9et52u": _2,
          "时尚": _2,
          "xn--9krt00a": _2,
          "微博": _2,
          "xn--b4w605ferd": _2,
          "淡马锡": _2,
          "xn--bck1b9a5dre4c": _2,
          "ファッション": _2,
          "xn--c1avg": _2,
          "орг": _2,
          "xn--c2br7g": _2,
          "नेट": _2,
          "xn--cck2b3b": _2,
          "ストア": _2,
          "xn--cckwcxetd": _2,
          "アマゾン": _2,
          "xn--cg4bki": _2,
          "삼성": _2,
          "xn--czr694b": _2,
          "商标": _2,
          "xn--czrs0t": _2,
          "商店": _2,
          "xn--czru2d": _2,
          "商城": _2,
          "xn--d1acj3b": _2,
          "дети": _2,
          "xn--eckvdtc9d": _2,
          "ポイント": _2,
          "xn--efvy88h": _2,
          "新闻": _2,
          "xn--fct429k": _2,
          "家電": _2,
          "xn--fhbei": _2,
          "كوم": _2,
          "xn--fiq228c5hs": _2,
          "中文网": _2,
          "xn--fiq64b": _2,
          "中信": _2,
          "xn--fjq720a": _2,
          "娱乐": _2,
          "xn--flw351e": _2,
          "谷歌": _2,
          "xn--fzys8d69uvgm": _2,
          "電訊盈科": _2,
          "xn--g2xx48c": _2,
          "购物": _2,
          "xn--gckr3f0f": _2,
          "クラウド": _2,
          "xn--gk3at1e": _2,
          "通販": _2,
          "xn--hxt814e": _2,
          "网店": _2,
          "xn--i1b6b1a6a2e": _2,
          "संगठन": _2,
          "xn--imr513n": _2,
          "餐厅": _2,
          "xn--io0a7i": _2,
          "网络": _2,
          "xn--j1aef": _2,
          "ком": _2,
          "xn--jlq480n2rg": _2,
          "亚马逊": _2,
          "xn--jvr189m": _2,
          "食品": _2,
          "xn--kcrx77d1x4a": _2,
          "飞利浦": _2,
          "xn--kput3i": _2,
          "手机": _2,
          "xn--mgba3a3ejt": _2,
          "ارامكو": _2,
          "xn--mgba7c0bbn0a": _2,
          "العليان": _2,
          "xn--mgbaakc7dvf": _2,
          "اتصالات": _2,
          "xn--mgbab2bd": _2,
          "بازار": _2,
          "xn--mgbca7dzdo": _2,
          "ابوظبي": _2,
          "xn--mgbi4ecexp": _2,
          "كاثوليك": _2,
          "xn--mgbt3dhd": _2,
          "همراه": _2,
          "xn--mk1bu44c": _2,
          "닷컴": _2,
          "xn--mxtq1m": _2,
          "政府": _2,
          "xn--ngbc5azd": _2,
          "شبكة": _2,
          "xn--ngbe9e0a": _2,
          "بيتك": _2,
          "xn--ngbrx": _2,
          "عرب": _2,
          "xn--nqv7f": _2,
          "机构": _2,
          "xn--nqv7fs00ema": _2,
          "组织机构": _2,
          "xn--nyqy26a": _2,
          "健康": _2,
          "xn--otu796d": _2,
          "招聘": _2,
          "xn--p1acf": {
            "$": 1,
            "succ": {
              "xn--90amc": _3,
              "xn--j1aef": _3,
              "xn--j1ael8b": _3,
              "xn--h1ahn": _3,
              "xn--j1adp": _3,
              "xn--c1avg": _3,
              "xn--80aaa0cvac": _3,
              "xn--h1aliz": _3,
              "xn--90a1af": _3,
              "xn--41a": _3
            }
          },
          "рус": {
            "$": 1,
            "succ": {
              "биз": _3,
              "ком": _3,
              "крым": _3,
              "мир": _3,
              "мск": _3,
              "орг": _3,
              "самара": _3,
              "сочи": _3,
              "спб": _3,
              "я": _3
            }
          },
          "xn--pssy2u": _2,
          "大拿": _2,
          "xn--q9jyb4c": _2,
          "みんな": _2,
          "xn--qcka1pmc": _2,
          "グーグル": _2,
          "xn--rhqv96g": _2,
          "世界": _2,
          "xn--rovu88b": _2,
          "書籍": _2,
          "xn--ses554g": _2,
          "网址": _2,
          "xn--t60b56a": _2,
          "닷넷": _2,
          "xn--tckwe": _2,
          "コム": _2,
          "xn--tiq49xqyj": _2,
          "天主教": _2,
          "xn--unup4y": _2,
          "游戏": _2,
          "xn--vermgensberater-ctb": _2,
          "vermögensberater": _2,
          "xn--vermgensberatung-pwb": _2,
          "vermögensberatung": _2,
          "xn--vhquv": _2,
          "企业": _2,
          "xn--vuq861b": _2,
          "信息": _2,
          "xn--w4r85el8fhu5dnra": _2,
          "嘉里大酒店": _2,
          "xn--w4rs40l": _2,
          "嘉里": _2,
          "xn--xhq521b": _2,
          "广东": _2,
          "xn--zfr164b": _2,
          "政务": _2,
          "xyz": {
            "$": 1,
            "succ": {
              "blogsite": _3,
              "localzone": _3,
              "crafting": _3,
              "zapto": _3,
              "telebit": _5
            }
          },
          "yachts": _2,
          "yahoo": _2,
          "yamaxun": _2,
          "yandex": _2,
          "yodobashi": _2,
          "yoga": _2,
          "yokohama": _2,
          "you": _2,
          "youtube": _2,
          "yun": _2,
          "zappos": _2,
          "zara": _2,
          "zero": _2,
          "zip": _2,
          "zone": {
            "$": 1,
            "succ": {
              "cloud66": _3,
              "hs": _3,
              "triton": _5,
              "lima": _3
            }
          },
          "zuerich": _2
        }
      };
      return rules;
    }();

    /**
     * Lookup parts of domain in Trie
     */
    function lookupInTrie(parts, trie, index, allowedMask) {
      var result = null;
      var node = trie;
      while (node !== undefined) {
        // We have a match!
        if ((node.$ & allowedMask) !== 0) {
          result = {
            index: index + 1,
            isIcann: node.$ === 1 /* RULE_TYPE.ICANN */,
            isPrivate: node.$ === 2 /* RULE_TYPE.PRIVATE */
          };
        }
        // No more `parts` to look for
        if (index === -1) {
          break;
        }
        var succ = node.succ;
        node = succ && (succ[parts[index]] || succ['*']);
        index -= 1;
      }
      return result;
    }
    /**
     * Check if `hostname` has a valid public suffix in `trie`.
     */
    function suffixLookup(hostname, options, out) {
      if (fastPathLookup(hostname, options, out) === true) {
        return;
      }
      var hostnameParts = hostname.split('.');
      var allowedMask = (options.allowPrivateDomains === true ? 2 /* RULE_TYPE.PRIVATE */ : 0) | (options.allowIcannDomains === true ? 1 /* RULE_TYPE.ICANN */ : 0);
      // Look for exceptions
      var exceptionMatch = lookupInTrie(hostnameParts, exceptions, hostnameParts.length - 1, allowedMask);
      if (exceptionMatch !== null) {
        out.isIcann = exceptionMatch.isIcann;
        out.isPrivate = exceptionMatch.isPrivate;
        out.publicSuffix = hostnameParts.slice(exceptionMatch.index + 1).join('.');
        return;
      }
      // Look for a match in rules
      var rulesMatch = lookupInTrie(hostnameParts, rules, hostnameParts.length - 1, allowedMask);
      if (rulesMatch !== null) {
        out.isIcann = rulesMatch.isIcann;
        out.isPrivate = rulesMatch.isPrivate;
        out.publicSuffix = hostnameParts.slice(rulesMatch.index).join('.');
        return;
      }
      // No match found...
      // Prevailing rule is '*' so we consider the top-level domain to be the
      // public suffix of `hostname` (e.g.: 'example.org' => 'org').
      out.isIcann = false;
      out.isPrivate = false;
      out.publicSuffix = hostnameParts[hostnameParts.length - 1];
    }

    // For all methods but 'parse', it does not make sense to allocate an object
    // every single time to only return the value of a specific attribute. To avoid
    // this un-necessary allocation, we use a global object which is re-used.
    var RESULT = getEmptyResult();
    function parse(url) {
      var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
      return parseImpl(url, 5 /* FLAG.ALL */, suffixLookup, options, getEmptyResult());
    }
    function getHostname(url) {
      var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
      /*@__INLINE__*/resetResult(RESULT);
      return parseImpl(url, 0 /* FLAG.HOSTNAME */, suffixLookup, options, RESULT).hostname;
    }
    function getDomain(url) {
      var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
      /*@__INLINE__*/resetResult(RESULT);
      return parseImpl(url, 3 /* FLAG.DOMAIN */, suffixLookup, options, RESULT).domain;
    }

    var word = '[a-fA-F\\d:]';
    var b = function b(options) {
      return options && options.includeBoundaries ? "(?:(?<=\\s|^)(?=".concat(word, ")|(?<=").concat(word, ")(?=\\s|$))") : '';
    };
    var v4 = '(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]\\d|\\d)(?:\\.(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]\\d|\\d)){3}';
    var v6seg = '[a-fA-F\\d]{1,4}';
    var v6 = "\n(?:\n(?:".concat(v6seg, ":){7}(?:").concat(v6seg, "|:)|                                    // 1:2:3:4:5:6:7::  1:2:3:4:5:6:7:8\n(?:").concat(v6seg, ":){6}(?:").concat(v4, "|:").concat(v6seg, "|:)|                             // 1:2:3:4:5:6::    1:2:3:4:5:6::8   1:2:3:4:5:6::8  1:2:3:4:5:6::1.2.3.4\n(?:").concat(v6seg, ":){5}(?::").concat(v4, "|(?::").concat(v6seg, "){1,2}|:)|                   // 1:2:3:4:5::      1:2:3:4:5::7:8   1:2:3:4:5::8    1:2:3:4:5::7:1.2.3.4\n(?:").concat(v6seg, ":){4}(?:(?::").concat(v6seg, "){0,1}:").concat(v4, "|(?::").concat(v6seg, "){1,3}|:)| // 1:2:3:4::        1:2:3:4::6:7:8   1:2:3:4::8      1:2:3:4::6:7:1.2.3.4\n(?:").concat(v6seg, ":){3}(?:(?::").concat(v6seg, "){0,2}:").concat(v4, "|(?::").concat(v6seg, "){1,4}|:)| // 1:2:3::          1:2:3::5:6:7:8   1:2:3::8        1:2:3::5:6:7:1.2.3.4\n(?:").concat(v6seg, ":){2}(?:(?::").concat(v6seg, "){0,3}:").concat(v4, "|(?::").concat(v6seg, "){1,5}|:)| // 1:2::            1:2::4:5:6:7:8   1:2::8          1:2::4:5:6:7:1.2.3.4\n(?:").concat(v6seg, ":){1}(?:(?::").concat(v6seg, "){0,4}:").concat(v4, "|(?::").concat(v6seg, "){1,6}|:)| // 1::              1::3:4:5:6:7:8   1::8            1::3:4:5:6:7:1.2.3.4\n(?::(?:(?::").concat(v6seg, "){0,5}:").concat(v4, "|(?::").concat(v6seg, "){1,7}|:))             // ::2:3:4:5:6:7:8  ::2:3:4:5:6:7:8  ::8             ::1.2.3.4\n)(?:%[0-9a-zA-Z]{1,})?                                             // %eth0            %1\n").replace(/\s*\/\/.*$/gm, '').replace(/\n/g, '').trim();

    // Pre-compile only the exact regexes because adding a global flag make regexes stateful
    var v46Exact = new RegExp("(?:^".concat(v4, "$)|(?:^").concat(v6, "$)"));
    var v4exact = new RegExp("^".concat(v4, "$"));
    var v6exact = new RegExp("^".concat(v6, "$"));
    var ip = function ip(options) {
      return options && options.exact ? v46Exact : new RegExp("(?:".concat(b(options)).concat(v4).concat(b(options), ")|(?:").concat(b(options)).concat(v6).concat(b(options), ")"), 'g');
    };
    ip.v4 = function (options) {
      return options && options.exact ? v4exact : new RegExp("".concat(b(options)).concat(v4).concat(b(options)), 'g');
    };
    ip.v6 = function (options) {
      return options && options.exact ? v6exact : new RegExp("".concat(b(options)).concat(v6).concat(b(options)), 'g');
    };
    var ipRegex$1 = ip;

    var ipRegex = ipRegex$1;
    var isIp = function isIp(string) {
      return ipRegex({
        exact: true
      }).test(string);
    };
    isIp.v4 = function (string) {
      return ipRegex.v4({
        exact: true
      }).test(string);
    };
    isIp.v6 = function (string) {
      return ipRegex.v6({
        exact: true
      }).test(string);
    };
    isIp.version = function (string) {
      return isIp(string) ? isIp.v4(string) ? 4 : 6 : undefined;
    };
    var isIp_1 = isIp;
    var isIp$1 = /*@__PURE__*/getDefaultExportFromCjs$1(isIp_1);

    function _createForOfIteratorHelper$2(o, allowArrayLike) { var it = typeof Symbol !== "undefined" && o[Symbol.iterator] || o["@@iterator"]; if (!it) { if (Array.isArray(o) || (it = _unsupportedIterableToArray$2(o)) || allowArrayLike && o && typeof o.length === "number") { if (it) o = it; var i = 0; var F = function F() {}; return { s: F, n: function n() { if (i >= o.length) return { done: true }; return { done: false, value: o[i++] }; }, e: function e(_e) { throw _e; }, 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 normalCompletion = true, didErr = false, err; return { s: function s() { it = it.call(o); }, n: function n() { var step = it.next(); normalCompletion = step.done; return step; }, e: function e(_e2) { didErr = true; err = _e2; }, f: function f() { try { if (!normalCompletion && it.return != null) it.return(); } finally { if (didErr) throw err; } } }; }
    function _unsupportedIterableToArray$2(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray$2(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray$2(o, minLen); }
    function _arrayLikeToArray$2(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; return arr2; }
    /*!
     * XRegExp 5.1.1
     * <xregexp.com>
     * Steven Levithan (c) 2007-present MIT License
     */

    /**
     * XRegExp provides augmented, extensible regular expressions. You get additional regex syntax and
     * flags, beyond what browsers support natively. XRegExp is also a regex utility belt with tools to
     * make your client-side grepping simpler and more powerful, while freeing you from related
     * cross-browser inconsistencies.
     */

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

    // Property name used for extended regex instance data
    var REGEX_DATA = 'xregexp';
    // Optional features that can be installed and uninstalled
    var features = {
      astral: false,
      namespacing: true
    };
    // Storage for fixed/extended native methods
    var fixed = {};
    // Storage for regexes cached by `XRegExp.cache`
    var regexCache = {};
    // Storage for pattern details cached by the `XRegExp` constructor
    var patternCache = {};
    // Storage for regex syntax tokens added internally or by `XRegExp.addToken`
    var tokens = [];
    // Token scopes
    var defaultScope = 'default';
    var classScope = 'class';
    // Regexes that match native regex syntax, including octals
    var nativeTokens = {
      // Any native multicharacter token in default scope, or any single character
      'default': /\\(?:0(?:[0-3][0-7]{0,2}|[4-7][0-7]?)?|[1-9]\d*|x[\dA-Fa-f]{2}|u(?:[\dA-Fa-f]{4}|{[\dA-Fa-f]+})|c[A-Za-z]|[\s\S])|\(\?(?:[:=!]|<[=!])|[?*+]\?|{\d+(?:,\d*)?}\??|[\s\S]/,
      // Any native multicharacter token in character class scope, or any single character
      'class': /\\(?:[0-3][0-7]{0,2}|[4-7][0-7]?|x[\dA-Fa-f]{2}|u(?:[\dA-Fa-f]{4}|{[\dA-Fa-f]+})|c[A-Za-z]|[\s\S])|[\s\S]/
    };
    // Any backreference or dollar-prefixed character in replacement strings
    var replacementToken = /\$(?:\{([^\}]+)\}|<([^>]+)>|(\d\d?|[\s\S]?))/g;
    // Check for correct `exec` handling of nonparticipating capturing groups
    var correctExecNpcg = /()??/.exec('')[1] === undefined;
    // Check for ES6 `flags` prop support
    var hasFlagsProp = /x/.flags !== undefined;
    function hasNativeFlag(flag) {
      // Can't check based on the presence of properties/getters since browsers might support such
      // properties even when they don't support the corresponding flag in regex construction (tested
      // in Chrome 48, where `'unicode' in /x/` is true but trying to construct a regex with flag `u`
      // throws an error)
      var isSupported = true;
      try {
        // Can't use regex literals for testing even in a `try` because regex literals with
        // unsupported flags cause a compilation error in IE
        new RegExp('', flag);

        // Work around a broken/incomplete IE11 polyfill for sticky introduced in core-js 3.6.0
        if (flag === 'y') {
          // Using function to avoid babel transform to regex literal
          var gy = function () {
            return 'gy';
          }();
          var incompleteY = '.a'.replace(new RegExp('a', gy), '.') === '..';
          if (incompleteY) {
            isSupported = false;
          }
        }
      } catch (exception) {
        isSupported = false;
      }
      return isSupported;
    }
    // Check for ES2021 `d` flag support
    var hasNativeD = hasNativeFlag('d');
    // Check for ES2018 `s` flag support
    var hasNativeS = hasNativeFlag('s');
    // Check for ES6 `u` flag support
    var hasNativeU = hasNativeFlag('u');
    // Check for ES6 `y` flag support
    var hasNativeY = hasNativeFlag('y');
    // Tracker for known flags, including addon flags
    var registeredFlags = {
      d: hasNativeD,
      g: true,
      i: true,
      m: true,
      s: hasNativeS,
      u: hasNativeU,
      y: hasNativeY
    };
    // Flags to remove when passing to native `RegExp` constructor
    var nonnativeFlags = hasNativeS ? /[^dgimsuy]+/g : /[^dgimuy]+/g;

    /**
     * Attaches extended data and `XRegExp.prototype` properties to a regex object.
     *
     * @private
     * @param {RegExp} regex Regex to augment.
     * @param {Array} captureNames Array with capture names, or `null`.
     * @param {String} xSource XRegExp pattern used to generate `regex`, or `null` if N/A.
     * @param {String} xFlags XRegExp flags used to generate `regex`, or `null` if N/A.
     * @param {Boolean} [isInternalOnly=false] Whether the regex will be used only for internal
     *   operations, and never exposed to users. For internal-only regexes, we can improve perf by
     *   skipping some operations like attaching `XRegExp.prototype` properties.
     * @returns {!RegExp} Augmented regex.
     */
    function augment(regex, captureNames, xSource, xFlags, isInternalOnly) {
      regex[REGEX_DATA] = {
        captureNames
      };
      if (isInternalOnly) {
        return regex;
      }

      // Can't auto-inherit these since the XRegExp constructor returns a nonprimitive value
      if (regex.__proto__) {
        regex.__proto__ = XRegExp.prototype;
      } else {
        for (var p in XRegExp.prototype) {
          // An `XRegExp.prototype.hasOwnProperty(p)` check wouldn't be worth it here, since this
          // is performance sensitive, and enumerable `Object.prototype` or `RegExp.prototype`
          // extensions exist on `regex.prototype` anyway
          regex[p] = XRegExp.prototype[p];
        }
      }
      regex[REGEX_DATA].source = xSource;
      // Emulate the ES6 `flags` prop by ensuring flags are in alphabetical order
      regex[REGEX_DATA].flags = xFlags ? xFlags.split('').sort().join('') : xFlags;
      return regex;
    }

    /**
     * Removes any duplicate characters from the provided string.
     *
     * @private
     * @param {String} str String to remove duplicate characters from.
     * @returns {string} String with any duplicate characters removed.
     */
    function clipDuplicates(str) {
      return str.replace(/([\s\S])(?=[\s\S]*\1)/g, '');
    }

    /**
     * Copies a regex object while preserving extended data and augmenting with `XRegExp.prototype`
     * properties. The copy has a fresh `lastIndex` property (set to zero). Allows adding and removing
     * flags g and y while copying the regex.
     *
     * @private
     * @param {RegExp} regex Regex to copy.
     * @param {Object} [options] Options object with optional properties:
     *   - `addG` {Boolean} Add flag g while copying the regex.
     *   - `addY` {Boolean} Add flag y while copying the regex.
     *   - `removeG` {Boolean} Remove flag g while copying the regex.
     *   - `removeY` {Boolean} Remove flag y while copying the regex.
     *   - `isInternalOnly` {Boolean} Whether the copied regex will be used only for internal
     *     operations, and never exposed to users. For internal-only regexes, we can improve perf by
     *     skipping some operations like attaching `XRegExp.prototype` properties.
     *   - `source` {String} Overrides `<regex>.source`, for special cases.
     * @returns {RegExp} Copy of the provided regex, possibly with modified flags.
     */
    function copyRegex(regex, options) {
      if (!XRegExp.isRegExp(regex)) {
        throw new TypeError('Type RegExp expected');
      }
      var xData = regex[REGEX_DATA] || {};
      var flags = getNativeFlags(regex);
      var flagsToAdd = '';
      var flagsToRemove = '';
      var xregexpSource = null;
      var xregexpFlags = null;
      options = options || {};
      if (options.removeG) {
        flagsToRemove += 'g';
      }
      if (options.removeY) {
        flagsToRemove += 'y';
      }
      if (flagsToRemove) {
        flags = flags.replace(new RegExp("[".concat(flagsToRemove, "]+"), 'g'), '');
      }
      if (options.addG) {
        flagsToAdd += 'g';
      }
      if (options.addY) {
        flagsToAdd += 'y';
      }
      if (flagsToAdd) {
        flags = clipDuplicates(flags + flagsToAdd);
      }
      if (!options.isInternalOnly) {
        if (xData.source !== undefined) {
          xregexpSource = xData.source;
        }
        // null or undefined; don't want to add to `flags` if the previous value was null, since
        // that indicates we're not tracking original precompilation flags
        if (xData.flags != null) {
          // Flags are only added for non-internal regexes by `XRegExp.globalize`. Flags are never
          // removed for non-internal regexes, so don't need to handle it
          xregexpFlags = flagsToAdd ? clipDuplicates(xData.flags + flagsToAdd) : xData.flags;
        }
      }

      // Augment with `XRegExp.prototype` properties, but use the native `RegExp` constructor to avoid
      // searching for special tokens. That would be wrong for regexes constructed by `RegExp`, and
      // unnecessary for regexes constructed by `XRegExp` because the regex has already undergone the
      // translation to native regex syntax
      regex = augment(new RegExp(options.source || regex.source, flags), hasNamedCapture(regex) ? xData.captureNames.slice(0) : null, xregexpSource, xregexpFlags, options.isInternalOnly);
      return regex;
    }

    /**
     * Converts hexadecimal to decimal.
     *
     * @private
     * @param {String} hex
     * @returns {number}
     */
    function dec(hex) {
      return parseInt(hex, 16);
    }

    /**
     * Returns a pattern that can be used in a native RegExp in place of an ignorable token such as an
     * inline comment or whitespace with flag x. This is used directly as a token handler function
     * passed to `XRegExp.addToken`.
     *
     * @private
     * @param {String} match Match arg of `XRegExp.addToken` handler
     * @param {String} scope Scope arg of `XRegExp.addToken` handler
     * @param {String} flags Flags arg of `XRegExp.addToken` handler
     * @returns {string} Either '' or '(?:)', depending on which is needed in the context of the match.
     */
    function getContextualTokenSeparator(match, scope, flags) {
      var matchEndPos = match.index + match[0].length;
      var precedingChar = match.input[match.index - 1];
      var followingChar = match.input[matchEndPos];
      if (
      // No need to separate tokens if at the beginning or end of a group, before or after a
      // group, or before or after a `|`
      /^[()|]$/.test(precedingChar) || /^[()|]$/.test(followingChar) ||
      // No need to separate tokens if at the beginning or end of the pattern
      match.index === 0 || matchEndPos === match.input.length ||
      // No need to separate tokens if at the beginning of a noncapturing group or lookaround.
      // Looks only at the last 4 chars (at most) for perf when constructing long regexes.
      /\(\?(?:[:=!]|<[=!])$/.test(match.input.substring(match.index - 4, match.index)) ||
      // Avoid separating tokens when the following token is a quantifier
      isQuantifierNext(match.input, matchEndPos, flags)) {
        return '';
      }
      // Keep tokens separated. This avoids e.g. inadvertedly changing `\1 1` or `\1(?#)1` to `\11`.
      // This also ensures all tokens remain as discrete atoms, e.g. it prevents converting the
      // syntax error `(? :` into `(?:`.
      return '(?:)';
    }

    /**
     * Returns native `RegExp` flags used by a regex object.
     *
     * @private
     * @param {RegExp} regex Regex to check.
     * @returns {string} Native flags in use.
     */
    function getNativeFlags(regex) {
      return hasFlagsProp ? regex.flags :
      // Explicitly using `RegExp.prototype.toString` (rather than e.g. `String` or concatenation
      // with an empty string) allows this to continue working predictably when
      // `XRegExp.proptotype.toString` is overridden
      /\/([a-z]*)$/i.exec(RegExp.prototype.toString.call(regex))[1];
    }

    /**
     * Determines whether a regex has extended instance data used to track capture names.
     *
     * @private
     * @param {RegExp} regex Regex to check.
     * @returns {boolean} Whether the regex uses named capture.
     */
    function hasNamedCapture(regex) {
      return !!(regex[REGEX_DATA] && regex[REGEX_DATA].captureNames);
    }

    /**
     * Converts decimal to hexadecimal.
     *
     * @private
     * @param {Number|String} dec
     * @returns {string}
     */
    function hex(dec) {
      return parseInt(dec, 10).toString(16);
    }

    /**
     * Checks whether the next nonignorable token after the specified position is a quantifier.
     *
     * @private
     * @param {String} pattern Pattern to search within.
     * @param {Number} pos Index in `pattern` to search at.
     * @param {String} flags Flags used by the pattern.
     * @returns {Boolean} Whether the next nonignorable token is a quantifier.
     */
    function isQuantifierNext(pattern, pos, flags) {
      var inlineCommentPattern = '\\(\\?#[^)]*\\)';
      var lineCommentPattern = '#[^#\\n]*';
      var quantifierPattern = '[?*+]|{\\d+(?:,\\d*)?}';
      var regex = flags.includes('x') ?
      // Ignore any leading whitespace, line comments, and inline comments
      new RegExp("^(?:\\s|".concat(lineCommentPattern, "|").concat(inlineCommentPattern, ")*(?:").concat(quantifierPattern, ")")) :
      // Ignore any leading inline comments
      new RegExp("^(?:".concat(inlineCommentPattern, ")*(?:").concat(quantifierPattern, ")"));
      return regex.test(pattern.slice(pos));
    }

    /**
     * Determines whether a value is of the specified type, by resolving its internal [[Class]].
     *
     * @private
     * @param {*} value Object to check.
     * @param {String} type Type to check for, in TitleCase.
     * @returns {boolean} Whether the object matches the type.
     */
    function isType(value, type) {
      return Object.prototype.toString.call(value) === "[object ".concat(type, "]");
    }

    /**
     * Returns the object, or throws an error if it is `null` or `undefined`. This is used to follow
     * the ES5 abstract operation `ToObject`.
     *
     * @private
     * @param {*} value Object to check and return.
     * @returns {*} The provided object.
     */
    function nullThrows(value) {
      // null or undefined
      if (value == null) {
        throw new TypeError('Cannot convert null or undefined to object');
      }
      return value;
    }

    /**
     * Adds leading zeros if shorter than four characters. Used for fixed-length hexadecimal values.
     *
     * @private
     * @param {String} str
     * @returns {string}
     */
    function pad4(str) {
      while (str.length < 4) {
        str = "0".concat(str);
      }
      return str;
    }

    /**
     * Checks for flag-related errors, and strips/applies flags in a leading mode modifier. Offloads
     * the flag preparation logic from the `XRegExp` constructor.
     *
     * @private
     * @param {String} pattern Regex pattern, possibly with a leading mode modifier.
     * @param {String} flags Any combination of flags.
     * @returns {!Object} Object with properties `pattern` and `flags`.
     */
    function prepareFlags(pattern, flags) {
      // Recent browsers throw on duplicate flags, so copy this behavior for nonnative flags
      if (clipDuplicates(flags) !== flags) {
        throw new SyntaxError("Invalid duplicate regex flag ".concat(flags));
      }

      // Strip and apply a leading mode modifier with any combination of flags except `dgy`
      pattern = pattern.replace(/^\(\?([\w$]+)\)/, function ($0, $1) {
        if (/[dgy]/.test($1)) {
          throw new SyntaxError("Cannot use flags dgy in mode modifier ".concat($0));
        }
        // Allow duplicate flags within the mode modifier
        flags = clipDuplicates(flags + $1);
        return '';
      });

      // Throw on unknown native or nonnative flags
      var _iterator = _createForOfIteratorHelper$2(flags),
        _step;
      try {
        for (_iterator.s(); !(_step = _iterator.n()).done;) {
          var flag = _step.value;
          if (!registeredFlags[flag]) {
            throw new SyntaxError("Unknown regex flag ".concat(flag));
          }
        }
      } catch (err) {
        _iterator.e(err);
      } finally {
        _iterator.f();
      }
      return {
        pattern,
        flags
      };
    }

    /**
     * Prepares an options object from the given value.
     *
     * @private
     * @param {String|Object} value Value to convert to an options object.
     * @returns {Object} Options object.
     */
    function prepareOptions(value) {
      var options = {};
      if (isType(value, 'String')) {
        XRegExp.forEach(value, /[^\s,]+/, function (match) {
          options[match] = true;
        });
        return options;
      }
      return value;
    }

    /**
     * Registers a flag so it doesn't throw an 'unknown flag' error.
     *
     * @private
     * @param {String} flag Single-character flag to register.
     */
    function registerFlag(flag) {
      if (!/^[\w$]$/.test(flag)) {
        throw new Error('Flag must be a single character A-Za-z0-9_$');
      }
      registeredFlags[flag] = true;
    }

    /**
     * Runs built-in and custom regex syntax tokens in reverse insertion order at the specified
     * position, until a match is found.
     *
     * @private
     * @param {String} pattern Original pattern from which an XRegExp object is being built.
     * @param {String} flags Flags being used to construct the regex.
     * @param {Number} pos Position to search for tokens within `pattern`.
     * @param {Number} scope Regex scope to apply: 'default' or 'class'.
     * @param {Object} context Context object to use for token handler functions.
     * @returns {Object} Object with properties `matchLength`, `output`, and `reparse`; or `null`.
     */
    function runTokens(pattern, flags, pos, scope, context) {
      var i = tokens.length;
      var leadChar = pattern[pos];
      var result = null;
      var match;
      var t;

      // Run in reverse insertion order
      while (i--) {
        t = tokens[i];
        if (t.leadChar && t.leadChar !== leadChar || t.scope !== scope && t.scope !== 'all' || t.flag && !flags.includes(t.flag)) {
          continue;
        }
        match = XRegExp.exec(pattern, t.regex, pos, 'sticky');
        if (match) {
          result = {
            matchLength: match[0].length,
            output: t.handler.call(context, match, scope, flags),
            reparse: t.reparse
          };
          // Finished with token tests
          break;
        }
      }
      return result;
    }

    /**
     * Enables or disables implicit astral mode opt-in. When enabled, flag A is automatically added to
     * all new regexes created by XRegExp. This causes an error to be thrown when creating regexes if
     * the Unicode Base addon is not available, since flag A is registered by that addon.
     *
     * @private
     * @param {Boolean} on `true` to enable; `false` to disable.
     */
    function setAstral(on) {
      features.astral = on;
    }

    /**
     * Adds named capture groups to the `groups` property of match arrays. See here for details:
     * https://github.com/tc39/proposal-regexp-named-groups
     *
     * @private
     * @param {Boolean} on `true` to enable; `false` to disable.
     */
    function setNamespacing(on) {
      features.namespacing = on;
    }

    // ==--------------------------==
    // Constructor
    // ==--------------------------==

    /**
     * Creates an extended regular expression object for matching text with a pattern. Differs from a
     * native regular expression in that additional syntax and flags are supported. The returned object
     * is in fact a native `RegExp` and works with all native methods.
     *
     * @class XRegExp
     * @constructor
     * @param {String|RegExp} pattern Regex pattern string, or an existing regex object to copy.
     * @param {String} [flags] Any combination of flags.
     *   Native flags:
     *     - `d` - indices for capturing groups (ES2021)
     *     - `g` - global
     *     - `i` - ignore case
     *     - `m` - multiline anchors
     *     - `u` - unicode (ES6)
     *     - `y` - sticky (Firefox 3+, ES6)
     *   Additional XRegExp flags:
     *     - `n` - named capture only
     *     - `s` - dot matches all (aka singleline) - works even when not natively supported
     *     - `x` - free-spacing and line comments (aka extended)
     *     - `A` - 21-bit Unicode properties (aka astral) - requires the Unicode Base addon
     *   Flags cannot be provided when constructing one `RegExp` from another.
     * @returns {RegExp} Extended regular expression object.
     * @example
     *
     * // With named capture and flag x
     * XRegExp(`(?<year>  [0-9]{4} ) -?  # year
     *          (?<month> [0-9]{2} ) -?  # month
     *          (?<day>   [0-9]{2} )     # day`, 'x');
     *
     * // Providing a regex object copies it. Native regexes are recompiled using native (not XRegExp)
     * // syntax. Copies maintain extended data, are augmented with `XRegExp.prototype` properties, and
     * // have fresh `lastIndex` properties (set to zero).
     * XRegExp(/regex/);
     */
    function XRegExp(pattern, flags) {
      if (XRegExp.isRegExp(pattern)) {
        if (flags !== undefined) {
          throw new TypeError('Cannot supply flags when copying a RegExp');
        }
        return copyRegex(pattern);
      }

      // Copy the argument behavior of `RegExp`
      pattern = pattern === undefined ? '' : String(pattern);
      flags = flags === undefined ? '' : String(flags);
      if (XRegExp.isInstalled('astral') && !flags.includes('A')) {
        // This causes an error to be thrown if the Unicode Base addon is not available
        flags += 'A';
      }
      if (!patternCache[pattern]) {
        patternCache[pattern] = {};
      }
      if (!patternCache[pattern][flags]) {
        var context = {
          hasNamedCapture: false,
          captureNames: []
        };
        var scope = defaultScope;
        var output = '';
        var pos = 0;
        var result;

        // Check for flag-related errors, and strip/apply flags in a leading mode modifier
        var applied = prepareFlags(pattern, flags);
        var appliedPattern = applied.pattern;
        var appliedFlags = applied.flags;

        // Use XRegExp's tokens to translate the pattern to a native regex pattern.
        // `appliedPattern.length` may change on each iteration if tokens use `reparse`
        while (pos < appliedPattern.length) {
          do {
            // Check for custom tokens at the current position
            result = runTokens(appliedPattern, appliedFlags, pos, scope, context);
            // If the matched token used the `reparse` option, splice its output into the
            // pattern before running tokens again at the same position
            if (result && result.reparse) {
              appliedPattern = appliedPattern.slice(0, pos) + result.output + appliedPattern.slice(pos + result.matchLength);
            }
          } while (result && result.reparse);
          if (result) {
            output += result.output;
            pos += result.matchLength || 1;
          } else {
            // Get the native token at the current position
            var _XRegExp$exec = XRegExp.exec(appliedPattern, nativeTokens[scope], pos, 'sticky'),
              _XRegExp$exec2 = _slicedToArray$1(_XRegExp$exec, 1),
              token = _XRegExp$exec2[0];
            output += token;
            pos += token.length;
            if (token === '[' && scope === defaultScope) {
              scope = classScope;
            } else if (token === ']' && scope === classScope) {
              scope = defaultScope;
            }
          }
        }
        patternCache[pattern][flags] = {
          // Use basic cleanup to collapse repeated empty groups like `(?:)(?:)` to `(?:)`. Empty
          // groups are sometimes inserted during regex transpilation in order to keep tokens
          // separated. However, more than one empty group in a row is never needed.
          pattern: output.replace(/(?:\(\?:\))+/g, '(?:)'),
          // Strip all but native flags
          flags: appliedFlags.replace(nonnativeFlags, ''),
          // `context.captureNames` has an item for each capturing group, even if unnamed
          captures: context.hasNamedCapture ? context.captureNames : null
        };
      }
      var generated = patternCache[pattern][flags];
      return augment(new RegExp(generated.pattern, generated.flags), generated.captures, pattern, flags);
    }

    // Add `RegExp.prototype` to the prototype chain
    XRegExp.prototype = new RegExp();

    // ==--------------------------==
    // Public properties
    // ==--------------------------==

    /**
     * The XRegExp version number as a string containing three dot-separated parts. For example,
     * '2.0.0-beta-3'.
     *
     * @static
     * @memberOf XRegExp
     * @type String
     */
    XRegExp.version = '5.1.1';

    // ==--------------------------==
    // Public methods
    // ==--------------------------==

    // Intentionally undocumented; used in tests and addons
    XRegExp._clipDuplicates = clipDuplicates;
    XRegExp._hasNativeFlag = hasNativeFlag;
    XRegExp._dec = dec;
    XRegExp._hex = hex;
    XRegExp._pad4 = pad4;

    /**
     * Extends XRegExp syntax and allows custom flags. This is used internally and can be used to
     * create XRegExp addons. If more than one token can match the same string, the last added wins.
     *
     * @memberOf XRegExp
     * @param {RegExp} regex Regex object that matches the new token.
     * @param {Function} handler Function that returns a new pattern string (using native regex syntax)
     *   to replace the matched token within all future XRegExp regexes. Has access to persistent
     *   properties of the regex being built, through `this`. Invoked with three arguments:
     *   - The match array, with named backreference properties.
     *   - The regex scope where the match was found: 'default' or 'class'.
     *   - The flags used by the regex, including any flags in a leading mode modifier.
     *   The handler function becomes part of the XRegExp construction process, so be careful not to
     *   construct XRegExps within the function or you will trigger infinite recursion.
     * @param {Object} [options] Options object with optional properties:
     *   - `scope` {String} Scope where the token applies: 'default', 'class', or 'all'.
     *   - `flag` {String} Single-character flag that triggers the token. This also registers the
     *     flag, which prevents XRegExp from throwing an 'unknown flag' error when the flag is used.
     *   - `optionalFlags` {String} Any custom flags checked for within the token `handler` that are
     *     not required to trigger the token. This registers the flags, to prevent XRegExp from
     *     throwing an 'unknown flag' error when any of the flags are used.
     *   - `reparse` {Boolean} Whether the `handler` function's output should not be treated as
     *     final, and instead be reparseable by other tokens (including the current token). Allows
     *     token chaining or deferring.
     *   - `leadChar` {String} Single character that occurs at the beginning of any successful match
     *     of the token (not always applicable). This doesn't change the behavior of the token unless
     *     you provide an erroneous value. However, providing it can increase the token's performance
     *     since the token can be skipped at any positions where this character doesn't appear.
     * @example
     *
     * // Basic usage: Add \a for the ALERT control code
     * XRegExp.addToken(
     *   /\\a/,
     *   () => '\\x07',
     *   {scope: 'all'}
     * );
     * XRegExp('\\a[\\a-\\n]+').test('\x07\n\x07'); // -> true
     *
     * // Add the U (ungreedy) flag from PCRE and RE2, which reverses greedy and lazy quantifiers.
     * // Since `scope` is not specified, it uses 'default' (i.e., transformations apply outside of
     * // character classes only)
     * XRegExp.addToken(
     *   /([?*+]|{\d+(?:,\d*)?})(\??)/,
     *   (match) => `${match[1]}${match[2] ? '' : '?'}`,
     *   {flag: 'U'}
     * );
     * XRegExp('a+', 'U').exec('aaa')[0]; // -> 'a'
     * XRegExp('a+?', 'U').exec('aaa')[0]; // -> 'aaa'
     */
    XRegExp.addToken = function (regex, handler, options) {
      options = options || {};
      var _options = options,
        optionalFlags = _options.optionalFlags;
      if (options.flag) {
        registerFlag(options.flag);
      }
      if (optionalFlags) {
        optionalFlags = optionalFlags.split('');
        var _iterator2 = _createForOfIteratorHelper$2(optionalFlags),
          _step2;
        try {
          for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
            var flag = _step2.value;
            registerFlag(flag);
          }
        } catch (err) {
          _iterator2.e(err);
        } finally {
          _iterator2.f();
        }
      }

      // Add to the private list of syntax tokens
      tokens.push({
        regex: copyRegex(regex, {
          addG: true,
          addY: hasNativeY,
          isInternalOnly: true
        }),
        handler,
        scope: options.scope || defaultScope,
        flag: options.flag,
        reparse: options.reparse,
        leadChar: options.leadChar
      });

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

    /**
     * Caches and returns the result of calling `XRegExp(pattern, flags)`. On any subsequent call with
     * the same pattern and flag combination, the cached copy of the regex is returned.
     *
     * @memberOf XRegExp
     * @param {String} pattern Regex pattern string.
     * @param {String} [flags] Any combination of XRegExp flags.
     * @returns {RegExp} Cached XRegExp object.
     * @example
     *
     * let match;
     * while (match = XRegExp.cache('.', 'gs').exec('abc')) {
     *   // The regex is compiled once only
     * }
     */
    XRegExp.cache = function (pattern, flags) {
      if (!regexCache[pattern]) {
        regexCache[pattern] = {};
      }
      return regexCache[pattern][flags] || (regexCache[pattern][flags] = XRegExp(pattern, flags));
    };

    // Intentionally undocumented; used in tests
    XRegExp.cache.flush = function (cacheName) {
      if (cacheName === 'patterns') {
        // Flush the pattern cache used by the `XRegExp` constructor
        patternCache = {};
      } else {
        // Flush the regex cache populated by `XRegExp.cache`
        regexCache = {};
      }
    };

    /**
     * Escapes any regular expression metacharacters, for use when matching literal strings. The result
     * can safely be used at any position within a regex that uses any flags.
     *
     * @memberOf XRegExp
     * @param {String} str String to escape.
     * @returns {string} String with regex metacharacters escaped.
     * @example
     *
     * XRegExp.escape('Escaped? <.>');
     * // -> 'Escaped\?\u0020<\.>'
     */
    // Following are the contexts where each metacharacter needs to be escaped because it would
    // otherwise have a special meaning, change the meaning of surrounding characters, or cause an
    // error. Context 'default' means outside character classes only.
    // - `\` - context: all
    // - `[()*+?.$|` - context: default
    // - `]` - context: default with flag u or if forming the end of a character class
    // - `{}` - context: default with flag u or if part of a valid/complete quantifier pattern
    // - `,` - context: default if in a position that causes an unescaped `{` to turn into a quantifier.
    //   Ex: `/^a{1\,2}$/` matches `'a{1,2}'`, but `/^a{1,2}$/` matches `'a'` or `'aa'`
    // - `#` and <whitespace> - context: default with flag x
    // - `^` - context: default, and context: class if it's the first character in the class
    // - `-` - context: class if part of a valid character class range
    XRegExp.escape = function (str) {
      return String(nullThrows(str)).
      // Escape most special chars with a backslash
      replace(/[\\\[\]{}()*+?.^$|]/g, '\\$&').
      // Convert to \uNNNN for special chars that can't be escaped when used with ES6 flag `u`
      replace(/[\s#\-,]/g, function (match) {
        return "\\u".concat(pad4(hex(match.charCodeAt(0))));
      });
    };

    /**
     * Executes a regex search in a specified string. Returns a match array or `null`. If the provided
     * regex uses named capture, named capture properties are included on the match array's `groups`
     * property. Optional `pos` and `sticky` arguments specify the search start position, and whether
     * the match must start at the specified position only. The `lastIndex` property of the provided
     * regex is not used, but is updated for compatibility. Also fixes browser bugs compared to the
     * native `RegExp.prototype.exec` and can be used reliably cross-browser.
     *
     * @memberOf XRegExp
     * @param {String} str String to search.
     * @param {RegExp} regex Regex to search with.
     * @param {Number} [pos=0] Zero-based index at which to start the search.
     * @param {Boolean|String} [sticky=false] Whether the match must start at the specified position
     *   only. The string `'sticky'` is accepted as an alternative to `true`.
     * @returns {Array} Match array with named capture properties on the `groups` object, or `null`. If
     *   the `namespacing` feature is off, named capture properties are directly on the match array.
     * @example
     *
     * // Basic use, with named capturing group
     * let match = XRegExp.exec('U+2620', XRegExp('U\\+(?<hex>[0-9A-F]{4})'));
     * match.groups.hex; // -> '2620'
     *
     * // With pos and sticky, in a loop
     * let pos = 3, result = [], match;
     * while (match = XRegExp.exec('<1><2><3><4>5<6>', /<(\d)>/, pos, 'sticky')) {
     *   result.push(match[1]);
     *   pos = match.index + match[0].length;
     * }
     * // result -> ['2', '3', '4']
     */
    XRegExp.exec = function (str, regex, pos, sticky) {
      var cacheKey = 'g';
      var addY = false;
      var fakeY = false;
      var match;
      addY = hasNativeY && !!(sticky || regex.sticky && sticky !== false);
      if (addY) {
        cacheKey += 'y';
      } else if (sticky) {
        // Simulate sticky matching by appending an empty capture to the original regex. The
        // resulting regex will succeed no matter what at the current index (set with `lastIndex`),
        // and will not search the rest of the subject string. We'll know that the original regex
        // has failed if that last capture is `''` rather than `undefined` (i.e., if that last
        // capture participated in the match).
        fakeY = true;
        cacheKey += 'FakeY';
      }
      regex[REGEX_DATA] = regex[REGEX_DATA] || {};

      // Shares cached copies with `XRegExp.match`/`replace`
      var r2 = regex[REGEX_DATA][cacheKey] || (regex[REGEX_DATA][cacheKey] = copyRegex(regex, {
        addG: true,
        addY,
        source: fakeY ? "".concat(regex.source, "|()") : undefined,
        removeY: sticky === false,
        isInternalOnly: true
      }));
      pos = pos || 0;
      r2.lastIndex = pos;

      // Fixed `exec` required for `lastIndex` fix, named backreferences, etc.
      match = fixed.exec.call(r2, str);

      // Get rid of the capture added by the pseudo-sticky matcher if needed. An empty string means
      // the original regexp failed (see above).
      if (fakeY && match && match.pop() === '') {
        match = null;
      }
      if (regex.global) {
        regex.lastIndex = match ? r2.lastIndex : 0;
      }
      return match;
    };

    /**
     * Executes a provided function once per regex match. Searches always start at the beginning of the
     * string and continue until the end, regardless of the state of the regex's `global` property and
     * initial `lastIndex`.
     *
     * @memberOf XRegExp
     * @param {String} str String to search.
     * @param {RegExp} regex Regex to search with.
     * @param {Function} callback Function to execute for each match. Invoked with four arguments:
     *   - The match array, with named backreference properties.
     *   - The zero-based match index.
     *   - The string being traversed.
     *   - The regex object being used to traverse the string.
     * @example
     *
     * // Extracts every other digit from a string
     * const evens = [];
     * XRegExp.forEach('1a2345', /\d/, (match, i) => {
     *   if (i % 2) evens.push(+match[0]);
     * });
     * // evens -> [2, 4]
     */
    XRegExp.forEach = function (str, regex, callback) {
      var pos = 0;
      var i = -1;
      var match;
      while (match = XRegExp.exec(str, regex, pos)) {
        // Because `regex` is provided to `callback`, the function could use the deprecated/
        // nonstandard `RegExp.prototype.compile` to mutate the regex. However, since `XRegExp.exec`
        // doesn't use `lastIndex` to set the search position, this can't lead to an infinite loop,
        // at least. Actually, because of the way `XRegExp.exec` caches globalized versions of
        // regexes, mutating the regex will not have any effect on the iteration or matched strings,
        // which is a nice side effect that brings extra safety.
        callback(match, ++i, str, regex);
        pos = match.index + (match[0].length || 1);
      }
    };

    /**
     * Copies a regex object and adds flag `g`. The copy maintains extended data, is augmented with
     * `XRegExp.prototype` properties, and has a fresh `lastIndex` property (set to zero). Native
     * regexes are not recompiled using XRegExp syntax.
     *
     * @memberOf XRegExp
     * @param {RegExp} regex Regex to globalize.
     * @returns {RegExp} Copy of the provided regex with flag `g` added.
     * @example
     *
     * const globalCopy = XRegExp.globalize(/regex/);
     * globalCopy.global; // -> true
     */
    XRegExp.globalize = function (regex) {
      return copyRegex(regex, {
        addG: true
      });
    };

    /**
     * Installs optional features according to the specified options. Can be undone using
     * `XRegExp.uninstall`.
     *
     * @memberOf XRegExp
     * @param {Object|String} options Options object or string.
     * @example
     *
     * // With an options object
     * XRegExp.install({
     *   // Enables support for astral code points in Unicode addons (implicitly sets flag A)
     *   astral: true,
     *
     *   // Adds named capture groups to the `groups` property of matches
     *   namespacing: true
     * });
     *
     * // With an options string
     * XRegExp.install('astral namespacing');
     */
    XRegExp.install = function (options) {
      options = prepareOptions(options);
      if (!features.astral && options.astral) {
        setAstral(true);
      }
      if (!features.namespacing && options.namespacing) {
        setNamespacing(true);
      }
    };

    /**
     * Checks whether an individual optional feature is installed.
     *
     * @memberOf XRegExp
     * @param {String} feature Name of the feature to check. One of:
     *   - `astral`
     *   - `namespacing`
     * @returns {boolean} Whether the feature is installed.
     * @example
     *
     * XRegExp.isInstalled('astral');
     */
    XRegExp.isInstalled = function (feature) {
      return !!features[feature];
    };

    /**
     * Returns `true` if an object is a regex; `false` if it isn't. This works correctly for regexes
     * created in another frame, when `instanceof` and `constructor` checks would fail.
     *
     * @memberOf XRegExp
     * @param {*} value Object to check.
     * @returns {boolean} Whether the object is a `RegExp` object.
     * @example
     *
     * XRegExp.isRegExp('string'); // -> false
     * XRegExp.isRegExp(/regex/i); // -> true
     * XRegExp.isRegExp(RegExp('^', 'm')); // -> true
     * XRegExp.isRegExp(XRegExp('(?s).')); // -> true
     */
    XRegExp.isRegExp = function (value) {
      return Object.prototype.toString.call(value) === '[object RegExp]';
    };
    // Same as `isType(value, 'RegExp')`, but avoiding that function call here for perf since
    // `isRegExp` is used heavily by internals including regex construction

    /**
     * Returns the first matched string, or in global mode, an array containing all matched strings.
     * This is essentially a more convenient re-implementation of `String.prototype.match` that gives
     * the result types you actually want (string instead of `exec`-style array in match-first mode,
     * and an empty array instead of `null` when no matches are found in match-all mode). It also lets
     * you override flag g and ignore `lastIndex`, and fixes browser bugs.
     *
     * @memberOf XRegExp
     * @param {String} str String to search.
     * @param {RegExp} regex Regex to search with.
     * @param {String} [scope='one'] Use 'one' to return the first match as a string. Use 'all' to
     *   return an array of all matched strings. If not explicitly specified and `regex` uses flag g,
     *   `scope` is 'all'.
     * @returns {String|Array} In match-first mode: First match as a string, or `null`. In match-all
     *   mode: Array of all matched strings, or an empty array.
     * @example
     *
     * // Match first
     * XRegExp.match('abc', /\w/); // -> 'a'
     * XRegExp.match('abc', /\w/g, 'one'); // -> 'a'
     * XRegExp.match('abc', /x/g, 'one'); // -> null
     *
     * // Match all
     * XRegExp.match('abc', /\w/g); // -> ['a', 'b', 'c']
     * XRegExp.match('abc', /\w/, 'all'); // -> ['a', 'b', 'c']
     * XRegExp.match('abc', /x/, 'all'); // -> []
     */
    XRegExp.match = function (str, regex, scope) {
      var global = regex.global && scope !== 'one' || scope === 'all';
      var cacheKey = (global ? 'g' : '') + (regex.sticky ? 'y' : '') || 'noGY';
      regex[REGEX_DATA] = regex[REGEX_DATA] || {};

      // Shares cached copies with `XRegExp.exec`/`replace`
      var r2 = regex[REGEX_DATA][cacheKey] || (regex[REGEX_DATA][cacheKey] = copyRegex(regex, {
        addG: !!global,
        removeG: scope === 'one',
        isInternalOnly: true
      }));
      var result = String(nullThrows(str)).match(r2);
      if (regex.global) {
        regex.lastIndex = scope === 'one' && result ?
        // Can't use `r2.lastIndex` since `r2` is nonglobal in this case
        result.index + result[0].length : 0;
      }
      return global ? result || [] : result && result[0];
    };

    /**
     * Retrieves the matches from searching a string using a chain of regexes that successively search
     * within previous matches. The provided `chain` array can contain regexes and or objects with
     * `regex` and `backref` properties. When a backreference is specified, the named or numbered
     * backreference is passed forward to the next regex or returned.
     *
     * @memberOf XRegExp
     * @param {String} str String to search.
     * @param {Array} chain Regexes that each search for matches within preceding results.
     * @returns {Array} Matches by the last regex in the chain, or an empty array.
     * @example
     *
     * // Basic usage; matches numbers within <b> tags
     * XRegExp.matchChain('1 <b>2</b> 3 <b>4 a 56</b>', [
     *   XRegExp('(?is)<b>.*?</b>'),
     *   /\d+/
     * ]);
     * // -> ['2', '4', '56']
     *
     * // Passing forward and returning specific backreferences
     * const html = `<a href="http://xregexp.com/api/">XRegExp</a>
     *               <a href="http://www.google.com/">Google</a>`;
     * XRegExp.matchChain(html, [
     *   {regex: /<a href="([^"]+)">/i, backref: 1},
     *   {regex: XRegExp('(?i)^https?://(?<domain>[^/?#]+)'), backref: 'domain'}
     * ]);
     * // -> ['xregexp.com', 'www.google.com']
     */
    XRegExp.matchChain = function (str, chain) {
      return function recurseChain(values, level) {
        var item = chain[level].regex ? chain[level] : {
          regex: chain[level]
        };
        var matches = [];
        function addMatch(match) {
          if (item.backref) {
            var ERR_UNDEFINED_GROUP = "Backreference to undefined group: ".concat(item.backref);
            var isNamedBackref = isNaN(item.backref);
            if (isNamedBackref && XRegExp.isInstalled('namespacing')) {
              // `groups` has `null` as prototype, so using `in` instead of `hasOwnProperty`
              if (!(match.groups && item.backref in match.groups)) {
                throw new ReferenceError(ERR_UNDEFINED_GROUP);
              }
            } else if (!match.hasOwnProperty(item.backref)) {
              throw new ReferenceError(ERR_UNDEFINED_GROUP);
            }
            var backrefValue = isNamedBackref && XRegExp.isInstalled('namespacing') ? match.groups[item.backref] : match[item.backref];
            matches.push(backrefValue || '');
          } else {
            matches.push(match[0]);
          }
        }
        var _iterator3 = _createForOfIteratorHelper$2(values),
          _step3;
        try {
          for (_iterator3.s(); !(_step3 = _iterator3.n()).done;) {
            var value = _step3.value;
            XRegExp.forEach(value, item.regex, addMatch);
          }
        } catch (err) {
          _iterator3.e(err);
        } finally {
          _iterator3.f();
        }
        return level === chain.length - 1 || !matches.length ? matches : recurseChain(matches, level + 1);
      }([str], 0);
    };

    /**
     * Returns a new string with one or all matches of a pattern replaced. The pattern can be a string
     * or regex, and the replacement can be a string or a function to be called for each match. To
     * perform a global search and replace, use the optional `scope` argument or include flag g if using
     * a regex. Replacement strings can use `$<n>` or `${n}` for named and numbered backreferences.
     * Replacement functions can use named backreferences via the last argument. Also fixes browser bugs
     * compared to the native `String.prototype.replace` and can be used reliably cross-browser.
     *
     * @memberOf XRegExp
     * @param {String} str String to search.
     * @param {RegExp|String} search Search pattern to be replaced.
     * @param {String|Function} replacement Replacement string or a function invoked to create it.
     *   Replacement strings can include special replacement syntax:
     *     - $$ - Inserts a literal $ character.
     *     - $&, $0 - Inserts the matched substring.
     *     - $` - Inserts the string that precedes the matched substring (left context).
     *     - $' - Inserts the string that follows the matched substring (right context).
     *     - $n, $nn - Where n/nn are digits referencing an existing capturing group, inserts
     *       backreference n/nn.
     *     - $<n>, ${n} - Where n is a name or any number of digits that reference an existing capturing
     *       group, inserts backreference n.
     *   Replacement functions are invoked with three or more arguments:
     *     - args[0] - The matched substring (corresponds to `$&` above). If the `namespacing` feature
     *       is off, named backreferences are accessible as properties of this argument.
     *     - args[1..n] - One argument for each backreference (corresponding to `$1`, `$2`, etc. above).
     *       If the regex has no capturing groups, no arguments appear in this position.
     *     - args[n+1] - The zero-based index of the match within the entire search string.
     *     - args[n+2] - The total string being searched.
     *     - args[n+3] - If the the search pattern is a regex with named capturing groups, the last
     *       argument is the groups object. Its keys are the backreference names and its values are the
     *       backreference values. If the `namespacing` feature is off, this argument is not present.
     * @param {String} [scope] Use 'one' to replace the first match only, or 'all'. Defaults to 'one'.
     *   Defaults to 'all' if using a regex with flag g.
     * @returns {String} New string with one or all matches replaced.
     * @example
     *
     * // Regex search, using named backreferences in replacement string
     * const name = XRegExp('(?<first>\\w+) (?<last>\\w+)');
     * XRegExp.replace('John Smith', name, '$<last>, $<first>');
     * // -> 'Smith, John'
     *
     * // Regex search, using named backreferences in replacement function
     * XRegExp.replace('John Smith', name, (...args) => {
     *   const groups = args[args.length - 1];
     *   return `${groups.last}, ${groups.first}`;
     * });
     * // -> 'Smith, John'
     *
     * // String search, with replace-all
     * XRegExp.replace('RegExp builds RegExps', 'RegExp', 'XRegExp', 'all');
     * // -> 'XRegExp builds XRegExps'
     */
    XRegExp.replace = function (str, search, replacement, scope) {
      var isRegex = XRegExp.isRegExp(search);
      var global = search.global && scope !== 'one' || scope === 'all';
      var cacheKey = (global ? 'g' : '') + (search.sticky ? 'y' : '') || 'noGY';
      var s2 = search;
      if (isRegex) {
        search[REGEX_DATA] = search[REGEX_DATA] || {};

        // Shares cached copies with `XRegExp.exec`/`match`. Since a copy is used, `search`'s
        // `lastIndex` isn't updated *during* replacement iterations
        s2 = search[REGEX_DATA][cacheKey] || (search[REGEX_DATA][cacheKey] = copyRegex(search, {
          addG: !!global,
          removeG: scope === 'one',
          isInternalOnly: true
        }));
      } else if (global) {
        s2 = new RegExp(XRegExp.escape(String(search)), 'g');
      }

      // Fixed `replace` required for named backreferences, etc.
      var result = fixed.replace.call(nullThrows(str), s2, replacement);
      if (isRegex && search.global) {
        // Fixes IE, Safari bug (last tested IE 9, Safari 5.1)
        search.lastIndex = 0;
      }
      return result;
    };

    /**
     * Performs batch processing of string replacements. Used like `XRegExp.replace`, but accepts an
     * array of replacement details. Later replacements operate on the output of earlier replacements.
     * Replacement details are accepted as an array with a regex or string to search for, the
     * replacement string or function, and an optional scope of 'one' or 'all'. Uses the XRegExp
     * replacement text syntax, which supports named backreference properties via `$<name>` or
     * `${name}`.
     *
     * @memberOf XRegExp
     * @param {String} str String to search.
     * @param {Array} replacements Array of replacement detail arrays.
     * @returns {String} New string with all replacements.
     * @example
     *
     * str = XRegExp.replaceEach(str, [
     *   [XRegExp('(?<name>a)'), 'z$<name>'],
     *   [/b/gi, 'y'],
     *   [/c/g, 'x', 'one'], // scope 'one' overrides /g
     *   [/d/, 'w', 'all'],  // scope 'all' overrides lack of /g
     *   ['e', 'v', 'all'],  // scope 'all' allows replace-all for strings
     *   [/f/g, (match) => match.toUpperCase()]
     * ]);
     */
    XRegExp.replaceEach = function (str, replacements) {
      var _iterator4 = _createForOfIteratorHelper$2(replacements),
        _step4;
      try {
        for (_iterator4.s(); !(_step4 = _iterator4.n()).done;) {
          var r = _step4.value;
          str = XRegExp.replace(str, r[0], r[1], r[2]);
        }
      } catch (err) {
        _iterator4.e(err);
      } finally {
        _iterator4.f();
      }
      return str;
    };

    /**
     * Splits a string into an array of strings using a regex or string separator. Matches of the
     * separator are not included in the result array. However, if `separator` is a regex that contains
     * capturing groups, backreferences are spliced into the result each time `separator` is matched.
     * Fixes browser bugs compared to the native `String.prototype.split` and can be used reliably
     * cross-browser.
     *
     * @memberOf XRegExp
     * @param {String} str String to split.
     * @param {RegExp|String} separator Regex or string to use for separating the string.
     * @param {Number} [limit] Maximum number of items to include in the result array.
     * @returns {Array} Array of substrings.
     * @example
     *
     * // Basic use
     * XRegExp.split('a b c', ' ');
     * // -> ['a', 'b', 'c']
     *
     * // With limit
     * XRegExp.split('a b c', ' ', 2);
     * // -> ['a', 'b']
     *
     * // Backreferences in result array
     * XRegExp.split('..word1..', /([a-z]+)(\d+)/i);
     * // -> ['..', 'word', '1', '..']
     */
    XRegExp.split = function (str, separator, limit) {
      return fixed.split.call(nullThrows(str), separator, limit);
    };

    /**
     * Executes a regex search in a specified string. Returns `true` or `false`. Optional `pos` and
     * `sticky` arguments specify the search start position, and whether the match must start at the
     * specified position only. The `lastIndex` property of the provided regex is not used, but is
     * updated for compatibility. Also fixes browser bugs compared to the native
     * `RegExp.prototype.test` and can be used reliably cross-browser.
     *
     * @memberOf XRegExp
     * @param {String} str String to search.
     * @param {RegExp} regex Regex to search with.
     * @param {Number} [pos=0] Zero-based index at which to start the search.
     * @param {Boolean|String} [sticky=false] Whether the match must start at the specified position
     *   only. The string `'sticky'` is accepted as an alternative to `true`.
     * @returns {boolean} Whether the regex matched the provided value.
     * @example
     *
     * // Basic use
     * XRegExp.test('abc', /c/); // -> true
     *
     * // With pos and sticky
     * XRegExp.test('abc', /c/, 0, 'sticky'); // -> false
     * XRegExp.test('abc', /c/, 2, 'sticky'); // -> true
     */
    // Do this the easy way :-)
    XRegExp.test = function (str, regex, pos, sticky) {
      return !!XRegExp.exec(str, regex, pos, sticky);
    };

    /**
     * Uninstalls optional features according to the specified options. Used to undo the actions of
     * `XRegExp.install`.
     *
     * @memberOf XRegExp
     * @param {Object|String} options Options object or string.
     * @example
     *
     * // With an options object
     * XRegExp.uninstall({
     *   // Disables support for astral code points in Unicode addons (unless enabled per regex)
     *   astral: true,
     *
     *   // Don't add named capture groups to the `groups` property of matches
     *   namespacing: true
     * });
     *
     * // With an options string
     * XRegExp.uninstall('astral namespacing');
     */
    XRegExp.uninstall = function (options) {
      options = prepareOptions(options);
      if (features.astral && options.astral) {
        setAstral(false);
      }
      if (features.namespacing && options.namespacing) {
        setNamespacing(false);
      }
    };

    /**
     * Returns an XRegExp object that is the union of the given patterns. Patterns can be provided as
     * regex objects or strings. Metacharacters are escaped in patterns provided as strings.
     * Backreferences in provided regex objects are automatically renumbered to work correctly within
     * the larger combined pattern. Native flags used by provided regexes are ignored in favor of the
     * `flags` argument.
     *
     * @memberOf XRegExp
     * @param {Array} patterns Regexes and strings to combine.
     * @param {String} [flags] Any combination of XRegExp flags.
     * @param {Object} [options] Options object with optional properties:
     *   - `conjunction` {String} Type of conjunction to use: 'or' (default) or 'none'.
     * @returns {RegExp} Union of the provided regexes and strings.
     * @example
     *
     * XRegExp.union(['a+b*c', /(dogs)\1/, /(cats)\1/], 'i');
     * // -> /a\+b\*c|(dogs)\1|(cats)\2/i
     *
     * XRegExp.union([/man/, /bear/, /pig/], 'i', {conjunction: 'none'});
     * // -> /manbearpig/i
     */
    XRegExp.union = function (patterns, flags, options) {
      options = options || {};
      var conjunction = options.conjunction || 'or';
      var numCaptures = 0;
      var numPriorCaptures;
      var captureNames;
      function rewrite(match, paren, backref) {
        var name = captureNames[numCaptures - numPriorCaptures];

        // Capturing group
        if (paren) {
          ++numCaptures;
          // If the current capture has a name, preserve the name
          if (name) {
            return "(?<".concat(name, ">");
          }
          // Backreference
        } else if (backref) {
          // Rewrite the backreference
          return "\\".concat(+backref + numPriorCaptures);
        }
        return match;
      }
      if (!(isType(patterns, 'Array') && patterns.length)) {
        throw new TypeError('Must provide a nonempty array of patterns to merge');
      }
      var parts = /(\()(?!\?)|\\([1-9]\d*)|\\[\s\S]|\[(?:[^\\\]]|\\[\s\S])*\]/g;
      var output = [];
      var _iterator5 = _createForOfIteratorHelper$2(patterns),
        _step5;
      try {
        for (_iterator5.s(); !(_step5 = _iterator5.n()).done;) {
          var pattern = _step5.value;
          if (XRegExp.isRegExp(pattern)) {
            numPriorCaptures = numCaptures;
            captureNames = pattern[REGEX_DATA] && pattern[REGEX_DATA].captureNames || [];

            // Rewrite backreferences. Passing to XRegExp dies on octals and ensures patterns are
            // independently valid; helps keep this simple. Named captures are put back
            output.push(XRegExp(pattern.source).source.replace(parts, rewrite));
          } else {
            output.push(XRegExp.escape(pattern));
          }
        }
      } catch (err) {
        _iterator5.e(err);
      } finally {
        _iterator5.f();
      }
      var separator = conjunction === 'none' ? '' : '|';
      return XRegExp(output.join(separator), flags);
    };

    // ==--------------------------==
    // Fixed/extended native methods
    // ==--------------------------==

    /**
     * Adds named capture support (with backreferences returned as `result.name`), and fixes browser
     * bugs in the native `RegExp.prototype.exec`. Use via `XRegExp.exec`.
     *
     * @memberOf RegExp
     * @param {String} str String to search.
     * @returns {Array} Match array with named backreference properties, or `null`.
     */
    fixed.exec = function (str) {
      var origLastIndex = this.lastIndex;
      var match = RegExp.prototype.exec.apply(this, arguments);
      if (match) {
        // Fix browsers whose `exec` methods don't return `undefined` for nonparticipating capturing
        // groups. This fixes IE 5.5-8, but not IE 9's quirks mode or emulation of older IEs. IE 9
        // in standards mode follows the spec.
        if (!correctExecNpcg && match.length > 1 && match.includes('')) {
          var r2 = copyRegex(this, {
            removeG: true,
            isInternalOnly: true
          });
          // Using `str.slice(match.index)` rather than `match[0]` in case lookahead allowed
          // matching due to characters outside the match
          String(str).slice(match.index).replace(r2, function () {
            var len = arguments.length;
            // Skip index 0 and the last 2
            for (var i = 1; i < len - 2; ++i) {
              if ((i < 0 || arguments.length <= i ? undefined : arguments[i]) === undefined) {
                match[i] = undefined;
              }
            }
          });
        }

        // Attach named capture properties
        if (this[REGEX_DATA] && this[REGEX_DATA].captureNames) {
          var groupsObject = match;
          if (XRegExp.isInstalled('namespacing')) {
            // https://tc39.github.io/proposal-regexp-named-groups/#sec-regexpbuiltinexec
            match.groups = Object.create(null);
            groupsObject = match.groups;
          }
          // Skip index 0
          for (var i = 1; i < match.length; ++i) {
            var name = this[REGEX_DATA].captureNames[i - 1];
            if (name) {
              groupsObject[name] = match[i];
            }
          }
          // Preserve any existing `groups` obj that came from native ES2018 named capture
        } else if (!match.groups && XRegExp.isInstalled('namespacing')) {
          match.groups = undefined;
        }

        // Fix browsers that increment `lastIndex` after zero-length matches
        if (this.global && !match[0].length && this.lastIndex > match.index) {
          this.lastIndex = match.index;
        }
      }
      if (!this.global) {
        // Fixes IE, Opera bug (last tested IE 9, Opera 11.6)
        this.lastIndex = origLastIndex;
      }
      return match;
    };

    /**
     * Fixes browser bugs in the native `RegExp.prototype.test`.
     *
     * @memberOf RegExp
     * @param {String} str String to search.
     * @returns {boolean} Whether the regex matched the provided value.
     */
    fixed.test = function (str) {
      // Do this the easy way :-)
      return !!fixed.exec.call(this, str);
    };

    /**
     * Adds named capture support (with backreferences returned as `result.name`), and fixes browser
     * bugs in the native `String.prototype.match`.
     *
     * @memberOf String
     * @param {RegExp|*} regex Regex to search with. If not a regex object, it is passed to `RegExp`.
     * @returns {Array} If `regex` uses flag g, an array of match strings or `null`. Without flag g,
     *   the result of calling `regex.exec(this)`.
     */
    fixed.match = function (regex) {
      if (!XRegExp.isRegExp(regex)) {
        // Use the native `RegExp` rather than `XRegExp`
        regex = new RegExp(regex);
      } else if (regex.global) {
        var result = String.prototype.match.apply(this, arguments);
        // Fixes IE bug
        regex.lastIndex = 0;
        return result;
      }
      return fixed.exec.call(regex, nullThrows(this));
    };

    /**
     * Adds support for `${n}` (or `$<n>`) tokens for named and numbered backreferences in replacement
     * text, and provides named backreferences to replacement functions as `arguments[0].name`. Also
     * fixes browser bugs in replacement text syntax when performing a replacement using a nonregex
     * search value, and the value of a replacement regex's `lastIndex` property during replacement
     * iterations and upon completion. Note that this doesn't support SpiderMonkey's proprietary third
     * (`flags`) argument. Use via `XRegExp.replace`.
     *
     * @memberOf String
     * @param {RegExp|String} search Search pattern to be replaced.
     * @param {String|Function} replacement Replacement string or a function invoked to create it.
     * @returns {string} New string with one or all matches replaced.
     */
    fixed.replace = function (search, replacement) {
      var isRegex = XRegExp.isRegExp(search);
      var origLastIndex;
      var captureNames;
      var result;
      if (isRegex) {
        if (search[REGEX_DATA]) {
          captureNames = search[REGEX_DATA].captureNames;
        }
        // Only needed if `search` is nonglobal
        origLastIndex = search.lastIndex;
      } else {
        search += ''; // Type-convert
      }

      // Don't use `typeof`; some older browsers return 'function' for regex objects
      if (isType(replacement, 'Function')) {
        // Stringifying `this` fixes a bug in IE < 9 where the last argument in replacement
        // functions isn't type-converted to a string
        result = String(this).replace(search, function () {
          for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
            args[_key] = arguments[_key];
          }
          if (captureNames) {
            var groupsObject;
            if (XRegExp.isInstalled('namespacing')) {
              // https://tc39.github.io/proposal-regexp-named-groups/#sec-regexpbuiltinexec
              groupsObject = Object.create(null);
              args.push(groupsObject);
            } else {
              // Change the `args[0]` string primitive to a `String` object that can store
              // properties. This really does need to use `String` as a constructor
              args[0] = new String(args[0]);
              groupsObject = args[0];
            }

            // Store named backreferences
            for (var i = 0; i < captureNames.length; ++i) {
              if (captureNames[i]) {
                groupsObject[captureNames[i]] = args[i + 1];
              }
            }
          }
          // ES6 specs the context for replacement functions as `undefined`
          return replacement(...args);
        });
      } else {
        // Ensure that the last value of `args` will be a string when given nonstring `this`,
        // while still throwing on null or undefined context
        result = String(nullThrows(this)).replace(search, function () {
          for (var _len2 = arguments.length, args = new Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {
            args[_key2] = arguments[_key2];
          }
          return String(replacement).replace(replacementToken, replacer);
          function replacer($0, bracketed, angled, dollarToken) {
            bracketed = bracketed || angled;

            // ES2018 added a new trailing `groups` arg that's passed to replacement functions
            // when the search regex uses native named capture
            var numNonCaptureArgs = isType(args[args.length - 1], 'Object') ? 4 : 3;
            var numCaptures = args.length - numNonCaptureArgs;

            // Handle named or numbered backreference with curly or angled braces: ${n}, $<n>
            if (bracketed) {
              // Handle backreference to numbered capture, if `bracketed` is an integer. Use
              // `0` for the entire match. Any number of leading zeros may be used.
              if (/^\d+$/.test(bracketed)) {
                // Type-convert and drop leading zeros
                var _n = +bracketed;
                if (_n <= numCaptures) {
                  return args[_n] || '';
                }
              }

              // Handle backreference to named capture. If the name does not refer to an
              // existing capturing group, it's an error. Also handles the error for numbered
              // backference that does not refer to an existing group.
              // Using `indexOf` since having groups with the same name is already an error,
              // otherwise would need `lastIndexOf`.
              var n = captureNames ? captureNames.indexOf(bracketed) : -1;
              if (n < 0) {
                throw new SyntaxError("Backreference to undefined group ".concat($0));
              }
              return args[n + 1] || '';
            }

            // Handle `$`-prefixed variable
            // Handle space/blank first because type conversion with `+` drops space padding
            // and converts spaces and empty strings to `0`
            if (dollarToken === '' || dollarToken === ' ') {
              throw new SyntaxError("Invalid token ".concat($0));
            }
            if (dollarToken === '&' || +dollarToken === 0) {
              // $&, $0 (not followed by 1-9), $00
              return args[0];
            }
            if (dollarToken === '$') {
              // $$
              return '$';
            }
            if (dollarToken === '`') {
              // $` (left context)
              return args[args.length - 1].slice(0, args[args.length - 2]);
            }
            if (dollarToken === "'") {
              // $' (right context)
              return args[args.length - 1].slice(args[args.length - 2] + args[0].length);
            }

            // Handle numbered backreference without braces
            // Type-convert and drop leading zero
            dollarToken = +dollarToken;
            // XRegExp behavior for `$n` and `$nn`:
            // - Backrefs end after 1 or 2 digits. Use `${..}` or `$<..>` for more digits.
            // - `$1` is an error if no capturing groups.
            // - `$10` is an error if less than 10 capturing groups. Use `${1}0` or `$<1>0`
            //   instead.
            // - `$01` is `$1` if at least one capturing group, else it's an error.
            // - `$0` (not followed by 1-9) and `$00` are the entire match.
            // Native behavior, for comparison:
            // - Backrefs end after 1 or 2 digits. Cannot reference capturing group 100+.
            // - `$1` is a literal `$1` if no capturing groups.
            // - `$10` is `$1` followed by a literal `0` if less than 10 capturing groups.
            // - `$01` is `$1` if at least one capturing group, else it's a literal `$01`.
            // - `$0` is a literal `$0`.
            if (!isNaN(dollarToken)) {
              if (dollarToken > numCaptures) {
                throw new SyntaxError("Backreference to undefined group ".concat($0));
              }
              return args[dollarToken] || '';
            }

            // `$` followed by an unsupported char is an error, unlike native JS
            throw new SyntaxError("Invalid token ".concat($0));
          }
        });
      }
      if (isRegex) {
        if (search.global) {
          // Fixes IE, Safari bug (last tested IE 9, Safari 5.1)
          search.lastIndex = 0;
        } else {
          // Fixes IE, Opera bug (last tested IE 9, Opera 11.6)
          search.lastIndex = origLastIndex;
        }
      }
      return result;
    };

    /**
     * Fixes browser bugs in the native `String.prototype.split`. Use via `XRegExp.split`.
     *
     * @memberOf String
     * @param {RegExp|String} separator Regex or string to use for separating the string.
     * @param {Number} [limit] Maximum number of items to include in the result array.
     * @returns {!Array} Array of substrings.
     */
    fixed.split = function (separator, limit) {
      if (!XRegExp.isRegExp(separator)) {
        // Browsers handle nonregex split correctly, so use the faster native method
        return String.prototype.split.apply(this, arguments);
      }
      var str = String(this);
      var output = [];
      var origLastIndex = separator.lastIndex;
      var lastLastIndex = 0;
      var lastLength;

      // Values for `limit`, per the spec:
      // If undefined: pow(2,32) - 1
      // If 0, Infinity, or NaN: 0
      // If positive number: limit = floor(limit); if (limit >= pow(2,32)) limit -= pow(2,32);
      // If negative number: pow(2,32) - floor(abs(limit))
      // If other: Type-convert, then use the above rules
      // This line fails in very strange ways for some values of `limit` in Opera 10.5-10.63, unless
      // Opera Dragonfly is open (go figure). It works in at least Opera 9.5-10.1 and 11+
      limit = (limit === undefined ? -1 : limit) >>> 0;
      XRegExp.forEach(str, separator, function (match) {
        // This condition is not the same as `if (match[0].length)`
        if (match.index + match[0].length > lastLastIndex) {
          output.push(str.slice(lastLastIndex, match.index));
          if (match.length > 1 && match.index < str.length) {
            Array.prototype.push.apply(output, match.slice(1));
          }
          lastLength = match[0].length;
          lastLastIndex = match.index + lastLength;
        }
      });
      if (lastLastIndex === str.length) {
        if (!separator.test('') || lastLength) {
          output.push('');
        }
      } else {
        output.push(str.slice(lastLastIndex));
      }
      separator.lastIndex = origLastIndex;
      return output.length > limit ? output.slice(0, limit) : output;
    };

    // ==--------------------------==
    // Built-in syntax/flag tokens
    // ==--------------------------==

    /*
     * Letter escapes that natively match literal characters: `\a`, `\A`, etc. These should be
     * SyntaxErrors but are allowed in web reality. XRegExp makes them errors for cross-browser
     * consistency and to reserve their syntax, but lets them be superseded by addons.
     */
    XRegExp.addToken(/\\([ABCE-RTUVXYZaeg-mopqyz]|c(?![A-Za-z])|u(?![\dA-Fa-f]{4}|{[\dA-Fa-f]+})|x(?![\dA-Fa-f]{2}))/, function (match, scope) {
      // \B is allowed in default scope only
      if (match[1] === 'B' && scope === defaultScope) {
        return match[0];
      }
      throw new SyntaxError("Invalid escape ".concat(match[0]));
    }, {
      scope: 'all',
      leadChar: '\\'
    });

    /*
     * Unicode code point escape with curly braces: `\u{N..}`. `N..` is any one or more digit
     * hexadecimal number from 0-10FFFF, and can include leading zeros. Requires the native ES6 `u` flag
     * to support code points greater than U+FFFF. Avoids converting code points above U+FFFF to
     * surrogate pairs (which could be done without flag `u`), since that could lead to broken behavior
     * if you follow a `\u{N..}` token that references a code point above U+FFFF with a quantifier, or
     * if you use the same in a character class.
     */
    XRegExp.addToken(/\\u{([\dA-Fa-f]+)}/, function (match, scope, flags) {
      var code = dec(match[1]);
      if (code > 0x10FFFF) {
        throw new SyntaxError("Invalid Unicode code point ".concat(match[0]));
      }
      if (code <= 0xFFFF) {
        // Converting to \uNNNN avoids needing to escape the literal character and keep it
        // separate from preceding tokens
        return "\\u".concat(pad4(hex(code)));
      }
      // If `code` is between 0xFFFF and 0x10FFFF, require and defer to native handling
      if (hasNativeU && flags.includes('u')) {
        return match[0];
      }
      throw new SyntaxError("Cannot use Unicode code point above \\u{FFFF} without flag u");
    }, {
      scope: 'all',
      leadChar: '\\'
    });

    /*
     * Comment pattern: `(?# )`. Inline comments are an alternative to the line comments allowed in
     * free-spacing mode (flag x).
     */
    XRegExp.addToken(/\(\?#[^)]*\)/, getContextualTokenSeparator, {
      leadChar: '('
    });

    /*
     * Whitespace and line comments, in free-spacing mode (aka extended mode, flag x) only.
     */
    XRegExp.addToken(/\s+|#[^\n]*\n?/, getContextualTokenSeparator, {
      flag: 'x'
    });

    /*
     * Dot, in dotAll mode (aka singleline mode, flag s) only.
     */
    if (!hasNativeS) {
      XRegExp.addToken(/\./, function () {
        return '[\\s\\S]';
      }, {
        flag: 's',
        leadChar: '.'
      });
    }

    /*
     * Named backreference: `\k<name>`. Backreference names can use RegExpIdentifierName characters
     * only. Also allows numbered backreferences as `\k<n>`.
     */
    XRegExp.addToken(/\\k<([^>]+)>/, function (match) {
      // Groups with the same name is an error, else would need `lastIndexOf`
      var index = isNaN(match[1]) ? this.captureNames.indexOf(match[1]) + 1 : +match[1];
      var endIndex = match.index + match[0].length;
      if (!index || index > this.captureNames.length) {
        throw new SyntaxError("Backreference to undefined group ".concat(match[0]));
      }
      // Keep backreferences separate from subsequent literal numbers. This avoids e.g.
      // inadvertedly changing `(?<n>)\k<n>1` to `()\11`.
      return "\\".concat(index).concat(endIndex === match.input.length || isNaN(match.input[endIndex]) ? '' : '(?:)');
    }, {
      leadChar: '\\'
    });

    /*
     * Numbered backreference or octal, plus any following digits: `\0`, `\11`, etc. Octals except `\0`
     * not followed by 0-9 and backreferences to unopened capture groups throw an error. Other matches
     * are returned unaltered. IE < 9 doesn't support backreferences above `\99` in regex syntax.
     */
    XRegExp.addToken(/\\(\d+)/, function (match, scope) {
      if (!(scope === defaultScope && /^[1-9]/.test(match[1]) && +match[1] <= this.captureNames.length) && match[1] !== '0') {
        throw new SyntaxError("Cannot use octal escape or backreference to undefined group ".concat(match[0]));
      }
      return match[0];
    }, {
      scope: 'all',
      leadChar: '\\'
    });

    /*
     * Named capturing group; match the opening delimiter only: `(?<name>`. Capture names can use the
     * RegExpIdentifierName characters only. Names can't be integers. Supports Python-style
     * `(?P<name>` as an alternate syntax to avoid issues in some older versions of Opera which natively
     * supported the Python-style syntax. Otherwise, XRegExp might treat numbered backreferences to
     * Python-style named capture as octals.
     */
    XRegExp.addToken(/\(\?P?<((?:[\$A-Z_a-z\xAA\xB5\xBA\xC0-\xD6\xD8-\xF6\xF8-\u02C1\u02C6-\u02D1\u02E0-\u02E4\u02EC\u02EE\u0370-\u0374\u0376\u0377\u037A-\u037D\u037F\u0386\u0388-\u038A\u038C\u038E-\u03A1\u03A3-\u03F5\u03F7-\u0481\u048A-\u052F\u0531-\u0556\u0559\u0560-\u0588\u05D0-\u05EA\u05EF-\u05F2\u0620-\u064A\u066E\u066F\u0671-\u06D3\u06D5\u06E5\u06E6\u06EE\u06EF\u06FA-\u06FC\u06FF\u0710\u0712-\u072F\u074D-\u07A5\u07B1\u07CA-\u07EA\u07F4\u07F5\u07FA\u0800-\u0815\u081A\u0824\u0828\u0840-\u0858\u0860-\u086A\u0870-\u0887\u0889-\u088E\u08A0-\u08C9\u0904-\u0939\u093D\u0950\u0958-\u0961\u0971-\u0980\u0985-\u098C\u098F\u0990\u0993-\u09A8\u09AA-\u09B0\u09B2\u09B6-\u09B9\u09BD\u09CE\u09DC\u09DD\u09DF-\u09E1\u09F0\u09F1\u09FC\u0A05-\u0A0A\u0A0F\u0A10\u0A13-\u0A28\u0A2A-\u0A30\u0A32\u0A33\u0A35\u0A36\u0A38\u0A39\u0A59-\u0A5C\u0A5E\u0A72-\u0A74\u0A85-\u0A8D\u0A8F-\u0A91\u0A93-\u0AA8\u0AAA-\u0AB0\u0AB2\u0AB3\u0AB5-\u0AB9\u0ABD\u0AD0\u0AE0\u0AE1\u0AF9\u0B05-\u0B0C\u0B0F\u0B10\u0B13-\u0B28\u0B2A-\u0B30\u0B32\u0B33\u0B35-\u0B39\u0B3D\u0B5C\u0B5D\u0B5F-\u0B61\u0B71\u0B83\u0B85-\u0B8A\u0B8E-\u0B90\u0B92-\u0B95\u0B99\u0B9A\u0B9C\u0B9E\u0B9F\u0BA3\u0BA4\u0BA8-\u0BAA\u0BAE-\u0BB9\u0BD0\u0C05-\u0C0C\u0C0E-\u0C10\u0C12-\u0C28\u0C2A-\u0C39\u0C3D\u0C58-\u0C5A\u0C5D\u0C60\u0C61\u0C80\u0C85-\u0C8C\u0C8E-\u0C90\u0C92-\u0CA8\u0CAA-\u0CB3\u0CB5-\u0CB9\u0CBD\u0CDD\u0CDE\u0CE0\u0CE1\u0CF1\u0CF2\u0D04-\u0D0C\u0D0E-\u0D10\u0D12-\u0D3A\u0D3D\u0D4E\u0D54-\u0D56\u0D5F-\u0D61\u0D7A-\u0D7F\u0D85-\u0D96\u0D9A-\u0DB1\u0DB3-\u0DBB\u0DBD\u0DC0-\u0DC6\u0E01-\u0E30\u0E32\u0E33\u0E40-\u0E46\u0E81\u0E82\u0E84\u0E86-\u0E8A\u0E8C-\u0EA3\u0EA5\u0EA7-\u0EB0\u0EB2\u0EB3\u0EBD\u0EC0-\u0EC4\u0EC6\u0EDC-\u0EDF\u0F00\u0F40-\u0F47\u0F49-\u0F6C\u0F88-\u0F8C\u1000-\u102A\u103F\u1050-\u1055\u105A-\u105D\u1061\u1065\u1066\u106E-\u1070\u1075-\u1081\u108E\u10A0-\u10C5\u10C7\u10CD\u10D0-\u10FA\u10FC-\u1248\u124A-\u124D\u1250-\u1256\u1258\u125A-\u125D\u1260-\u1288\u128A-\u128D\u1290-\u12B0\u12B2-\u12B5\u12B8-\u12BE\u12C0\u12C2-\u12C5\u12C8-\u12D6\u12D8-\u1310\u1312-\u1315\u1318-\u135A\u1380-\u138F\u13A0-\u13F5\u13F8-\u13FD\u1401-\u166C\u166F-\u167F\u1681-\u169A\u16A0-\u16EA\u16EE-\u16F8\u1700-\u1711\u171F-\u1731\u1740-\u1751\u1760-\u176C\u176E-\u1770\u1780-\u17B3\u17D7\u17DC\u1820-\u1878\u1880-\u18A8\u18AA\u18B0-\u18F5\u1900-\u191E\u1950-\u196D\u1970-\u1974\u1980-\u19AB\u19B0-\u19C9\u1A00-\u1A16\u1A20-\u1A54\u1AA7\u1B05-\u1B33\u1B45-\u1B4C\u1B83-\u1BA0\u1BAE\u1BAF\u1BBA-\u1BE5\u1C00-\u1C23\u1C4D-\u1C4F\u1C5A-\u1C7D\u1C80-\u1C88\u1C90-\u1CBA\u1CBD-\u1CBF\u1CE9-\u1CEC\u1CEE-\u1CF3\u1CF5\u1CF6\u1CFA\u1D00-\u1DBF\u1E00-\u1F15\u1F18-\u1F1D\u1F20-\u1F45\u1F48-\u1F4D\u1F50-\u1F57\u1F59\u1F5B\u1F5D\u1F5F-\u1F7D\u1F80-\u1FB4\u1FB6-\u1FBC\u1FBE\u1FC2-\u1FC4\u1FC6-\u1FCC\u1FD0-\u1FD3\u1FD6-\u1FDB\u1FE0-\u1FEC\u1FF2-\u1FF4\u1FF6-\u1FFC\u2071\u207F\u2090-\u209C\u2102\u2107\u210A-\u2113\u2115\u2118-\u211D\u2124\u2126\u2128\u212A-\u2139\u213C-\u213F\u2145-\u2149\u214E\u2160-\u2188\u2C00-\u2CE4\u2CEB-\u2CEE\u2CF2\u2CF3\u2D00-\u2D25\u2D27\u2D2D\u2D30-\u2D67\u2D6F\u2D80-\u2D96\u2DA0-\u2DA6\u2DA8-\u2DAE\u2DB0-\u2DB6\u2DB8-\u2DBE\u2DC0-\u2DC6\u2DC8-\u2DCE\u2DD0-\u2DD6\u2DD8-\u2DDE\u3005-\u3007\u3021-\u3029\u3031-\u3035\u3038-\u303C\u3041-\u3096\u309B-\u309F\u30A1-\u30FA\u30FC-\u30FF\u3105-\u312F\u3131-\u318E\u31A0-\u31BF\u31F0-\u31FF\u3400-\u4DBF\u4E00-\uA48C\uA4D0-\uA4FD\uA500-\uA60C\uA610-\uA61F\uA62A\uA62B\uA640-\uA66E\uA67F-\uA69D\uA6A0-\uA6EF\uA717-\uA71F\uA722-\uA788\uA78B-\uA7CA\uA7D0\uA7D1\uA7D3\uA7D5-\uA7D9\uA7F2-\uA801\uA803-\uA805\uA807-\uA80A\uA80C-\uA822\uA840-\uA873\uA882-\uA8B3\uA8F2-\uA8F7\uA8FB\uA8FD\uA8FE\uA90A-\uA925\uA930-\uA946\uA960-\uA97C\uA984-\uA9B2\uA9CF\uA9E0-\uA9E4\uA9E6-\uA9EF\uA9FA-\uA9FE\uAA00-\uAA28\uAA40-\uAA42\uAA44-\uAA4B\uAA60-\uAA76\uAA7A\uAA7E-\uAAAF\uAAB1\uAAB5\uAAB6\uAAB9-\uAABD\uAAC0\uAAC2\uAADB-\uAADD\uAAE0-\uAAEA\uAAF2-\uAAF4\uAB01-\uAB06\uAB09-\uAB0E\uAB11-\uAB16\uAB20-\uAB26\uAB28-\uAB2E\uAB30-\uAB5A\uAB5C-\uAB69\uAB70-\uABE2\uAC00-\uD7A3\uD7B0-\uD7C6\uD7CB-\uD7FB\uF900-\uFA6D\uFA70-\uFAD9\uFB00-\uFB06\uFB13-\uFB17\uFB1D\uFB1F-\uFB28\uFB2A-\uFB36\uFB38-\uFB3C\uFB3E\uFB40\uFB41\uFB43\uFB44\uFB46-\uFBB1\uFBD3-\uFD3D\uFD50-\uFD8F\uFD92-\uFDC7\uFDF0-\uFDFB\uFE70-\uFE74\uFE76-\uFEFC\uFF21-\uFF3A\uFF41-\uFF5A\uFF66-\uFFBE\uFFC2-\uFFC7\uFFCA-\uFFCF\uFFD2-\uFFD7\uFFDA-\uFFDC]|\uD800[\uDC00-\uDC0B\uDC0D-\uDC26\uDC28-\uDC3A\uDC3C\uDC3D\uDC3F-\uDC4D\uDC50-\uDC5D\uDC80-\uDCFA\uDD40-\uDD74\uDE80-\uDE9C\uDEA0-\uDED0\uDF00-\uDF1F\uDF2D-\uDF4A\uDF50-\uDF75\uDF80-\uDF9D\uDFA0-\uDFC3\uDFC8-\uDFCF\uDFD1-\uDFD5]|\uD801[\uDC00-\uDC9D\uDCB0-\uDCD3\uDCD8-\uDCFB\uDD00-\uDD27\uDD30-\uDD63\uDD70-\uDD7A\uDD7C-\uDD8A\uDD8C-\uDD92\uDD94\uDD95\uDD97-\uDDA1\uDDA3-\uDDB1\uDDB3-\uDDB9\uDDBB\uDDBC\uDE00-\uDF36\uDF40-\uDF55\uDF60-\uDF67\uDF80-\uDF85\uDF87-\uDFB0\uDFB2-\uDFBA]|\uD802[\uDC00-\uDC05\uDC08\uDC0A-\uDC35\uDC37\uDC38\uDC3C\uDC3F-\uDC55\uDC60-\uDC76\uDC80-\uDC9E\uDCE0-\uDCF2\uDCF4\uDCF5\uDD00-\uDD15\uDD20-\uDD39\uDD80-\uDDB7\uDDBE\uDDBF\uDE00\uDE10-\uDE13\uDE15-\uDE17\uDE19-\uDE35\uDE60-\uDE7C\uDE80-\uDE9C\uDEC0-\uDEC7\uDEC9-\uDEE4\uDF00-\uDF35\uDF40-\uDF55\uDF60-\uDF72\uDF80-\uDF91]|\uD803[\uDC00-\uDC48\uDC80-\uDCB2\uDCC0-\uDCF2\uDD00-\uDD23\uDE80-\uDEA9\uDEB0\uDEB1\uDF00-\uDF1C\uDF27\uDF30-\uDF45\uDF70-\uDF81\uDFB0-\uDFC4\uDFE0-\uDFF6]|\uD804[\uDC03-\uDC37\uDC71\uDC72\uDC75\uDC83-\uDCAF\uDCD0-\uDCE8\uDD03-\uDD26\uDD44\uDD47\uDD50-\uDD72\uDD76\uDD83-\uDDB2\uDDC1-\uDDC4\uDDDA\uDDDC\uDE00-\uDE11\uDE13-\uDE2B\uDE3F\uDE40\uDE80-\uDE86\uDE88\uDE8A-\uDE8D\uDE8F-\uDE9D\uDE9F-\uDEA8\uDEB0-\uDEDE\uDF05-\uDF0C\uDF0F\uDF10\uDF13-\uDF28\uDF2A-\uDF30\uDF32\uDF33\uDF35-\uDF39\uDF3D\uDF50\uDF5D-\uDF61]|\uD805[\uDC00-\uDC34\uDC47-\uDC4A\uDC5F-\uDC61\uDC80-\uDCAF\uDCC4\uDCC5\uDCC7\uDD80-\uDDAE\uDDD8-\uDDDB\uDE00-\uDE2F\uDE44\uDE80-\uDEAA\uDEB8\uDF00-\uDF1A\uDF40-\uDF46]|\uD806[\uDC00-\uDC2B\uDCA0-\uDCDF\uDCFF-\uDD06\uDD09\uDD0C-\uDD13\uDD15\uDD16\uDD18-\uDD2F\uDD3F\uDD41\uDDA0-\uDDA7\uDDAA-\uDDD0\uDDE1\uDDE3\uDE00\uDE0B-\uDE32\uDE3A\uDE50\uDE5C-\uDE89\uDE9D\uDEB0-\uDEF8]|\uD807[\uDC00-\uDC08\uDC0A-\uDC2E\uDC40\uDC72-\uDC8F\uDD00-\uDD06\uDD08\uDD09\uDD0B-\uDD30\uDD46\uDD60-\uDD65\uDD67\uDD68\uDD6A-\uDD89\uDD98\uDEE0-\uDEF2\uDF02\uDF04-\uDF10\uDF12-\uDF33\uDFB0]|\uD808[\uDC00-\uDF99]|\uD809[\uDC00-\uDC6E\uDC80-\uDD43]|\uD80B[\uDF90-\uDFF0]|[\uD80C\uD81C-\uD820\uD822\uD840-\uD868\uD86A-\uD86C\uD86F-\uD872\uD874-\uD879\uD880-\uD883\uD885-\uD887][\uDC00-\uDFFF]|\uD80D[\uDC00-\uDC2F\uDC41-\uDC46]|\uD811[\uDC00-\uDE46]|\uD81A[\uDC00-\uDE38\uDE40-\uDE5E\uDE70-\uDEBE\uDED0-\uDEED\uDF00-\uDF2F\uDF40-\uDF43\uDF63-\uDF77\uDF7D-\uDF8F]|\uD81B[\uDE40-\uDE7F\uDF00-\uDF4A\uDF50\uDF93-\uDF9F\uDFE0\uDFE1\uDFE3]|\uD821[\uDC00-\uDFF7]|\uD823[\uDC00-\uDCD5\uDD00-\uDD08]|\uD82B[\uDFF0-\uDFF3\uDFF5-\uDFFB\uDFFD\uDFFE]|\uD82C[\uDC00-\uDD22\uDD32\uDD50-\uDD52\uDD55\uDD64-\uDD67\uDD70-\uDEFB]|\uD82F[\uDC00-\uDC6A\uDC70-\uDC7C\uDC80-\uDC88\uDC90-\uDC99]|\uD835[\uDC00-\uDC54\uDC56-\uDC9C\uDC9E\uDC9F\uDCA2\uDCA5\uDCA6\uDCA9-\uDCAC\uDCAE-\uDCB9\uDCBB\uDCBD-\uDCC3\uDCC5-\uDD05\uDD07-\uDD0A\uDD0D-\uDD14\uDD16-\uDD1C\uDD1E-\uDD39\uDD3B-\uDD3E\uDD40-\uDD44\uDD46\uDD4A-\uDD50\uDD52-\uDEA5\uDEA8-\uDEC0\uDEC2-\uDEDA\uDEDC-\uDEFA\uDEFC-\uDF14\uDF16-\uDF34\uDF36-\uDF4E\uDF50-\uDF6E\uDF70-\uDF88\uDF8A-\uDFA8\uDFAA-\uDFC2\uDFC4-\uDFCB]|\uD837[\uDF00-\uDF1E\uDF25-\uDF2A]|\uD838[\uDC30-\uDC6D\uDD00-\uDD2C\uDD37-\uDD3D\uDD4E\uDE90-\uDEAD\uDEC0-\uDEEB]|\uD839[\uDCD0-\uDCEB\uDFE0-\uDFE6\uDFE8-\uDFEB\uDFED\uDFEE\uDFF0-\uDFFE]|\uD83A[\uDC00-\uDCC4\uDD00-\uDD43\uDD4B]|\uD83B[\uDE00-\uDE03\uDE05-\uDE1F\uDE21\uDE22\uDE24\uDE27\uDE29-\uDE32\uDE34-\uDE37\uDE39\uDE3B\uDE42\uDE47\uDE49\uDE4B\uDE4D-\uDE4F\uDE51\uDE52\uDE54\uDE57\uDE59\uDE5B\uDE5D\uDE5F\uDE61\uDE62\uDE64\uDE67-\uDE6A\uDE6C-\uDE72\uDE74-\uDE77\uDE79-\uDE7C\uDE7E\uDE80-\uDE89\uDE8B-\uDE9B\uDEA1-\uDEA3\uDEA5-\uDEA9\uDEAB-\uDEBB]|\uD869[\uDC00-\uDEDF\uDF00-\uDFFF]|\uD86D[\uDC00-\uDF39\uDF40-\uDFFF]|\uD86E[\uDC00-\uDC1D\uDC20-\uDFFF]|\uD873[\uDC00-\uDEA1\uDEB0-\uDFFF]|\uD87A[\uDC00-\uDFE0]|\uD87E[\uDC00-\uDE1D]|\uD884[\uDC00-\uDF4A\uDF50-\uDFFF]|\uD888[\uDC00-\uDFAF])(?:[\$0-9A-Z_a-z\xAA\xB5\xB7\xBA\xC0-\xD6\xD8-\xF6\xF8-\u02C1\u02C6-\u02D1\u02E0-\u02E4\u02EC\u02EE\u0300-\u0374\u0376\u0377\u037A-\u037D\u037F\u0386-\u038A\u038C\u038E-\u03A1\u03A3-\u03F5\u03F7-\u0481\u0483-\u0487\u048A-\u052F\u0531-\u0556\u0559\u0560-\u0588\u0591-\u05BD\u05BF\u05C1\u05C2\u05C4\u05C5\u05C7\u05D0-\u05EA\u05EF-\u05F2\u0610-\u061A\u0620-\u0669\u066E-\u06D3\u06D5-\u06DC\u06DF-\u06E8\u06EA-\u06FC\u06FF\u0710-\u074A\u074D-\u07B1\u07C0-\u07F5\u07FA\u07FD\u0800-\u082D\u0840-\u085B\u0860-\u086A\u0870-\u0887\u0889-\u088E\u0898-\u08E1\u08E3-\u0963\u0966-\u096F\u0971-\u0983\u0985-\u098C\u098F\u0990\u0993-\u09A8\u09AA-\u09B0\u09B2\u09B6-\u09B9\u09BC-\u09C4\u09C7\u09C8\u09CB-\u09CE\u09D7\u09DC\u09DD\u09DF-\u09E3\u09E6-\u09F1\u09FC\u09FE\u0A01-\u0A03\u0A05-\u0A0A\u0A0F\u0A10\u0A13-\u0A28\u0A2A-\u0A30\u0A32\u0A33\u0A35\u0A36\u0A38\u0A39\u0A3C\u0A3E-\u0A42\u0A47\u0A48\u0A4B-\u0A4D\u0A51\u0A59-\u0A5C\u0A5E\u0A66-\u0A75\u0A81-\u0A83\u0A85-\u0A8D\u0A8F-\u0A91\u0A93-\u0AA8\u0AAA-\u0AB0\u0AB2\u0AB3\u0AB5-\u0AB9\u0ABC-\u0AC5\u0AC7-\u0AC9\u0ACB-\u0ACD\u0AD0\u0AE0-\u0AE3\u0AE6-\u0AEF\u0AF9-\u0AFF\u0B01-\u0B03\u0B05-\u0B0C\u0B0F\u0B10\u0B13-\u0B28\u0B2A-\u0B30\u0B32\u0B33\u0B35-\u0B39\u0B3C-\u0B44\u0B47\u0B48\u0B4B-\u0B4D\u0B55-\u0B57\u0B5C\u0B5D\u0B5F-\u0B63\u0B66-\u0B6F\u0B71\u0B82\u0B83\u0B85-\u0B8A\u0B8E-\u0B90\u0B92-\u0B95\u0B99\u0B9A\u0B9C\u0B9E\u0B9F\u0BA3\u0BA4\u0BA8-\u0BAA\u0BAE-\u0BB9\u0BBE-\u0BC2\u0BC6-\u0BC8\u0BCA-\u0BCD\u0BD0\u0BD7\u0BE6-\u0BEF\u0C00-\u0C0C\u0C0E-\u0C10\u0C12-\u0C28\u0C2A-\u0C39\u0C3C-\u0C44\u0C46-\u0C48\u0C4A-\u0C4D\u0C55\u0C56\u0C58-\u0C5A\u0C5D\u0C60-\u0C63\u0C66-\u0C6F\u0C80-\u0C83\u0C85-\u0C8C\u0C8E-\u0C90\u0C92-\u0CA8\u0CAA-\u0CB3\u0CB5-\u0CB9\u0CBC-\u0CC4\u0CC6-\u0CC8\u0CCA-\u0CCD\u0CD5\u0CD6\u0CDD\u0CDE\u0CE0-\u0CE3\u0CE6-\u0CEF\u0CF1-\u0CF3\u0D00-\u0D0C\u0D0E-\u0D10\u0D12-\u0D44\u0D46-\u0D48\u0D4A-\u0D4E\u0D54-\u0D57\u0D5F-\u0D63\u0D66-\u0D6F\u0D7A-\u0D7F\u0D81-\u0D83\u0D85-\u0D96\u0D9A-\u0DB1\u0DB3-\u0DBB\u0DBD\u0DC0-\u0DC6\u0DCA\u0DCF-\u0DD4\u0DD6\u0DD8-\u0DDF\u0DE6-\u0DEF\u0DF2\u0DF3\u0E01-\u0E3A\u0E40-\u0E4E\u0E50-\u0E59\u0E81\u0E82\u0E84\u0E86-\u0E8A\u0E8C-\u0EA3\u0EA5\u0EA7-\u0EBD\u0EC0-\u0EC4\u0EC6\u0EC8-\u0ECE\u0ED0-\u0ED9\u0EDC-\u0EDF\u0F00\u0F18\u0F19\u0F20-\u0F29\u0F35\u0F37\u0F39\u0F3E-\u0F47\u0F49-\u0F6C\u0F71-\u0F84\u0F86-\u0F97\u0F99-\u0FBC\u0FC6\u1000-\u1049\u1050-\u109D\u10A0-\u10C5\u10C7\u10CD\u10D0-\u10FA\u10FC-\u1248\u124A-\u124D\u1250-\u1256\u1258\u125A-\u125D\u1260-\u1288\u128A-\u128D\u1290-\u12B0\u12B2-\u12B5\u12B8-\u12BE\u12C0\u12C2-\u12C5\u12C8-\u12D6\u12D8-\u1310\u1312-\u1315\u1318-\u135A\u135D-\u135F\u1369-\u1371\u1380-\u138F\u13A0-\u13F5\u13F8-\u13FD\u1401-\u166C\u166F-\u167F\u1681-\u169A\u16A0-\u16EA\u16EE-\u16F8\u1700-\u1715\u171F-\u1734\u1740-\u1753\u1760-\u176C\u176E-\u1770\u1772\u1773\u1780-\u17D3\u17D7\u17DC\u17DD\u17E0-\u17E9\u180B-\u180D\u180F-\u1819\u1820-\u1878\u1880-\u18AA\u18B0-\u18F5\u1900-\u191E\u1920-\u192B\u1930-\u193B\u1946-\u196D\u1970-\u1974\u1980-\u19AB\u19B0-\u19C9\u19D0-\u19DA\u1A00-\u1A1B\u1A20-\u1A5E\u1A60-\u1A7C\u1A7F-\u1A89\u1A90-\u1A99\u1AA7\u1AB0-\u1ABD\u1ABF-\u1ACE\u1B00-\u1B4C\u1B50-\u1B59\u1B6B-\u1B73\u1B80-\u1BF3\u1C00-\u1C37\u1C40-\u1C49\u1C4D-\u1C7D\u1C80-\u1C88\u1C90-\u1CBA\u1CBD-\u1CBF\u1CD0-\u1CD2\u1CD4-\u1CFA\u1D00-\u1F15\u1F18-\u1F1D\u1F20-\u1F45\u1F48-\u1F4D\u1F50-\u1F57\u1F59\u1F5B\u1F5D\u1F5F-\u1F7D\u1F80-\u1FB4\u1FB6-\u1FBC\u1FBE\u1FC2-\u1FC4\u1FC6-\u1FCC\u1FD0-\u1FD3\u1FD6-\u1FDB\u1FE0-\u1FEC\u1FF2-\u1FF4\u1FF6-\u1FFC\u200C\u200D\u203F\u2040\u2054\u2071\u207F\u2090-\u209C\u20D0-\u20DC\u20E1\u20E5-\u20F0\u2102\u2107\u210A-\u2113\u2115\u2118-\u211D\u2124\u2126\u2128\u212A-\u2139\u213C-\u213F\u2145-\u2149\u214E\u2160-\u2188\u2C00-\u2CE4\u2CEB-\u2CF3\u2D00-\u2D25\u2D27\u2D2D\u2D30-\u2D67\u2D6F\u2D7F-\u2D96\u2DA0-\u2DA6\u2DA8-\u2DAE\u2DB0-\u2DB6\u2DB8-\u2DBE\u2DC0-\u2DC6\u2DC8-\u2DCE\u2DD0-\u2DD6\u2DD8-\u2DDE\u2DE0-\u2DFF\u3005-\u3007\u3021-\u302F\u3031-\u3035\u3038-\u303C\u3041-\u3096\u3099-\u309F\u30A1-\u30FA\u30FC-\u30FF\u3105-\u312F\u3131-\u318E\u31A0-\u31BF\u31F0-\u31FF\u3400-\u4DBF\u4E00-\uA48C\uA4D0-\uA4FD\uA500-\uA60C\uA610-\uA62B\uA640-\uA66F\uA674-\uA67D\uA67F-\uA6F1\uA717-\uA71F\uA722-\uA788\uA78B-\uA7CA\uA7D0\uA7D1\uA7D3\uA7D5-\uA7D9\uA7F2-\uA827\uA82C\uA840-\uA873\uA880-\uA8C5\uA8D0-\uA8D9\uA8E0-\uA8F7\uA8FB\uA8FD-\uA92D\uA930-\uA953\uA960-\uA97C\uA980-\uA9C0\uA9CF-\uA9D9\uA9E0-\uA9FE\uAA00-\uAA36\uAA40-\uAA4D\uAA50-\uAA59\uAA60-\uAA76\uAA7A-\uAAC2\uAADB-\uAADD\uAAE0-\uAAEF\uAAF2-\uAAF6\uAB01-\uAB06\uAB09-\uAB0E\uAB11-\uAB16\uAB20-\uAB26\uAB28-\uAB2E\uAB30-\uAB5A\uAB5C-\uAB69\uAB70-\uABEA\uABEC\uABED\uABF0-\uABF9\uAC00-\uD7A3\uD7B0-\uD7C6\uD7CB-\uD7FB\uF900-\uFA6D\uFA70-\uFAD9\uFB00-\uFB06\uFB13-\uFB17\uFB1D-\uFB28\uFB2A-\uFB36\uFB38-\uFB3C\uFB3E\uFB40\uFB41\uFB43\uFB44\uFB46-\uFBB1\uFBD3-\uFD3D\uFD50-\uFD8F\uFD92-\uFDC7\uFDF0-\uFDFB\uFE00-\uFE0F\uFE20-\uFE2F\uFE33\uFE34\uFE4D-\uFE4F\uFE70-\uFE74\uFE76-\uFEFC\uFF10-\uFF19\uFF21-\uFF3A\uFF3F\uFF41-\uFF5A\uFF66-\uFFBE\uFFC2-\uFFC7\uFFCA-\uFFCF\uFFD2-\uFFD7\uFFDA-\uFFDC]|\uD800[\uDC00-\uDC0B\uDC0D-\uDC26\uDC28-\uDC3A\uDC3C\uDC3D\uDC3F-\uDC4D\uDC50-\uDC5D\uDC80-\uDCFA\uDD40-\uDD74\uDDFD\uDE80-\uDE9C\uDEA0-\uDED0\uDEE0\uDF00-\uDF1F\uDF2D-\uDF4A\uDF50-\uDF7A\uDF80-\uDF9D\uDFA0-\uDFC3\uDFC8-\uDFCF\uDFD1-\uDFD5]|\uD801[\uDC00-\uDC9D\uDCA0-\uDCA9\uDCB0-\uDCD3\uDCD8-\uDCFB\uDD00-\uDD27\uDD30-\uDD63\uDD70-\uDD7A\uDD7C-\uDD8A\uDD8C-\uDD92\uDD94\uDD95\uDD97-\uDDA1\uDDA3-\uDDB1\uDDB3-\uDDB9\uDDBB\uDDBC\uDE00-\uDF36\uDF40-\uDF55\uDF60-\uDF67\uDF80-\uDF85\uDF87-\uDFB0\uDFB2-\uDFBA]|\uD802[\uDC00-\uDC05\uDC08\uDC0A-\uDC35\uDC37\uDC38\uDC3C\uDC3F-\uDC55\uDC60-\uDC76\uDC80-\uDC9E\uDCE0-\uDCF2\uDCF4\uDCF5\uDD00-\uDD15\uDD20-\uDD39\uDD80-\uDDB7\uDDBE\uDDBF\uDE00-\uDE03\uDE05\uDE06\uDE0C-\uDE13\uDE15-\uDE17\uDE19-\uDE35\uDE38-\uDE3A\uDE3F\uDE60-\uDE7C\uDE80-\uDE9C\uDEC0-\uDEC7\uDEC9-\uDEE6\uDF00-\uDF35\uDF40-\uDF55\uDF60-\uDF72\uDF80-\uDF91]|\uD803[\uDC00-\uDC48\uDC80-\uDCB2\uDCC0-\uDCF2\uDD00-\uDD27\uDD30-\uDD39\uDE80-\uDEA9\uDEAB\uDEAC\uDEB0\uDEB1\uDEFD-\uDF1C\uDF27\uDF30-\uDF50\uDF70-\uDF85\uDFB0-\uDFC4\uDFE0-\uDFF6]|\uD804[\uDC00-\uDC46\uDC66-\uDC75\uDC7F-\uDCBA\uDCC2\uDCD0-\uDCE8\uDCF0-\uDCF9\uDD00-\uDD34\uDD36-\uDD3F\uDD44-\uDD47\uDD50-\uDD73\uDD76\uDD80-\uDDC4\uDDC9-\uDDCC\uDDCE-\uDDDA\uDDDC\uDE00-\uDE11\uDE13-\uDE37\uDE3E-\uDE41\uDE80-\uDE86\uDE88\uDE8A-\uDE8D\uDE8F-\uDE9D\uDE9F-\uDEA8\uDEB0-\uDEEA\uDEF0-\uDEF9\uDF00-\uDF03\uDF05-\uDF0C\uDF0F\uDF10\uDF13-\uDF28\uDF2A-\uDF30\uDF32\uDF33\uDF35-\uDF39\uDF3B-\uDF44\uDF47\uDF48\uDF4B-\uDF4D\uDF50\uDF57\uDF5D-\uDF63\uDF66-\uDF6C\uDF70-\uDF74]|\uD805[\uDC00-\uDC4A\uDC50-\uDC59\uDC5E-\uDC61\uDC80-\uDCC5\uDCC7\uDCD0-\uDCD9\uDD80-\uDDB5\uDDB8-\uDDC0\uDDD8-\uDDDD\uDE00-\uDE40\uDE44\uDE50-\uDE59\uDE80-\uDEB8\uDEC0-\uDEC9\uDF00-\uDF1A\uDF1D-\uDF2B\uDF30-\uDF39\uDF40-\uDF46]|\uD806[\uDC00-\uDC3A\uDCA0-\uDCE9\uDCFF-\uDD06\uDD09\uDD0C-\uDD13\uDD15\uDD16\uDD18-\uDD35\uDD37\uDD38\uDD3B-\uDD43\uDD50-\uDD59\uDDA0-\uDDA7\uDDAA-\uDDD7\uDDDA-\uDDE1\uDDE3\uDDE4\uDE00-\uDE3E\uDE47\uDE50-\uDE99\uDE9D\uDEB0-\uDEF8]|\uD807[\uDC00-\uDC08\uDC0A-\uDC36\uDC38-\uDC40\uDC50-\uDC59\uDC72-\uDC8F\uDC92-\uDCA7\uDCA9-\uDCB6\uDD00-\uDD06\uDD08\uDD09\uDD0B-\uDD36\uDD3A\uDD3C\uDD3D\uDD3F-\uDD47\uDD50-\uDD59\uDD60-\uDD65\uDD67\uDD68\uDD6A-\uDD8E\uDD90\uDD91\uDD93-\uDD98\uDDA0-\uDDA9\uDEE0-\uDEF6\uDF00-\uDF10\uDF12-\uDF3A\uDF3E-\uDF42\uDF50-\uDF59\uDFB0]|\uD808[\uDC00-\uDF99]|\uD809[\uDC00-\uDC6E\uDC80-\uDD43]|\uD80B[\uDF90-\uDFF0]|[\uD80C\uD81C-\uD820\uD822\uD840-\uD868\uD86A-\uD86C\uD86F-\uD872\uD874-\uD879\uD880-\uD883\uD885-\uD887][\uDC00-\uDFFF]|\uD80D[\uDC00-\uDC2F\uDC40-\uDC55]|\uD811[\uDC00-\uDE46]|\uD81A[\uDC00-\uDE38\uDE40-\uDE5E\uDE60-\uDE69\uDE70-\uDEBE\uDEC0-\uDEC9\uDED0-\uDEED\uDEF0-\uDEF4\uDF00-\uDF36\uDF40-\uDF43\uDF50-\uDF59\uDF63-\uDF77\uDF7D-\uDF8F]|\uD81B[\uDE40-\uDE7F\uDF00-\uDF4A\uDF4F-\uDF87\uDF8F-\uDF9F\uDFE0\uDFE1\uDFE3\uDFE4\uDFF0\uDFF1]|\uD821[\uDC00-\uDFF7]|\uD823[\uDC00-\uDCD5\uDD00-\uDD08]|\uD82B[\uDFF0-\uDFF3\uDFF5-\uDFFB\uDFFD\uDFFE]|\uD82C[\uDC00-\uDD22\uDD32\uDD50-\uDD52\uDD55\uDD64-\uDD67\uDD70-\uDEFB]|\uD82F[\uDC00-\uDC6A\uDC70-\uDC7C\uDC80-\uDC88\uDC90-\uDC99\uDC9D\uDC9E]|\uD833[\uDF00-\uDF2D\uDF30-\uDF46]|\uD834[\uDD65-\uDD69\uDD6D-\uDD72\uDD7B-\uDD82\uDD85-\uDD8B\uDDAA-\uDDAD\uDE42-\uDE44]|\uD835[\uDC00-\uDC54\uDC56-\uDC9C\uDC9E\uDC9F\uDCA2\uDCA5\uDCA6\uDCA9-\uDCAC\uDCAE-\uDCB9\uDCBB\uDCBD-\uDCC3\uDCC5-\uDD05\uDD07-\uDD0A\uDD0D-\uDD14\uDD16-\uDD1C\uDD1E-\uDD39\uDD3B-\uDD3E\uDD40-\uDD44\uDD46\uDD4A-\uDD50\uDD52-\uDEA5\uDEA8-\uDEC0\uDEC2-\uDEDA\uDEDC-\uDEFA\uDEFC-\uDF14\uDF16-\uDF34\uDF36-\uDF4E\uDF50-\uDF6E\uDF70-\uDF88\uDF8A-\uDFA8\uDFAA-\uDFC2\uDFC4-\uDFCB\uDFCE-\uDFFF]|\uD836[\uDE00-\uDE36\uDE3B-\uDE6C\uDE75\uDE84\uDE9B-\uDE9F\uDEA1-\uDEAF]|\uD837[\uDF00-\uDF1E\uDF25-\uDF2A]|\uD838[\uDC00-\uDC06\uDC08-\uDC18\uDC1B-\uDC21\uDC23\uDC24\uDC26-\uDC2A\uDC30-\uDC6D\uDC8F\uDD00-\uDD2C\uDD30-\uDD3D\uDD40-\uDD49\uDD4E\uDE90-\uDEAE\uDEC0-\uDEF9]|\uD839[\uDCD0-\uDCF9\uDFE0-\uDFE6\uDFE8-\uDFEB\uDFED\uDFEE\uDFF0-\uDFFE]|\uD83A[\uDC00-\uDCC4\uDCD0-\uDCD6\uDD00-\uDD4B\uDD50-\uDD59]|\uD83B[\uDE00-\uDE03\uDE05-\uDE1F\uDE21\uDE22\uDE24\uDE27\uDE29-\uDE32\uDE34-\uDE37\uDE39\uDE3B\uDE42\uDE47\uDE49\uDE4B\uDE4D-\uDE4F\uDE51\uDE52\uDE54\uDE57\uDE59\uDE5B\uDE5D\uDE5F\uDE61\uDE62\uDE64\uDE67-\uDE6A\uDE6C-\uDE72\uDE74-\uDE77\uDE79-\uDE7C\uDE7E\uDE80-\uDE89\uDE8B-\uDE9B\uDEA1-\uDEA3\uDEA5-\uDEA9\uDEAB-\uDEBB]|\uD83E[\uDFF0-\uDFF9]|\uD869[\uDC00-\uDEDF\uDF00-\uDFFF]|\uD86D[\uDC00-\uDF39\uDF40-\uDFFF]|\uD86E[\uDC00-\uDC1D\uDC20-\uDFFF]|\uD873[\uDC00-\uDEA1\uDEB0-\uDFFF]|\uD87A[\uDC00-\uDFE0]|\uD87E[\uDC00-\uDE1D]|\uD884[\uDC00-\uDF4A\uDF50-\uDFFF]|\uD888[\uDC00-\uDFAF]|\uDB40[\uDD00-\uDDEF])*)>/, function (match) {
      if (!XRegExp.isInstalled('namespacing') && (match[1] === 'length' || match[1] === '__proto__')) {
        throw new SyntaxError("Cannot use reserved word as capture name ".concat(match[0]));
      }
      if (this.captureNames.includes(match[1])) {
        throw new SyntaxError("Cannot use same name for multiple groups ".concat(match[0]));
      }
      this.captureNames.push(match[1]);
      this.hasNamedCapture = true;
      return '(';
    }, {
      leadChar: '('
    });

    /*
     * Capturing group; match the opening parenthesis only. Required for support of named capturing
     * groups. Also adds named capture only mode (flag n).
     */
    XRegExp.addToken(/\((?!\?)/, function (match, scope, flags) {
      if (flags.includes('n')) {
        return '(?:';
      }
      this.captureNames.push(null);
      return '(';
    }, {
      optionalFlags: 'n',
      leadChar: '('
    });

    /*!
     * XRegExp.build 5.1.1
     * <xregexp.com>
     * Steven Levithan (c) 2012-present MIT License
     */

    var build = (function (XRegExp) {
      var REGEX_DATA = 'xregexp';
      var subParts = /(\()(?!\?)|\\([1-9]\d*)|\\[\s\S]|\[(?:[^\\\]]|\\[\s\S])*\]/g;
      var parts = XRegExp.union([/\({{([\w$]+)}}\)|{{([\w$]+)}}/, subParts], 'g', {
        conjunction: 'or'
      });

      /**
       * Strips a leading `^` and trailing unescaped `$`, if both are present.
       *
       * @private
       * @param {String} pattern Pattern to process.
       * @returns {String} Pattern with edge anchors removed.
       */
      function deanchor(pattern) {
        // Allow any number of empty noncapturing groups before/after anchors, because regexes
        // built/generated by XRegExp sometimes include them
        var leadingAnchor = /^(?:\(\?:\))*\^/;
        var trailingAnchor = /\$(?:\(\?:\))*$/;
        if (leadingAnchor.test(pattern) && trailingAnchor.test(pattern) &&
        // Ensure that the trailing `$` isn't escaped
        trailingAnchor.test(pattern.replace(/\\[\s\S]/g, ''))) {
          return pattern.replace(leadingAnchor, '').replace(trailingAnchor, '');
        }
        return pattern;
      }

      /**
       * Converts the provided value to an XRegExp. Native RegExp flags are not preserved.
       *
       * @private
       * @param {String|RegExp} value Value to convert.
       * @param {Boolean} [addFlagX] Whether to apply the `x` flag in cases when `value` is not
       *   already a regex generated by XRegExp
       * @returns {RegExp} XRegExp object with XRegExp syntax applied.
       */
      function asXRegExp(value, addFlagX) {
        var flags = addFlagX ? 'x' : '';
        return XRegExp.isRegExp(value) ? value[REGEX_DATA] && value[REGEX_DATA].captureNames ?
        // Don't recompile, to preserve capture names
        value :
        // Recompile as XRegExp
        XRegExp(value.source, flags) :
        // Compile string as XRegExp
        XRegExp(value, flags);
      }
      function interpolate(substitution) {
        return substitution instanceof RegExp ? substitution : XRegExp.escape(substitution);
      }
      function reduceToSubpatternsObject(subpatterns, interpolated, subpatternIndex) {
        subpatterns["subpattern".concat(subpatternIndex)] = interpolated;
        return subpatterns;
      }
      function embedSubpatternAfter(raw, subpatternIndex, rawLiterals) {
        var hasSubpattern = subpatternIndex < rawLiterals.length - 1;
        return raw + (hasSubpattern ? "{{subpattern".concat(subpatternIndex, "}}") : '');
      }

      /**
       * Provides tagged template literals that create regexes with XRegExp syntax and flags. The
       * provided pattern is handled as a raw string, so backslashes don't need to be escaped.
       *
       * Interpolation of strings and regexes shares the features of `XRegExp.build`. Interpolated
       * patterns are treated as atomic units when quantified, interpolated strings have their special
       * characters escaped, a leading `^` and trailing unescaped `$` are stripped from interpolated
       * regexes if both are present, and any backreferences within an interpolated regex are
       * rewritten to work within the overall pattern.
       *
       * @memberOf XRegExp
       * @param {String} [flags] Any combination of XRegExp flags.
       * @returns {Function} Handler for template literals that construct regexes with XRegExp syntax.
       * @example
       *
       * XRegExp.tag()`\b\w+\b`.test('word'); // -> true
       *
       * const hours = /1[0-2]|0?[1-9]/;
       * const minutes = /(?<minutes>[0-5][0-9])/;
       * const time = XRegExp.tag('x')`\b ${hours} : ${minutes} \b`;
       * time.test('10:59'); // -> true
       * XRegExp.exec('10:59', time).groups.minutes; // -> '59'
       *
       * const backref1 = /(a)\1/;
       * const backref2 = /(b)\1/;
       * XRegExp.tag()`${backref1}${backref2}`.test('aabb'); // -> true
       */
      XRegExp.tag = function (flags) {
        return function (literals) {
          for (var _len = arguments.length, substitutions = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
            substitutions[_key - 1] = arguments[_key];
          }
          var subpatterns = substitutions.map(interpolate).reduce(reduceToSubpatternsObject, {});
          var pattern = literals.raw.map(embedSubpatternAfter).join('');
          return XRegExp.build(pattern, subpatterns, flags);
        };
      };

      /**
       * Builds regexes using named subpatterns, for readability and pattern reuse. Backreferences in
       * the outer pattern and provided subpatterns are automatically renumbered to work correctly.
       * Native flags used by provided subpatterns are ignored in favor of the `flags` argument.
       *
       * @memberOf XRegExp
       * @param {String} pattern XRegExp pattern using `{{name}}` for embedded subpatterns. Allows
       *   `({{name}})` as shorthand for `(?<name>{{name}})`. Patterns cannot be embedded within
       *   character classes.
       * @param {Object} subs Lookup object for named subpatterns. Values can be strings or regexes. A
       *   leading `^` and trailing unescaped `$` are stripped from subpatterns, if both are present.
       * @param {String} [flags] Any combination of XRegExp flags.
       * @returns {RegExp} Regex with interpolated subpatterns.
       * @example
       *
       * const time = XRegExp.build('(?x)^ {{hours}} ({{minutes}}) $', {
       *   hours: XRegExp.build('{{h12}} : | {{h24}}', {
       *     h12: /1[0-2]|0?[1-9]/,
       *     h24: /2[0-3]|[01][0-9]/
       *   }, 'x'),
       *   minutes: /^[0-5][0-9]$/
       * });
       * time.test('10:59'); // -> true
       * XRegExp.exec('10:59', time).groups.minutes; // -> '59'
       */
      XRegExp.build = function (pattern, subs, flags) {
        flags = flags || '';
        // Used with `asXRegExp` calls for `pattern` and subpatterns in `subs`, to work around how
        // some browsers convert `RegExp('\n')` to a regex that contains the literal characters `\`
        // and `n`. See more details at <https://github.com/slevithan/xregexp/pull/163>.
        var addFlagX = flags.includes('x');
        var inlineFlags = /^\(\?([\w$]+)\)/.exec(pattern);
        // Add flags within a leading mode modifier to the overall pattern's flags
        if (inlineFlags) {
          flags = XRegExp._clipDuplicates(flags + inlineFlags[1]);
        }
        var data = {};
        for (var p in subs) {
          if (subs.hasOwnProperty(p)) {
            // Passing to XRegExp enables extended syntax and ensures independent validity,
            // lest an unescaped `(`, `)`, `[`, or trailing `\` breaks the `(?:)` wrapper. For
            // subpatterns provided as native regexes, it dies on octals and adds the property
            // used to hold extended regex instance data, for simplicity.
            var sub = asXRegExp(subs[p], addFlagX);
            data[p] = {
              // Deanchoring allows embedding independently useful anchored regexes. If you
              // really need to keep your anchors, double them (i.e., `^^...$$`).
              pattern: deanchor(sub.source),
              names: sub[REGEX_DATA].captureNames || []
            };
          }
        }

        // Passing to XRegExp dies on octals and ensures the outer pattern is independently valid;
        // helps keep this simple. Named captures will be put back.
        var patternAsRegex = asXRegExp(pattern, addFlagX);

        // 'Caps' is short for 'captures'
        var numCaps = 0;
        var numPriorCaps;
        var numOuterCaps = 0;
        var outerCapsMap = [0];
        var outerCapNames = patternAsRegex[REGEX_DATA].captureNames || [];
        var output = patternAsRegex.source.replace(parts, function ($0, $1, $2, $3, $4) {
          var subName = $1 || $2;
          var capName;
          var intro;
          var localCapIndex;
          // Named subpattern
          if (subName) {
            if (!data.hasOwnProperty(subName)) {
              throw new ReferenceError("Undefined property ".concat($0));
            }
            // Named subpattern was wrapped in a capturing group
            if ($1) {
              capName = outerCapNames[numOuterCaps];
              outerCapsMap[++numOuterCaps] = ++numCaps;
              // If it's a named group, preserve the name. Otherwise, use the subpattern name
              // as the capture name
              intro = "(?<".concat(capName || subName, ">");
            } else {
              intro = '(?:';
            }
            numPriorCaps = numCaps;
            var rewrittenSubpattern = data[subName].pattern.replace(subParts, function (match, paren, backref) {
              // Capturing group
              if (paren) {
                capName = data[subName].names[numCaps - numPriorCaps];
                ++numCaps;
                // If the current capture has a name, preserve the name
                if (capName) {
                  return "(?<".concat(capName, ">");
                }
                // Backreference
              } else if (backref) {
                localCapIndex = +backref - 1;
                // Rewrite the backreference
                return data[subName].names[localCapIndex] ? // Need to preserve the backreference name in case using flag `n`
                "\\k<".concat(data[subName].names[localCapIndex], ">") : "\\".concat(+backref + numPriorCaps);
              }
              return match;
            });
            return "".concat(intro).concat(rewrittenSubpattern, ")");
          }
          // Capturing group
          if ($3) {
            capName = outerCapNames[numOuterCaps];
            outerCapsMap[++numOuterCaps] = ++numCaps;
            // If the current capture has a name, preserve the name
            if (capName) {
              return "(?<".concat(capName, ">");
            }
            // Backreference
          } else if ($4) {
            localCapIndex = +$4 - 1;
            // Rewrite the backreference
            return outerCapNames[localCapIndex] ? // Need to preserve the backreference name in case using flag `n`
            "\\k<".concat(outerCapNames[localCapIndex], ">") : "\\".concat(outerCapsMap[+$4]);
          }
          return $0;
        });
        return XRegExp(output, flags);
      };
    });

    /*!
     * XRegExp.matchRecursive 5.1.1
     * <xregexp.com>
     * Steven Levithan (c) 2009-present MIT License
     */

    var matchRecursive = (function (XRegExp) {
      /**
       * Returns a match detail object composed of the provided values.
       *
       * @private
       */
      function row(name, value, start, end) {
        return {
          name,
          value,
          start,
          end
        };
      }

      /**
       * Returns an array of match strings between outermost left and right delimiters, or an array of
       * objects with detailed match parts and position data. By default, an error is thrown if
       * delimiters are unbalanced within the subject string.
       *
       * @memberOf XRegExp
       * @param {String} str String to search.
       * @param {String} left Left delimiter as an XRegExp pattern.
       * @param {String} right Right delimiter as an XRegExp pattern.
       * @param {String} [flags] Any combination of XRegExp flags, used for the left and right delimiters.
       * @param {Object} [options] Options object with optional properties:
       *   - `valueNames` {Array} Providing `valueNames` changes the return value from an array of
       *     matched strings to an array of objects that provide the value and start/end positions
       *     for the matched strings as well as the matched delimiters and unmatched string segments.
       *     To use this extended information mode, provide an array of 4 strings that name the parts
       *     to be returned:
       *     1. String segments outside of (before, between, and after) matches.
       *     2. Matched outermost left delimiters.
       *     3. Matched text between the outermost left and right delimiters.
       *     4. Matched outermost right delimiters.
       *     Taken together, these parts include the entire subject string if used with flag g.
       *     Use `null` for any of these values to omit unneeded parts from the returned results.
       *   - `escapeChar` {String} Single char used to escape delimiters within the subject string.
       *   - `unbalanced` {String} Handling mode for unbalanced delimiters. Options are:
       *     - 'error' - throw (default)
       *     - 'skip' - unbalanced delimiters are treated as part of the text between delimiters, and
       *       searches continue at the end of the unbalanced delimiter.
       *     - 'skip-lazy' - unbalanced delimiters are treated as part of the text between delimiters,
       *       and searches continue one character after the start of the unbalanced delimiter.
       * @returns {Array} Array of matches, or an empty array.
       * @example
       *
       * // Basic usage
       * const str1 = '(t((e))s)t()(ing)';
       * XRegExp.matchRecursive(str1, '\\(', '\\)', 'g');
       * // -> ['t((e))s', '', 'ing']
       *
       * // Extended information mode with valueNames
       * const str2 = 'Here is <div> <div>an</div></div> example';
       * XRegExp.matchRecursive(str2, '<div\\s*>', '</div>', 'gi', {
       *   valueNames: ['between', 'left', 'match', 'right']
       * });
       * // -> [
       * // {name: 'between', value: 'Here is ',       start: 0,  end: 8},
       * // {name: 'left',    value: '<div>',          start: 8,  end: 13},
       * // {name: 'match',   value: ' <div>an</div>', start: 13, end: 27},
       * // {name: 'right',   value: '</div>',         start: 27, end: 33},
       * // {name: 'between', value: ' example',       start: 33, end: 41}
       * // ]
       *
       * // Omitting unneeded parts with null valueNames, and using escapeChar
       * const str3 = '...{1}.\\{{function(x,y){return {y:x}}}';
       * XRegExp.matchRecursive(str3, '{', '}', 'g', {
       *   valueNames: ['literal', null, 'value', null],
       *   escapeChar: '\\'
       * });
       * // -> [
       * // {name: 'literal', value: '...',  start: 0, end: 3},
       * // {name: 'value',   value: '1',    start: 4, end: 5},
       * // {name: 'literal', value: '.\\{', start: 6, end: 9},
       * // {name: 'value',   value: 'function(x,y){return {y:x}}', start: 10, end: 37}
       * // ]
       *
       * // Sticky mode via flag y
       * const str4 = '<1><<<2>>><3>4<5>';
       * XRegExp.matchRecursive(str4, '<', '>', 'gy');
       * // -> ['1', '<<2>>', '3']
       *
       * // Skipping unbalanced delimiters instead of erroring
       * const str5 = 'Here is <div> <div>an</div> unbalanced example';
       * XRegExp.matchRecursive(str5, '<div\\s*>', '</div>', 'gi', {
       *     unbalanced: 'skip'
       * });
       * // -> ['an']
       */
      XRegExp.matchRecursive = function (str, left, right, flags, options) {
        flags = flags || '';
        options = options || {};
        var global = flags.includes('g');
        var sticky = flags.includes('y');
        // Flag `y` is handled manually
        var basicFlags = flags.replace(/y/g, '');
        left = XRegExp(left, basicFlags);
        right = XRegExp(right, basicFlags);
        var esc;
        var _options = options,
          escapeChar = _options.escapeChar;
        if (escapeChar) {
          if (escapeChar.length > 1) {
            throw new Error('Cannot use more than one escape character');
          }
          escapeChar = XRegExp.escape(escapeChar);
          // Example of concatenated `esc` regex:
          // `escapeChar`: '%'
          // `left`: '<'
          // `right`: '>'
          // Regex is: /(?:%[\S\s]|(?:(?!<|>)[^%])+)+/
          esc = new RegExp("(?:".concat(escapeChar, "[\\S\\s]|(?:(?!").concat(
          // Using `XRegExp.union` safely rewrites backreferences in `left` and `right`.
          // Intentionally not passing `basicFlags` to `XRegExp.union` since any syntax
          // transformation resulting from those flags was already applied to `left` and
          // `right` when they were passed through the XRegExp constructor above.
          XRegExp.union([left, right], '', {
            conjunction: 'or'
          }).source, ")[^").concat(escapeChar, "])+)+"),
          // Flags `dgy` not needed here
          flags.replace(XRegExp._hasNativeFlag('s') ? /[^imsu]/g : /[^imu]/g, ''));
        }
        var openTokens = 0;
        var delimStart = 0;
        var delimEnd = 0;
        var lastOuterEnd = 0;
        var outerStart;
        var innerStart;
        var leftMatch;
        var rightMatch;
        var vN = options.valueNames;
        var output = [];
        while (true) {
          // If using an escape character, advance to the delimiter's next starting position,
          // skipping any escaped characters in between
          if (escapeChar) {
            delimEnd += (XRegExp.exec(str, esc, delimEnd, 'sticky') || [''])[0].length;
          }
          leftMatch = XRegExp.exec(str, left, delimEnd);
          rightMatch = XRegExp.exec(str, right, delimEnd);
          // Keep the leftmost match only
          if (leftMatch && rightMatch) {
            if (leftMatch.index <= rightMatch.index) {
              rightMatch = null;
            } else {
              leftMatch = null;
            }
          }

          // Paths (LM: leftMatch, RM: rightMatch, OT: openTokens):
          // LM | RM | OT | Result
          // 1  | 0  | 1  | loop
          // 1  | 0  | 0  | loop
          // 0  | 1  | 1  | loop
          // 0  | 1  | 0  | throw
          // 0  | 0  | 1  | throw
          // 0  | 0  | 0  | break
          // The paths above don't include the sticky mode special case. The loop ends after the
          // first completed match if not `global`.
          if (leftMatch || rightMatch) {
            delimStart = (leftMatch || rightMatch).index;
            delimEnd = delimStart + (leftMatch || rightMatch)[0].length;
          } else if (!openTokens) {
            break;
          }
          if (sticky && !openTokens && delimStart > lastOuterEnd) {
            break;
          }
          if (leftMatch) {
            if (!openTokens) {
              outerStart = delimStart;
              innerStart = delimEnd;
            }
            openTokens += 1;
          } else if (rightMatch && openTokens) {
            openTokens -= 1;
            if (!openTokens) {
              if (vN) {
                if (vN[0] && outerStart > lastOuterEnd) {
                  output.push(row(vN[0], str.slice(lastOuterEnd, outerStart), lastOuterEnd, outerStart));
                }
                if (vN[1]) {
                  output.push(row(vN[1], str.slice(outerStart, innerStart), outerStart, innerStart));
                }
                if (vN[2]) {
                  output.push(row(vN[2], str.slice(innerStart, delimStart), innerStart, delimStart));
                }
                if (vN[3]) {
                  output.push(row(vN[3], str.slice(delimStart, delimEnd), delimStart, delimEnd));
                }
              } else {
                output.push(str.slice(innerStart, delimStart));
              }
              lastOuterEnd = delimEnd;
              if (!global) {
                break;
              }
            }
            // Found unbalanced delimiter
          } else {
            var unbalanced = options.unbalanced || 'error';
            if (unbalanced === 'skip' || unbalanced === 'skip-lazy') {
              if (rightMatch) {
                rightMatch = null;
                // No `leftMatch` for unbalanced left delimiter because we've reached the string end
              } else {
                if (unbalanced === 'skip') {
                  var outerStartDelimLength = XRegExp.exec(str, left, outerStart, 'sticky')[0].length;
                  delimEnd = outerStart + (outerStartDelimLength || 1);
                } else {
                  delimEnd = outerStart + 1;
                }
                openTokens = 0;
              }
            } else if (unbalanced === 'error') {
              var delimSide = rightMatch ? 'right' : 'left';
              var errorPos = rightMatch ? delimStart : outerStart;
              throw new Error("Unbalanced ".concat(delimSide, " delimiter found in string at position ").concat(errorPos));
            } else {
              throw new Error("Unsupported value for unbalanced: ".concat(unbalanced));
            }
          }

          // If the delimiter matched an empty string, avoid an infinite loop
          if (delimStart === delimEnd) {
            delimEnd += 1;
          }
        }
        if (global && output.length > 0 && !sticky && vN && vN[0] && str.length > lastOuterEnd) {
          output.push(row(vN[0], str.slice(lastOuterEnd), lastOuterEnd, str.length));
        }
        return output;
      };
    });

    function _createForOfIteratorHelper$1(o, allowArrayLike) { var it = typeof Symbol !== "undefined" && o[Symbol.iterator] || o["@@iterator"]; if (!it) { if (Array.isArray(o) || (it = _unsupportedIterableToArray$1(o)) || allowArrayLike && o && typeof o.length === "number") { if (it) o = it; var i = 0; var F = function F() {}; return { s: F, n: function n() { if (i >= o.length) return { done: true }; return { done: false, value: o[i++] }; }, e: function e(_e) { throw _e; }, 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 normalCompletion = true, didErr = false, err; return { s: function s() { it = it.call(o); }, n: function n() { var step = it.next(); normalCompletion = step.done; return step; }, e: function e(_e2) { didErr = true; err = _e2; }, f: function f() { try { if (!normalCompletion && it.return != null) it.return(); } finally { if (didErr) throw err; } } }; }
    function _unsupportedIterableToArray$1(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray$1(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray$1(o, minLen); }
    function _arrayLikeToArray$1(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; return arr2; }
    /*!
     * XRegExp Unicode Base 5.1.1
     * <xregexp.com>
     * Steven Levithan (c) 2008-present MIT License
     */

    var unicodeBase = (function (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;
        XRegExp.forEach(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) {
          combined = "[".concat(item.bmp, "]").concat(item.astral ? '|' : '');
        }
        if (item.astral) {
          combined += item.astral;
        }
        if (item.isBmpLast && item.bmp) {
          combined += "".concat(item.astral ? '|' : '', "[").concat(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 = _slicedToArray$1(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 = flags.includes('A');
        // 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)) {
            throw new ReferenceError("".concat(ERR_UNKNOWN_REF + fullToken, " -> ").concat(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$1(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];
      };
    });

    var categories = [{
      'name': 'C',
      'alias': 'Other',
      'isBmpLast': true,
      'bmp': "\0-\x1F\x7F-\x9F\xAD\u0378\u0379\u0380-\u0383\u038B\u038D\u03A2\u0530\u0557\u0558\u058B\u058C\u0590\u05C8-\u05CF\u05EB-\u05EE\u05F5-\u0605\u061C\u06DD\u070E\u070F\u074B\u074C\u07B2-\u07BF\u07FB\u07FC\u082E\u082F\u083F\u085C\u085D\u085F\u086B-\u086F\u088F-\u0897\u08E2\u0984\u098D\u098E\u0991\u0992\u09A9\u09B1\u09B3-\u09B5\u09BA\u09BB\u09C5\u09C6\u09C9\u09CA\u09CF-\u09D6\u09D8-\u09DB\u09DE\u09E4\u09E5\u09FF\u0A00\u0A04\u0A0B-\u0A0E\u0A11\u0A12\u0A29\u0A31\u0A34\u0A37\u0A3A\u0A3B\u0A3D\u0A43-\u0A46\u0A49\u0A4A\u0A4E-\u0A50\u0A52-\u0A58\u0A5D\u0A5F-\u0A65\u0A77-\u0A80\u0A84\u0A8E\u0A92\u0AA9\u0AB1\u0AB4\u0ABA\u0ABB\u0AC6\u0ACA\u0ACE\u0ACF\u0AD1-\u0ADF\u0AE4\u0AE5\u0AF2-\u0AF8\u0B00\u0B04\u0B0D\u0B0E\u0B11\u0B12\u0B29\u0B31\u0B34\u0B3A\u0B3B\u0B45\u0B46\u0B49\u0B4A\u0B4E-\u0B54\u0B58-\u0B5B\u0B5E\u0B64\u0B65\u0B78-\u0B81\u0B84\u0B8B-\u0B8D\u0B91\u0B96-\u0B98\u0B9B\u0B9D\u0BA0-\u0BA2\u0BA5-\u0BA7\u0BAB-\u0BAD\u0BBA-\u0BBD\u0BC3-\u0BC5\u0BC9\u0BCE\u0BCF\u0BD1-\u0BD6\u0BD8-\u0BE5\u0BFB-\u0BFF\u0C0D\u0C11\u0C29\u0C3A\u0C3B\u0C45\u0C49\u0C4E-\u0C54\u0C57\u0C5B\u0C5C\u0C5E\u0C5F\u0C64\u0C65\u0C70-\u0C76\u0C8D\u0C91\u0CA9\u0CB4\u0CBA\u0CBB\u0CC5\u0CC9\u0CCE-\u0CD4\u0CD7-\u0CDC\u0CDF\u0CE4\u0CE5\u0CF0\u0CF3-\u0CFF\u0D0D\u0D11\u0D45\u0D49\u0D50-\u0D53\u0D64\u0D65\u0D80\u0D84\u0D97-\u0D99\u0DB2\u0DBC\u0DBE\u0DBF\u0DC7-\u0DC9\u0DCB-\u0DCE\u0DD5\u0DD7\u0DE0-\u0DE5\u0DF0\u0DF1\u0DF5-\u0E00\u0E3B-\u0E3E\u0E5C-\u0E80\u0E83\u0E85\u0E8B\u0EA4\u0EA6\u0EBE\u0EBF\u0EC5\u0EC7\u0ECE\u0ECF\u0EDA\u0EDB\u0EE0-\u0EFF\u0F48\u0F6D-\u0F70\u0F98\u0FBD\u0FCD\u0FDB-\u0FFF\u10C6\u10C8-\u10CC\u10CE\u10CF\u1249\u124E\u124F\u1257\u1259\u125E\u125F\u1289\u128E\u128F\u12B1\u12B6\u12B7\u12BF\u12C1\u12C6\u12C7\u12D7\u1311\u1316\u1317\u135B\u135C\u137D-\u137F\u139A-\u139F\u13F6\u13F7\u13FE\u13FF\u169D-\u169F\u16F9-\u16FF\u1716-\u171E\u1737-\u173F\u1754-\u175F\u176D\u1771\u1774-\u177F\u17DE\u17DF\u17EA-\u17EF\u17FA-\u17FF\u180E\u181A-\u181F\u1879-\u187F\u18AB-\u18AF\u18F6-\u18FF\u191F\u192C-\u192F\u193C-\u193F\u1941-\u1943\u196E\u196F\u1975-\u197F\u19AC-\u19AF\u19CA-\u19CF\u19DB-\u19DD\u1A1C\u1A1D\u1A5F\u1A7D\u1A7E\u1A8A-\u1A8F\u1A9A-\u1A9F\u1AAE\u1AAF\u1ACF-\u1AFF\u1B4D-\u1B4F\u1B7F\u1BF4-\u1BFB\u1C38-\u1C3A\u1C4A-\u1C4C\u1C89-\u1C8F\u1CBB\u1CBC\u1CC8-\u1CCF\u1CFB-\u1CFF\u1F16\u1F17\u1F1E\u1F1F\u1F46\u1F47\u1F4E\u1F4F\u1F58\u1F5A\u1F5C\u1F5E\u1F7E\u1F7F\u1FB5\u1FC5\u1FD4\u1FD5\u1FDC\u1FF0\u1FF1\u1FF5\u1FFF\u200B-\u200F\u202A-\u202E\u2060-\u206F\u2072\u2073\u208F\u209D-\u209F\u20C1-\u20CF\u20F1-\u20FF\u218C-\u218F\u2427-\u243F\u244B-\u245F\u2B74\u2B75\u2B96\u2CF4-\u2CF8\u2D26\u2D28-\u2D2C\u2D2E\u2D2F\u2D68-\u2D6E\u2D71-\u2D7E\u2D97-\u2D9F\u2DA7\u2DAF\u2DB7\u2DBF\u2DC7\u2DCF\u2DD7\u2DDF\u2E5E-\u2E7F\u2E9A\u2EF4-\u2EFF\u2FD6-\u2FEF\u2FFC-\u2FFF\u3040\u3097\u3098\u3100-\u3104\u3130\u318F\u31E4-\u31EF\u321F\uA48D-\uA48F\uA4C7-\uA4CF\uA62C-\uA63F\uA6F8-\uA6FF\uA7CB-\uA7CF\uA7D2\uA7D4\uA7DA-\uA7F1\uA82D-\uA82F\uA83A-\uA83F\uA878-\uA87F\uA8C6-\uA8CD\uA8DA-\uA8DF\uA954-\uA95E\uA97D-\uA97F\uA9CE\uA9DA-\uA9DD\uA9FF\uAA37-\uAA3F\uAA4E\uAA4F\uAA5A\uAA5B\uAAC3-\uAADA\uAAF7-\uAB00\uAB07\uAB08\uAB0F\uAB10\uAB17-\uAB1F\uAB27\uAB2F\uAB6C-\uAB6F\uABEE\uABEF\uABFA-\uABFF\uD7A4-\uD7AF\uD7C7-\uD7CA\uD7FC-\uF8FF\uFA6E\uFA6F\uFADA-\uFAFF\uFB07-\uFB12\uFB18-\uFB1C\uFB37\uFB3D\uFB3F\uFB42\uFB45\uFBC3-\uFBD2\uFD90\uFD91\uFDC8-\uFDCE\uFDD0-\uFDEF\uFE1A-\uFE1F\uFE53\uFE67\uFE6C-\uFE6F\uFE75\uFEFD-\uFF00\uFFBF-\uFFC1\uFFC8\uFFC9\uFFD0\uFFD1\uFFD8\uFFD9\uFFDD-\uFFDF\uFFE7\uFFEF-\uFFFB\uFFFE\uFFFF",
      'astral': "\uD800[\uDC0C\uDC27\uDC3B\uDC3E\uDC4E\uDC4F\uDC5E-\uDC7F\uDCFB-\uDCFF\uDD03-\uDD06\uDD34-\uDD36\uDD8F\uDD9D-\uDD9F\uDDA1-\uDDCF\uDDFE-\uDE7F\uDE9D-\uDE9F\uDED1-\uDEDF\uDEFC-\uDEFF\uDF24-\uDF2C\uDF4B-\uDF4F\uDF7B-\uDF7F\uDF9E\uDFC4-\uDFC7\uDFD6-\uDFFF]|\uD801[\uDC9E\uDC9F\uDCAA-\uDCAF\uDCD4-\uDCD7\uDCFC-\uDCFF\uDD28-\uDD2F\uDD64-\uDD6E\uDD7B\uDD8B\uDD93\uDD96\uDDA2\uDDB2\uDDBA\uDDBD-\uDDFF\uDF37-\uDF3F\uDF56-\uDF5F\uDF68-\uDF7F\uDF86\uDFB1\uDFBB-\uDFFF]|\uD802[\uDC06\uDC07\uDC09\uDC36\uDC39-\uDC3B\uDC3D\uDC3E\uDC56\uDC9F-\uDCA6\uDCB0-\uDCDF\uDCF3\uDCF6-\uDCFA\uDD1C-\uDD1E\uDD3A-\uDD3E\uDD40-\uDD7F\uDDB8-\uDDBB\uDDD0\uDDD1\uDE04\uDE07-\uDE0B\uDE14\uDE18\uDE36\uDE37\uDE3B-\uDE3E\uDE49-\uDE4F\uDE59-\uDE5F\uDEA0-\uDEBF\uDEE7-\uDEEA\uDEF7-\uDEFF\uDF36-\uDF38\uDF56\uDF57\uDF73-\uDF77\uDF92-\uDF98\uDF9D-\uDFA8\uDFB0-\uDFFF]|\uD803[\uDC49-\uDC7F\uDCB3-\uDCBF\uDCF3-\uDCF9\uDD28-\uDD2F\uDD3A-\uDE5F\uDE7F\uDEAA\uDEAE\uDEAF\uDEB2-\uDEFF\uDF28-\uDF2F\uDF5A-\uDF6F\uDF8A-\uDFAF\uDFCC-\uDFDF\uDFF7-\uDFFF]|\uD804[\uDC4E-\uDC51\uDC76-\uDC7E\uDCBD\uDCC3-\uDCCF\uDCE9-\uDCEF\uDCFA-\uDCFF\uDD35\uDD48-\uDD4F\uDD77-\uDD7F\uDDE0\uDDF5-\uDDFF\uDE12\uDE3F-\uDE7F\uDE87\uDE89\uDE8E\uDE9E\uDEAA-\uDEAF\uDEEB-\uDEEF\uDEFA-\uDEFF\uDF04\uDF0D\uDF0E\uDF11\uDF12\uDF29\uDF31\uDF34\uDF3A\uDF45\uDF46\uDF49\uDF4A\uDF4E\uDF4F\uDF51-\uDF56\uDF58-\uDF5C\uDF64\uDF65\uDF6D-\uDF6F\uDF75-\uDFFF]|\uD805[\uDC5C\uDC62-\uDC7F\uDCC8-\uDCCF\uDCDA-\uDD7F\uDDB6\uDDB7\uDDDE-\uDDFF\uDE45-\uDE4F\uDE5A-\uDE5F\uDE6D-\uDE7F\uDEBA-\uDEBF\uDECA-\uDEFF\uDF1B\uDF1C\uDF2C-\uDF2F\uDF47-\uDFFF]|\uD806[\uDC3C-\uDC9F\uDCF3-\uDCFE\uDD07\uDD08\uDD0A\uDD0B\uDD14\uDD17\uDD36\uDD39\uDD3A\uDD47-\uDD4F\uDD5A-\uDD9F\uDDA8\uDDA9\uDDD8\uDDD9\uDDE5-\uDDFF\uDE48-\uDE4F\uDEA3-\uDEAF\uDEF9-\uDFFF]|\uD807[\uDC09\uDC37\uDC46-\uDC4F\uDC6D-\uDC6F\uDC90\uDC91\uDCA8\uDCB7-\uDCFF\uDD07\uDD0A\uDD37-\uDD39\uDD3B\uDD3E\uDD48-\uDD4F\uDD5A-\uDD5F\uDD66\uDD69\uDD8F\uDD92\uDD99-\uDD9F\uDDAA-\uDEDF\uDEF9-\uDFAF\uDFB1-\uDFBF\uDFF2-\uDFFE]|\uD808[\uDF9A-\uDFFF]|\uD809[\uDC6F\uDC75-\uDC7F\uDD44-\uDFFF]|[\uD80A\uD80E-\uD810\uD812-\uD819\uD824-\uD82A\uD82D\uD82E\uD830-\uD832\uD83F\uD87B-\uD87D\uD87F\uD885-\uDB3F\uDB41-\uDBFF][\uDC00-\uDFFF]|\uD80B[\uDC00-\uDF8F\uDFF3-\uDFFF]|\uD80D[\uDC2F-\uDFFF]|\uD811[\uDE47-\uDFFF]|\uD81A[\uDE39-\uDE3F\uDE5F\uDE6A-\uDE6D\uDEBF\uDECA-\uDECF\uDEEE\uDEEF\uDEF6-\uDEFF\uDF46-\uDF4F\uDF5A\uDF62\uDF78-\uDF7C\uDF90-\uDFFF]|\uD81B[\uDC00-\uDE3F\uDE9B-\uDEFF\uDF4B-\uDF4E\uDF88-\uDF8E\uDFA0-\uDFDF\uDFE5-\uDFEF\uDFF2-\uDFFF]|\uD821[\uDFF8-\uDFFF]|\uD823[\uDCD6-\uDCFF\uDD09-\uDFFF]|\uD82B[\uDC00-\uDFEF\uDFF4\uDFFC\uDFFF]|\uD82C[\uDD23-\uDD4F\uDD53-\uDD63\uDD68-\uDD6F\uDEFC-\uDFFF]|\uD82F[\uDC6B-\uDC6F\uDC7D-\uDC7F\uDC89-\uDC8F\uDC9A\uDC9B\uDCA0-\uDFFF]|\uD833[\uDC00-\uDEFF\uDF2E\uDF2F\uDF47-\uDF4F\uDFC4-\uDFFF]|\uD834[\uDCF6-\uDCFF\uDD27\uDD28\uDD73-\uDD7A\uDDEB-\uDDFF\uDE46-\uDEDF\uDEF4-\uDEFF\uDF57-\uDF5F\uDF79-\uDFFF]|\uD835[\uDC55\uDC9D\uDCA0\uDCA1\uDCA3\uDCA4\uDCA7\uDCA8\uDCAD\uDCBA\uDCBC\uDCC4\uDD06\uDD0B\uDD0C\uDD15\uDD1D\uDD3A\uDD3F\uDD45\uDD47-\uDD49\uDD51\uDEA6\uDEA7\uDFCC\uDFCD]|\uD836[\uDE8C-\uDE9A\uDEA0\uDEB0-\uDFFF]|\uD837[\uDC00-\uDEFF\uDF1F-\uDFFF]|\uD838[\uDC07\uDC19\uDC1A\uDC22\uDC25\uDC2B-\uDCFF\uDD2D-\uDD2F\uDD3E\uDD3F\uDD4A-\uDD4D\uDD50-\uDE8F\uDEAF-\uDEBF\uDEFA-\uDEFE\uDF00-\uDFFF]|\uD839[\uDC00-\uDFDF\uDFE7\uDFEC\uDFEF\uDFFF]|\uD83A[\uDCC5\uDCC6\uDCD7-\uDCFF\uDD4C-\uDD4F\uDD5A-\uDD5D\uDD60-\uDFFF]|\uD83B[\uDC00-\uDC70\uDCB5-\uDD00\uDD3E-\uDDFF\uDE04\uDE20\uDE23\uDE25\uDE26\uDE28\uDE33\uDE38\uDE3A\uDE3C-\uDE41\uDE43-\uDE46\uDE48\uDE4A\uDE4C\uDE50\uDE53\uDE55\uDE56\uDE58\uDE5A\uDE5C\uDE5E\uDE60\uDE63\uDE65\uDE66\uDE6B\uDE73\uDE78\uDE7D\uDE7F\uDE8A\uDE9C-\uDEA0\uDEA4\uDEAA\uDEBC-\uDEEF\uDEF2-\uDFFF]|\uD83C[\uDC2C-\uDC2F\uDC94-\uDC9F\uDCAF\uDCB0\uDCC0\uDCD0\uDCF6-\uDCFF\uDDAE-\uDDE5\uDE03-\uDE0F\uDE3C-\uDE3F\uDE49-\uDE4F\uDE52-\uDE5F\uDE66-\uDEFF]|\uD83D[\uDED8-\uDEDC\uDEED-\uDEEF\uDEFD-\uDEFF\uDF74-\uDF7F\uDFD9-\uDFDF\uDFEC-\uDFEF\uDFF1-\uDFFF]|\uD83E[\uDC0C-\uDC0F\uDC48-\uDC4F\uDC5A-\uDC5F\uDC88-\uDC8F\uDCAE\uDCAF\uDCB2-\uDCFF\uDE54-\uDE5F\uDE6E\uDE6F\uDE75-\uDE77\uDE7D-\uDE7F\uDE87-\uDE8F\uDEAD-\uDEAF\uDEBB-\uDEBF\uDEC6-\uDECF\uDEDA-\uDEDF\uDEE8-\uDEEF\uDEF7-\uDEFF\uDF93\uDFCB-\uDFEF\uDFFA-\uDFFF]|\uD869[\uDEE0-\uDEFF]|\uD86D[\uDF39-\uDF3F]|\uD86E[\uDC1E\uDC1F]|\uD873[\uDEA2-\uDEAF]|\uD87A[\uDFE1-\uDFFF]|\uD87E[\uDE1E-\uDFFF]|\uD884[\uDF4B-\uDFFF]|\uDB40[\uDC00-\uDCFF\uDDF0-\uDFFF]"
    }, {
      'name': 'Cc',
      'alias': 'Control',
      'bmp': '\0-\x1F\x7F-\x9F'
    }, {
      'name': 'Cf',
      'alias': 'Format',
      'bmp': "\xAD\u0600-\u0605\u061C\u06DD\u070F\u0890\u0891\u08E2\u180E\u200B-\u200F\u202A-\u202E\u2060-\u2064\u2066-\u206F\uFEFF\uFFF9-\uFFFB",
      'astral': "\uD804[\uDCBD\uDCCD]|\uD80D[\uDC30-\uDC38]|\uD82F[\uDCA0-\uDCA3]|\uD834[\uDD73-\uDD7A]|\uDB40[\uDC01\uDC20-\uDC7F]"
    }, {
      'name': 'Cn',
      'alias': 'Unassigned',
      'bmp': "\u0378\u0379\u0380-\u0383\u038B\u038D\u03A2\u0530\u0557\u0558\u058B\u058C\u0590\u05C8-\u05CF\u05EB-\u05EE\u05F5-\u05FF\u070E\u074B\u074C\u07B2-\u07BF\u07FB\u07FC\u082E\u082F\u083F\u085C\u085D\u085F\u086B-\u086F\u088F\u0892-\u0897\u0984\u098D\u098E\u0991\u0992\u09A9\u09B1\u09B3-\u09B5\u09BA\u09BB\u09C5\u09C6\u09C9\u09CA\u09CF-\u09D6\u09D8-\u09DB\u09DE\u09E4\u09E5\u09FF\u0A00\u0A04\u0A0B-\u0A0E\u0A11\u0A12\u0A29\u0A31\u0A34\u0A37\u0A3A\u0A3B\u0A3D\u0A43-\u0A46\u0A49\u0A4A\u0A4E-\u0A50\u0A52-\u0A58\u0A5D\u0A5F-\u0A65\u0A77-\u0A80\u0A84\u0A8E\u0A92\u0AA9\u0AB1\u0AB4\u0ABA\u0ABB\u0AC6\u0ACA\u0ACE\u0ACF\u0AD1-\u0ADF\u0AE4\u0AE5\u0AF2-\u0AF8\u0B00\u0B04\u0B0D\u0B0E\u0B11\u0B12\u0B29\u0B31\u0B34\u0B3A\u0B3B\u0B45\u0B46\u0B49\u0B4A\u0B4E-\u0B54\u0B58-\u0B5B\u0B5E\u0B64\u0B65\u0B78-\u0B81\u0B84\u0B8B-\u0B8D\u0B91\u0B96-\u0B98\u0B9B\u0B9D\u0BA0-\u0BA2\u0BA5-\u0BA7\u0BAB-\u0BAD\u0BBA-\u0BBD\u0BC3-\u0BC5\u0BC9\u0BCE\u0BCF\u0BD1-\u0BD6\u0BD8-\u0BE5\u0BFB-\u0BFF\u0C0D\u0C11\u0C29\u0C3A\u0C3B\u0C45\u0C49\u0C4E-\u0C54\u0C57\u0C5B\u0C5C\u0C5E\u0C5F\u0C64\u0C65\u0C70-\u0C76\u0C8D\u0C91\u0CA9\u0CB4\u0CBA\u0CBB\u0CC5\u0CC9\u0CCE-\u0CD4\u0CD7-\u0CDC\u0CDF\u0CE4\u0CE5\u0CF0\u0CF3-\u0CFF\u0D0D\u0D11\u0D45\u0D49\u0D50-\u0D53\u0D64\u0D65\u0D80\u0D84\u0D97-\u0D99\u0DB2\u0DBC\u0DBE\u0DBF\u0DC7-\u0DC9\u0DCB-\u0DCE\u0DD5\u0DD7\u0DE0-\u0DE5\u0DF0\u0DF1\u0DF5-\u0E00\u0E3B-\u0E3E\u0E5C-\u0E80\u0E83\u0E85\u0E8B\u0EA4\u0EA6\u0EBE\u0EBF\u0EC5\u0EC7\u0ECE\u0ECF\u0EDA\u0EDB\u0EE0-\u0EFF\u0F48\u0F6D-\u0F70\u0F98\u0FBD\u0FCD\u0FDB-\u0FFF\u10C6\u10C8-\u10CC\u10CE\u10CF\u1249\u124E\u124F\u1257\u1259\u125E\u125F\u1289\u128E\u128F\u12B1\u12B6\u12B7\u12BF\u12C1\u12C6\u12C7\u12D7\u1311\u1316\u1317\u135B\u135C\u137D-\u137F\u139A-\u139F\u13F6\u13F7\u13FE\u13FF\u169D-\u169F\u16F9-\u16FF\u1716-\u171E\u1737-\u173F\u1754-\u175F\u176D\u1771\u1774-\u177F\u17DE\u17DF\u17EA-\u17EF\u17FA-\u17FF\u181A-\u181F\u1879-\u187F\u18AB-\u18AF\u18F6-\u18FF\u191F\u192C-\u192F\u193C-\u193F\u1941-\u1943\u196E\u196F\u1975-\u197F\u19AC-\u19AF\u19CA-\u19CF\u19DB-\u19DD\u1A1C\u1A1D\u1A5F\u1A7D\u1A7E\u1A8A-\u1A8F\u1A9A-\u1A9F\u1AAE\u1AAF\u1ACF-\u1AFF\u1B4D-\u1B4F\u1B7F\u1BF4-\u1BFB\u1C38-\u1C3A\u1C4A-\u1C4C\u1C89-\u1C8F\u1CBB\u1CBC\u1CC8-\u1CCF\u1CFB-\u1CFF\u1F16\u1F17\u1F1E\u1F1F\u1F46\u1F47\u1F4E\u1F4F\u1F58\u1F5A\u1F5C\u1F5E\u1F7E\u1F7F\u1FB5\u1FC5\u1FD4\u1FD5\u1FDC\u1FF0\u1FF1\u1FF5\u1FFF\u2065\u2072\u2073\u208F\u209D-\u209F\u20C1-\u20CF\u20F1-\u20FF\u218C-\u218F\u2427-\u243F\u244B-\u245F\u2B74\u2B75\u2B96\u2CF4-\u2CF8\u2D26\u2D28-\u2D2C\u2D2E\u2D2F\u2D68-\u2D6E\u2D71-\u2D7E\u2D97-\u2D9F\u2DA7\u2DAF\u2DB7\u2DBF\u2DC7\u2DCF\u2DD7\u2DDF\u2E5E-\u2E7F\u2E9A\u2EF4-\u2EFF\u2FD6-\u2FEF\u2FFC-\u2FFF\u3040\u3097\u3098\u3100-\u3104\u3130\u318F\u31E4-\u31EF\u321F\uA48D-\uA48F\uA4C7-\uA4CF\uA62C-\uA63F\uA6F8-\uA6FF\uA7CB-\uA7CF\uA7D2\uA7D4\uA7DA-\uA7F1\uA82D-\uA82F\uA83A-\uA83F\uA878-\uA87F\uA8C6-\uA8CD\uA8DA-\uA8DF\uA954-\uA95E\uA97D-\uA97F\uA9CE\uA9DA-\uA9DD\uA9FF\uAA37-\uAA3F\uAA4E\uAA4F\uAA5A\uAA5B\uAAC3-\uAADA\uAAF7-\uAB00\uAB07\uAB08\uAB0F\uAB10\uAB17-\uAB1F\uAB27\uAB2F\uAB6C-\uAB6F\uABEE\uABEF\uABFA-\uABFF\uD7A4-\uD7AF\uD7C7-\uD7CA\uD7FC-\uD7FF\uFA6E\uFA6F\uFADA-\uFAFF\uFB07-\uFB12\uFB18-\uFB1C\uFB37\uFB3D\uFB3F\uFB42\uFB45\uFBC3-\uFBD2\uFD90\uFD91\uFDC8-\uFDCE\uFDD0-\uFDEF\uFE1A-\uFE1F\uFE53\uFE67\uFE6C-\uFE6F\uFE75\uFEFD\uFEFE\uFF00\uFFBF-\uFFC1\uFFC8\uFFC9\uFFD0\uFFD1\uFFD8\uFFD9\uFFDD-\uFFDF\uFFE7\uFFEF-\uFFF8\uFFFE\uFFFF",
      'astral': "\uD800[\uDC0C\uDC27\uDC3B\uDC3E\uDC4E\uDC4F\uDC5E-\uDC7F\uDCFB-\uDCFF\uDD03-\uDD06\uDD34-\uDD36\uDD8F\uDD9D-\uDD9F\uDDA1-\uDDCF\uDDFE-\uDE7F\uDE9D-\uDE9F\uDED1-\uDEDF\uDEFC-\uDEFF\uDF24-\uDF2C\uDF4B-\uDF4F\uDF7B-\uDF7F\uDF9E\uDFC4-\uDFC7\uDFD6-\uDFFF]|\uD801[\uDC9E\uDC9F\uDCAA-\uDCAF\uDCD4-\uDCD7\uDCFC-\uDCFF\uDD28-\uDD2F\uDD64-\uDD6E\uDD7B\uDD8B\uDD93\uDD96\uDDA2\uDDB2\uDDBA\uDDBD-\uDDFF\uDF37-\uDF3F\uDF56-\uDF5F\uDF68-\uDF7F\uDF86\uDFB1\uDFBB-\uDFFF]|\uD802[\uDC06\uDC07\uDC09\uDC36\uDC39-\uDC3B\uDC3D\uDC3E\uDC56\uDC9F-\uDCA6\uDCB0-\uDCDF\uDCF3\uDCF6-\uDCFA\uDD1C-\uDD1E\uDD3A-\uDD3E\uDD40-\uDD7F\uDDB8-\uDDBB\uDDD0\uDDD1\uDE04\uDE07-\uDE0B\uDE14\uDE18\uDE36\uDE37\uDE3B-\uDE3E\uDE49-\uDE4F\uDE59-\uDE5F\uDEA0-\uDEBF\uDEE7-\uDEEA\uDEF7-\uDEFF\uDF36-\uDF38\uDF56\uDF57\uDF73-\uDF77\uDF92-\uDF98\uDF9D-\uDFA8\uDFB0-\uDFFF]|\uD803[\uDC49-\uDC7F\uDCB3-\uDCBF\uDCF3-\uDCF9\uDD28-\uDD2F\uDD3A-\uDE5F\uDE7F\uDEAA\uDEAE\uDEAF\uDEB2-\uDEFF\uDF28-\uDF2F\uDF5A-\uDF6F\uDF8A-\uDFAF\uDFCC-\uDFDF\uDFF7-\uDFFF]|\uD804[\uDC4E-\uDC51\uDC76-\uDC7E\uDCC3-\uDCCC\uDCCE\uDCCF\uDCE9-\uDCEF\uDCFA-\uDCFF\uDD35\uDD48-\uDD4F\uDD77-\uDD7F\uDDE0\uDDF5-\uDDFF\uDE12\uDE3F-\uDE7F\uDE87\uDE89\uDE8E\uDE9E\uDEAA-\uDEAF\uDEEB-\uDEEF\uDEFA-\uDEFF\uDF04\uDF0D\uDF0E\uDF11\uDF12\uDF29\uDF31\uDF34\uDF3A\uDF45\uDF46\uDF49\uDF4A\uDF4E\uDF4F\uDF51-\uDF56\uDF58-\uDF5C\uDF64\uDF65\uDF6D-\uDF6F\uDF75-\uDFFF]|\uD805[\uDC5C\uDC62-\uDC7F\uDCC8-\uDCCF\uDCDA-\uDD7F\uDDB6\uDDB7\uDDDE-\uDDFF\uDE45-\uDE4F\uDE5A-\uDE5F\uDE6D-\uDE7F\uDEBA-\uDEBF\uDECA-\uDEFF\uDF1B\uDF1C\uDF2C-\uDF2F\uDF47-\uDFFF]|\uD806[\uDC3C-\uDC9F\uDCF3-\uDCFE\uDD07\uDD08\uDD0A\uDD0B\uDD14\uDD17\uDD36\uDD39\uDD3A\uDD47-\uDD4F\uDD5A-\uDD9F\uDDA8\uDDA9\uDDD8\uDDD9\uDDE5-\uDDFF\uDE48-\uDE4F\uDEA3-\uDEAF\uDEF9-\uDFFF]|\uD807[\uDC09\uDC37\uDC46-\uDC4F\uDC6D-\uDC6F\uDC90\uDC91\uDCA8\uDCB7-\uDCFF\uDD07\uDD0A\uDD37-\uDD39\uDD3B\uDD3E\uDD48-\uDD4F\uDD5A-\uDD5F\uDD66\uDD69\uDD8F\uDD92\uDD99-\uDD9F\uDDAA-\uDEDF\uDEF9-\uDFAF\uDFB1-\uDFBF\uDFF2-\uDFFE]|\uD808[\uDF9A-\uDFFF]|\uD809[\uDC6F\uDC75-\uDC7F\uDD44-\uDFFF]|[\uD80A\uD80E-\uD810\uD812-\uD819\uD824-\uD82A\uD82D\uD82E\uD830-\uD832\uD83F\uD87B-\uD87D\uD87F\uD885-\uDB3F\uDB41-\uDB7F][\uDC00-\uDFFF]|\uD80B[\uDC00-\uDF8F\uDFF3-\uDFFF]|\uD80D[\uDC2F\uDC39-\uDFFF]|\uD811[\uDE47-\uDFFF]|\uD81A[\uDE39-\uDE3F\uDE5F\uDE6A-\uDE6D\uDEBF\uDECA-\uDECF\uDEEE\uDEEF\uDEF6-\uDEFF\uDF46-\uDF4F\uDF5A\uDF62\uDF78-\uDF7C\uDF90-\uDFFF]|\uD81B[\uDC00-\uDE3F\uDE9B-\uDEFF\uDF4B-\uDF4E\uDF88-\uDF8E\uDFA0-\uDFDF\uDFE5-\uDFEF\uDFF2-\uDFFF]|\uD821[\uDFF8-\uDFFF]|\uD823[\uDCD6-\uDCFF\uDD09-\uDFFF]|\uD82B[\uDC00-\uDFEF\uDFF4\uDFFC\uDFFF]|\uD82C[\uDD23-\uDD4F\uDD53-\uDD63\uDD68-\uDD6F\uDEFC-\uDFFF]|\uD82F[\uDC6B-\uDC6F\uDC7D-\uDC7F\uDC89-\uDC8F\uDC9A\uDC9B\uDCA4-\uDFFF]|\uD833[\uDC00-\uDEFF\uDF2E\uDF2F\uDF47-\uDF4F\uDFC4-\uDFFF]|\uD834[\uDCF6-\uDCFF\uDD27\uDD28\uDDEB-\uDDFF\uDE46-\uDEDF\uDEF4-\uDEFF\uDF57-\uDF5F\uDF79-\uDFFF]|\uD835[\uDC55\uDC9D\uDCA0\uDCA1\uDCA3\uDCA4\uDCA7\uDCA8\uDCAD\uDCBA\uDCBC\uDCC4\uDD06\uDD0B\uDD0C\uDD15\uDD1D\uDD3A\uDD3F\uDD45\uDD47-\uDD49\uDD51\uDEA6\uDEA7\uDFCC\uDFCD]|\uD836[\uDE8C-\uDE9A\uDEA0\uDEB0-\uDFFF]|\uD837[\uDC00-\uDEFF\uDF1F-\uDFFF]|\uD838[\uDC07\uDC19\uDC1A\uDC22\uDC25\uDC2B-\uDCFF\uDD2D-\uDD2F\uDD3E\uDD3F\uDD4A-\uDD4D\uDD50-\uDE8F\uDEAF-\uDEBF\uDEFA-\uDEFE\uDF00-\uDFFF]|\uD839[\uDC00-\uDFDF\uDFE7\uDFEC\uDFEF\uDFFF]|\uD83A[\uDCC5\uDCC6\uDCD7-\uDCFF\uDD4C-\uDD4F\uDD5A-\uDD5D\uDD60-\uDFFF]|\uD83B[\uDC00-\uDC70\uDCB5-\uDD00\uDD3E-\uDDFF\uDE04\uDE20\uDE23\uDE25\uDE26\uDE28\uDE33\uDE38\uDE3A\uDE3C-\uDE41\uDE43-\uDE46\uDE48\uDE4A\uDE4C\uDE50\uDE53\uDE55\uDE56\uDE58\uDE5A\uDE5C\uDE5E\uDE60\uDE63\uDE65\uDE66\uDE6B\uDE73\uDE78\uDE7D\uDE7F\uDE8A\uDE9C-\uDEA0\uDEA4\uDEAA\uDEBC-\uDEEF\uDEF2-\uDFFF]|\uD83C[\uDC2C-\uDC2F\uDC94-\uDC9F\uDCAF\uDCB0\uDCC0\uDCD0\uDCF6-\uDCFF\uDDAE-\uDDE5\uDE03-\uDE0F\uDE3C-\uDE3F\uDE49-\uDE4F\uDE52-\uDE5F\uDE66-\uDEFF]|\uD83D[\uDED8-\uDEDC\uDEED-\uDEEF\uDEFD-\uDEFF\uDF74-\uDF7F\uDFD9-\uDFDF\uDFEC-\uDFEF\uDFF1-\uDFFF]|\uD83E[\uDC0C-\uDC0F\uDC48-\uDC4F\uDC5A-\uDC5F\uDC88-\uDC8F\uDCAE\uDCAF\uDCB2-\uDCFF\uDE54-\uDE5F\uDE6E\uDE6F\uDE75-\uDE77\uDE7D-\uDE7F\uDE87-\uDE8F\uDEAD-\uDEAF\uDEBB-\uDEBF\uDEC6-\uDECF\uDEDA-\uDEDF\uDEE8-\uDEEF\uDEF7-\uDEFF\uDF93\uDFCB-\uDFEF\uDFFA-\uDFFF]|\uD869[\uDEE0-\uDEFF]|\uD86D[\uDF39-\uDF3F]|\uD86E[\uDC1E\uDC1F]|\uD873[\uDEA2-\uDEAF]|\uD87A[\uDFE1-\uDFFF]|\uD87E[\uDE1E-\uDFFF]|\uD884[\uDF4B-\uDFFF]|\uDB40[\uDC00\uDC02-\uDC1F\uDC80-\uDCFF\uDDF0-\uDFFF]|[\uDBBF\uDBFF][\uDFFE\uDFFF]"
    }, {
      'name': 'Co',
      'alias': 'Private_Use',
      'bmp': "\uE000-\uF8FF",
      'astral': "[\uDB80-\uDBBE\uDBC0-\uDBFE][\uDC00-\uDFFF]|[\uDBBF\uDBFF][\uDC00-\uDFFD]"
    }, {
      'name': 'Cs',
      'alias': 'Surrogate',
      'bmp': "\uD800-\uDFFF"
    }, {
      'name': 'L',
      'alias': 'Letter',
      'bmp': "A-Za-z\xAA\xB5\xBA\xC0-\xD6\xD8-\xF6\xF8-\u02C1\u02C6-\u02D1\u02E0-\u02E4\u02EC\u02EE\u0370-\u0374\u0376\u0377\u037A-\u037D\u037F\u0386\u0388-\u038A\u038C\u038E-\u03A1\u03A3-\u03F5\u03F7-\u0481\u048A-\u052F\u0531-\u0556\u0559\u0560-\u0588\u05D0-\u05EA\u05EF-\u05F2\u0620-\u064A\u066E\u066F\u0671-\u06D3\u06D5\u06E5\u06E6\u06EE\u06EF\u06FA-\u06FC\u06FF\u0710\u0712-\u072F\u074D-\u07A5\u07B1\u07CA-\u07EA\u07F4\u07F5\u07FA\u0800-\u0815\u081A\u0824\u0828\u0840-\u0858\u0860-\u086A\u0870-\u0887\u0889-\u088E\u08A0-\u08C9\u0904-\u0939\u093D\u0950\u0958-\u0961\u0971-\u0980\u0985-\u098C\u098F\u0990\u0993-\u09A8\u09AA-\u09B0\u09B2\u09B6-\u09B9\u09BD\u09CE\u09DC\u09DD\u09DF-\u09E1\u09F0\u09F1\u09FC\u0A05-\u0A0A\u0A0F\u0A10\u0A13-\u0A28\u0A2A-\u0A30\u0A32\u0A33\u0A35\u0A36\u0A38\u0A39\u0A59-\u0A5C\u0A5E\u0A72-\u0A74\u0A85-\u0A8D\u0A8F-\u0A91\u0A93-\u0AA8\u0AAA-\u0AB0\u0AB2\u0AB3\u0AB5-\u0AB9\u0ABD\u0AD0\u0AE0\u0AE1\u0AF9\u0B05-\u0B0C\u0B0F\u0B10\u0B13-\u0B28\u0B2A-\u0B30\u0B32\u0B33\u0B35-\u0B39\u0B3D\u0B5C\u0B5D\u0B5F-\u0B61\u0B71\u0B83\u0B85-\u0B8A\u0B8E-\u0B90\u0B92-\u0B95\u0B99\u0B9A\u0B9C\u0B9E\u0B9F\u0BA3\u0BA4\u0BA8-\u0BAA\u0BAE-\u0BB9\u0BD0\u0C05-\u0C0C\u0C0E-\u0C10\u0C12-\u0C28\u0C2A-\u0C39\u0C3D\u0C58-\u0C5A\u0C5D\u0C60\u0C61\u0C80\u0C85-\u0C8C\u0C8E-\u0C90\u0C92-\u0CA8\u0CAA-\u0CB3\u0CB5-\u0CB9\u0CBD\u0CDD\u0CDE\u0CE0\u0CE1\u0CF1\u0CF2\u0D04-\u0D0C\u0D0E-\u0D10\u0D12-\u0D3A\u0D3D\u0D4E\u0D54-\u0D56\u0D5F-\u0D61\u0D7A-\u0D7F\u0D85-\u0D96\u0D9A-\u0DB1\u0DB3-\u0DBB\u0DBD\u0DC0-\u0DC6\u0E01-\u0E30\u0E32\u0E33\u0E40-\u0E46\u0E81\u0E82\u0E84\u0E86-\u0E8A\u0E8C-\u0EA3\u0EA5\u0EA7-\u0EB0\u0EB2\u0EB3\u0EBD\u0EC0-\u0EC4\u0EC6\u0EDC-\u0EDF\u0F00\u0F40-\u0F47\u0F49-\u0F6C\u0F88-\u0F8C\u1000-\u102A\u103F\u1050-\u1055\u105A-\u105D\u1061\u1065\u1066\u106E-\u1070\u1075-\u1081\u108E\u10A0-\u10C5\u10C7\u10CD\u10D0-\u10FA\u10FC-\u1248\u124A-\u124D\u1250-\u1256\u1258\u125A-\u125D\u1260-\u1288\u128A-\u128D\u1290-\u12B0\u12B2-\u12B5\u12B8-\u12BE\u12C0\u12C2-\u12C5\u12C8-\u12D6\u12D8-\u1310\u1312-\u1315\u1318-\u135A\u1380-\u138F\u13A0-\u13F5\u13F8-\u13FD\u1401-\u166C\u166F-\u167F\u1681-\u169A\u16A0-\u16EA\u16F1-\u16F8\u1700-\u1711\u171F-\u1731\u1740-\u1751\u1760-\u176C\u176E-\u1770\u1780-\u17B3\u17D7\u17DC\u1820-\u1878\u1880-\u1884\u1887-\u18A8\u18AA\u18B0-\u18F5\u1900-\u191E\u1950-\u196D\u1970-\u1974\u1980-\u19AB\u19B0-\u19C9\u1A00-\u1A16\u1A20-\u1A54\u1AA7\u1B05-\u1B33\u1B45-\u1B4C\u1B83-\u1BA0\u1BAE\u1BAF\u1BBA-\u1BE5\u1C00-\u1C23\u1C4D-\u1C4F\u1C5A-\u1C7D\u1C80-\u1C88\u1C90-\u1CBA\u1CBD-\u1CBF\u1CE9-\u1CEC\u1CEE-\u1CF3\u1CF5\u1CF6\u1CFA\u1D00-\u1DBF\u1E00-\u1F15\u1F18-\u1F1D\u1F20-\u1F45\u1F48-\u1F4D\u1F50-\u1F57\u1F59\u1F5B\u1F5D\u1F5F-\u1F7D\u1F80-\u1FB4\u1FB6-\u1FBC\u1FBE\u1FC2-\u1FC4\u1FC6-\u1FCC\u1FD0-\u1FD3\u1FD6-\u1FDB\u1FE0-\u1FEC\u1FF2-\u1FF4\u1FF6-\u1FFC\u2071\u207F\u2090-\u209C\u2102\u2107\u210A-\u2113\u2115\u2119-\u211D\u2124\u2126\u2128\u212A-\u212D\u212F-\u2139\u213C-\u213F\u2145-\u2149\u214E\u2183\u2184\u2C00-\u2CE4\u2CEB-\u2CEE\u2CF2\u2CF3\u2D00-\u2D25\u2D27\u2D2D\u2D30-\u2D67\u2D6F\u2D80-\u2D96\u2DA0-\u2DA6\u2DA8-\u2DAE\u2DB0-\u2DB6\u2DB8-\u2DBE\u2DC0-\u2DC6\u2DC8-\u2DCE\u2DD0-\u2DD6\u2DD8-\u2DDE\u2E2F\u3005\u3006\u3031-\u3035\u303B\u303C\u3041-\u3096\u309D-\u309F\u30A1-\u30FA\u30FC-\u30FF\u3105-\u312F\u3131-\u318E\u31A0-\u31BF\u31F0-\u31FF\u3400-\u4DBF\u4E00-\uA48C\uA4D0-\uA4FD\uA500-\uA60C\uA610-\uA61F\uA62A\uA62B\uA640-\uA66E\uA67F-\uA69D\uA6A0-\uA6E5\uA717-\uA71F\uA722-\uA788\uA78B-\uA7CA\uA7D0\uA7D1\uA7D3\uA7D5-\uA7D9\uA7F2-\uA801\uA803-\uA805\uA807-\uA80A\uA80C-\uA822\uA840-\uA873\uA882-\uA8B3\uA8F2-\uA8F7\uA8FB\uA8FD\uA8FE\uA90A-\uA925\uA930-\uA946\uA960-\uA97C\uA984-\uA9B2\uA9CF\uA9E0-\uA9E4\uA9E6-\uA9EF\uA9FA-\uA9FE\uAA00-\uAA28\uAA40-\uAA42\uAA44-\uAA4B\uAA60-\uAA76\uAA7A\uAA7E-\uAAAF\uAAB1\uAAB5\uAAB6\uAAB9-\uAABD\uAAC0\uAAC2\uAADB-\uAADD\uAAE0-\uAAEA\uAAF2-\uAAF4\uAB01-\uAB06\uAB09-\uAB0E\uAB11-\uAB16\uAB20-\uAB26\uAB28-\uAB2E\uAB30-\uAB5A\uAB5C-\uAB69\uAB70-\uABE2\uAC00-\uD7A3\uD7B0-\uD7C6\uD7CB-\uD7FB\uF900-\uFA6D\uFA70-\uFAD9\uFB00-\uFB06\uFB13-\uFB17\uFB1D\uFB1F-\uFB28\uFB2A-\uFB36\uFB38-\uFB3C\uFB3E\uFB40\uFB41\uFB43\uFB44\uFB46-\uFBB1\uFBD3-\uFD3D\uFD50-\uFD8F\uFD92-\uFDC7\uFDF0-\uFDFB\uFE70-\uFE74\uFE76-\uFEFC\uFF21-\uFF3A\uFF41-\uFF5A\uFF66-\uFFBE\uFFC2-\uFFC7\uFFCA-\uFFCF\uFFD2-\uFFD7\uFFDA-\uFFDC",
      'astral': "\uD800[\uDC00-\uDC0B\uDC0D-\uDC26\uDC28-\uDC3A\uDC3C\uDC3D\uDC3F-\uDC4D\uDC50-\uDC5D\uDC80-\uDCFA\uDE80-\uDE9C\uDEA0-\uDED0\uDF00-\uDF1F\uDF2D-\uDF40\uDF42-\uDF49\uDF50-\uDF75\uDF80-\uDF9D\uDFA0-\uDFC3\uDFC8-\uDFCF]|\uD801[\uDC00-\uDC9D\uDCB0-\uDCD3\uDCD8-\uDCFB\uDD00-\uDD27\uDD30-\uDD63\uDD70-\uDD7A\uDD7C-\uDD8A\uDD8C-\uDD92\uDD94\uDD95\uDD97-\uDDA1\uDDA3-\uDDB1\uDDB3-\uDDB9\uDDBB\uDDBC\uDE00-\uDF36\uDF40-\uDF55\uDF60-\uDF67\uDF80-\uDF85\uDF87-\uDFB0\uDFB2-\uDFBA]|\uD802[\uDC00-\uDC05\uDC08\uDC0A-\uDC35\uDC37\uDC38\uDC3C\uDC3F-\uDC55\uDC60-\uDC76\uDC80-\uDC9E\uDCE0-\uDCF2\uDCF4\uDCF5\uDD00-\uDD15\uDD20-\uDD39\uDD80-\uDDB7\uDDBE\uDDBF\uDE00\uDE10-\uDE13\uDE15-\uDE17\uDE19-\uDE35\uDE60-\uDE7C\uDE80-\uDE9C\uDEC0-\uDEC7\uDEC9-\uDEE4\uDF00-\uDF35\uDF40-\uDF55\uDF60-\uDF72\uDF80-\uDF91]|\uD803[\uDC00-\uDC48\uDC80-\uDCB2\uDCC0-\uDCF2\uDD00-\uDD23\uDE80-\uDEA9\uDEB0\uDEB1\uDF00-\uDF1C\uDF27\uDF30-\uDF45\uDF70-\uDF81\uDFB0-\uDFC4\uDFE0-\uDFF6]|\uD804[\uDC03-\uDC37\uDC71\uDC72\uDC75\uDC83-\uDCAF\uDCD0-\uDCE8\uDD03-\uDD26\uDD44\uDD47\uDD50-\uDD72\uDD76\uDD83-\uDDB2\uDDC1-\uDDC4\uDDDA\uDDDC\uDE00-\uDE11\uDE13-\uDE2B\uDE80-\uDE86\uDE88\uDE8A-\uDE8D\uDE8F-\uDE9D\uDE9F-\uDEA8\uDEB0-\uDEDE\uDF05-\uDF0C\uDF0F\uDF10\uDF13-\uDF28\uDF2A-\uDF30\uDF32\uDF33\uDF35-\uDF39\uDF3D\uDF50\uDF5D-\uDF61]|\uD805[\uDC00-\uDC34\uDC47-\uDC4A\uDC5F-\uDC61\uDC80-\uDCAF\uDCC4\uDCC5\uDCC7\uDD80-\uDDAE\uDDD8-\uDDDB\uDE00-\uDE2F\uDE44\uDE80-\uDEAA\uDEB8\uDF00-\uDF1A\uDF40-\uDF46]|\uD806[\uDC00-\uDC2B\uDCA0-\uDCDF\uDCFF-\uDD06\uDD09\uDD0C-\uDD13\uDD15\uDD16\uDD18-\uDD2F\uDD3F\uDD41\uDDA0-\uDDA7\uDDAA-\uDDD0\uDDE1\uDDE3\uDE00\uDE0B-\uDE32\uDE3A\uDE50\uDE5C-\uDE89\uDE9D\uDEB0-\uDEF8]|\uD807[\uDC00-\uDC08\uDC0A-\uDC2E\uDC40\uDC72-\uDC8F\uDD00-\uDD06\uDD08\uDD09\uDD0B-\uDD30\uDD46\uDD60-\uDD65\uDD67\uDD68\uDD6A-\uDD89\uDD98\uDEE0-\uDEF2\uDFB0]|\uD808[\uDC00-\uDF99]|\uD809[\uDC80-\uDD43]|\uD80B[\uDF90-\uDFF0]|[\uD80C\uD81C-\uD820\uD822\uD840-\uD868\uD86A-\uD86C\uD86F-\uD872\uD874-\uD879\uD880-\uD883][\uDC00-\uDFFF]|\uD80D[\uDC00-\uDC2E]|\uD811[\uDC00-\uDE46]|\uD81A[\uDC00-\uDE38\uDE40-\uDE5E\uDE70-\uDEBE\uDED0-\uDEED\uDF00-\uDF2F\uDF40-\uDF43\uDF63-\uDF77\uDF7D-\uDF8F]|\uD81B[\uDE40-\uDE7F\uDF00-\uDF4A\uDF50\uDF93-\uDF9F\uDFE0\uDFE1\uDFE3]|\uD821[\uDC00-\uDFF7]|\uD823[\uDC00-\uDCD5\uDD00-\uDD08]|\uD82B[\uDFF0-\uDFF3\uDFF5-\uDFFB\uDFFD\uDFFE]|\uD82C[\uDC00-\uDD22\uDD50-\uDD52\uDD64-\uDD67\uDD70-\uDEFB]|\uD82F[\uDC00-\uDC6A\uDC70-\uDC7C\uDC80-\uDC88\uDC90-\uDC99]|\uD835[\uDC00-\uDC54\uDC56-\uDC9C\uDC9E\uDC9F\uDCA2\uDCA5\uDCA6\uDCA9-\uDCAC\uDCAE-\uDCB9\uDCBB\uDCBD-\uDCC3\uDCC5-\uDD05\uDD07-\uDD0A\uDD0D-\uDD14\uDD16-\uDD1C\uDD1E-\uDD39\uDD3B-\uDD3E\uDD40-\uDD44\uDD46\uDD4A-\uDD50\uDD52-\uDEA5\uDEA8-\uDEC0\uDEC2-\uDEDA\uDEDC-\uDEFA\uDEFC-\uDF14\uDF16-\uDF34\uDF36-\uDF4E\uDF50-\uDF6E\uDF70-\uDF88\uDF8A-\uDFA8\uDFAA-\uDFC2\uDFC4-\uDFCB]|\uD837[\uDF00-\uDF1E]|\uD838[\uDD00-\uDD2C\uDD37-\uDD3D\uDD4E\uDE90-\uDEAD\uDEC0-\uDEEB]|\uD839[\uDFE0-\uDFE6\uDFE8-\uDFEB\uDFED\uDFEE\uDFF0-\uDFFE]|\uD83A[\uDC00-\uDCC4\uDD00-\uDD43\uDD4B]|\uD83B[\uDE00-\uDE03\uDE05-\uDE1F\uDE21\uDE22\uDE24\uDE27\uDE29-\uDE32\uDE34-\uDE37\uDE39\uDE3B\uDE42\uDE47\uDE49\uDE4B\uDE4D-\uDE4F\uDE51\uDE52\uDE54\uDE57\uDE59\uDE5B\uDE5D\uDE5F\uDE61\uDE62\uDE64\uDE67-\uDE6A\uDE6C-\uDE72\uDE74-\uDE77\uDE79-\uDE7C\uDE7E\uDE80-\uDE89\uDE8B-\uDE9B\uDEA1-\uDEA3\uDEA5-\uDEA9\uDEAB-\uDEBB]|\uD869[\uDC00-\uDEDF\uDF00-\uDFFF]|\uD86D[\uDC00-\uDF38\uDF40-\uDFFF]|\uD86E[\uDC00-\uDC1D\uDC20-\uDFFF]|\uD873[\uDC00-\uDEA1\uDEB0-\uDFFF]|\uD87A[\uDC00-\uDFE0]|\uD87E[\uDC00-\uDE1D]|\uD884[\uDC00-\uDF4A]"
    }, {
      'name': 'LC',
      'alias': 'Cased_Letter',
      'bmp': "A-Za-z\xB5\xC0-\xD6\xD8-\xF6\xF8-\u01BA\u01BC-\u01BF\u01C4-\u0293\u0295-\u02AF\u0370-\u0373\u0376\u0377\u037B-\u037D\u037F\u0386\u0388-\u038A\u038C\u038E-\u03A1\u03A3-\u03F5\u03F7-\u0481\u048A-\u052F\u0531-\u0556\u0560-\u0588\u10A0-\u10C5\u10C7\u10CD\u10D0-\u10FA\u10FD-\u10FF\u13A0-\u13F5\u13F8-\u13FD\u1C80-\u1C88\u1C90-\u1CBA\u1CBD-\u1CBF\u1D00-\u1D2B\u1D6B-\u1D77\u1D79-\u1D9A\u1E00-\u1F15\u1F18-\u1F1D\u1F20-\u1F45\u1F48-\u1F4D\u1F50-\u1F57\u1F59\u1F5B\u1F5D\u1F5F-\u1F7D\u1F80-\u1FB4\u1FB6-\u1FBC\u1FBE\u1FC2-\u1FC4\u1FC6-\u1FCC\u1FD0-\u1FD3\u1FD6-\u1FDB\u1FE0-\u1FEC\u1FF2-\u1FF4\u1FF6-\u1FFC\u2102\u2107\u210A-\u2113\u2115\u2119-\u211D\u2124\u2126\u2128\u212A-\u212D\u212F-\u2134\u2139\u213C-\u213F\u2145-\u2149\u214E\u2183\u2184\u2C00-\u2C7B\u2C7E-\u2CE4\u2CEB-\u2CEE\u2CF2\u2CF3\u2D00-\u2D25\u2D27\u2D2D\uA640-\uA66D\uA680-\uA69B\uA722-\uA76F\uA771-\uA787\uA78B-\uA78E\uA790-\uA7CA\uA7D0\uA7D1\uA7D3\uA7D5-\uA7D9\uA7F5\uA7F6\uA7FA\uAB30-\uAB5A\uAB60-\uAB68\uAB70-\uABBF\uFB00-\uFB06\uFB13-\uFB17\uFF21-\uFF3A\uFF41-\uFF5A",
      'astral': "\uD801[\uDC00-\uDC4F\uDCB0-\uDCD3\uDCD8-\uDCFB\uDD70-\uDD7A\uDD7C-\uDD8A\uDD8C-\uDD92\uDD94\uDD95\uDD97-\uDDA1\uDDA3-\uDDB1\uDDB3-\uDDB9\uDDBB\uDDBC]|\uD803[\uDC80-\uDCB2\uDCC0-\uDCF2]|\uD806[\uDCA0-\uDCDF]|\uD81B[\uDE40-\uDE7F]|\uD835[\uDC00-\uDC54\uDC56-\uDC9C\uDC9E\uDC9F\uDCA2\uDCA5\uDCA6\uDCA9-\uDCAC\uDCAE-\uDCB9\uDCBB\uDCBD-\uDCC3\uDCC5-\uDD05\uDD07-\uDD0A\uDD0D-\uDD14\uDD16-\uDD1C\uDD1E-\uDD39\uDD3B-\uDD3E\uDD40-\uDD44\uDD46\uDD4A-\uDD50\uDD52-\uDEA5\uDEA8-\uDEC0\uDEC2-\uDEDA\uDEDC-\uDEFA\uDEFC-\uDF14\uDF16-\uDF34\uDF36-\uDF4E\uDF50-\uDF6E\uDF70-\uDF88\uDF8A-\uDFA8\uDFAA-\uDFC2\uDFC4-\uDFCB]|\uD837[\uDF00-\uDF09\uDF0B-\uDF1E]|\uD83A[\uDD00-\uDD43]"
    }, {
      'name': 'Ll',
      'alias': 'Lowercase_Letter',
      'bmp': "a-z\xB5\xDF-\xF6\xF8-\xFF\u0101\u0103\u0105\u0107\u0109\u010B\u010D\u010F\u0111\u0113\u0115\u0117\u0119\u011B\u011D\u011F\u0121\u0123\u0125\u0127\u0129\u012B\u012D\u012F\u0131\u0133\u0135\u0137\u0138\u013A\u013C\u013E\u0140\u0142\u0144\u0146\u0148\u0149\u014B\u014D\u014F\u0151\u0153\u0155\u0157\u0159\u015B\u015D\u015F\u0161\u0163\u0165\u0167\u0169\u016B\u016D\u016F\u0171\u0173\u0175\u0177\u017A\u017C\u017E-\u0180\u0183\u0185\u0188\u018C\u018D\u0192\u0195\u0199-\u019B\u019E\u01A1\u01A3\u01A5\u01A8\u01AA\u01AB\u01AD\u01B0\u01B4\u01B6\u01B9\u01BA\u01BD-\u01BF\u01C6\u01C9\u01CC\u01CE\u01D0\u01D2\u01D4\u01D6\u01D8\u01DA\u01DC\u01DD\u01DF\u01E1\u01E3\u01E5\u01E7\u01E9\u01EB\u01ED\u01EF\u01F0\u01F3\u01F5\u01F9\u01FB\u01FD\u01FF\u0201\u0203\u0205\u0207\u0209\u020B\u020D\u020F\u0211\u0213\u0215\u0217\u0219\u021B\u021D\u021F\u0221\u0223\u0225\u0227\u0229\u022B\u022D\u022F\u0231\u0233-\u0239\u023C\u023F\u0240\u0242\u0247\u0249\u024B\u024D\u024F-\u0293\u0295-\u02AF\u0371\u0373\u0377\u037B-\u037D\u0390\u03AC-\u03CE\u03D0\u03D1\u03D5-\u03D7\u03D9\u03DB\u03DD\u03DF\u03E1\u03E3\u03E5\u03E7\u03E9\u03EB\u03ED\u03EF-\u03F3\u03F5\u03F8\u03FB\u03FC\u0430-\u045F\u0461\u0463\u0465\u0467\u0469\u046B\u046D\u046F\u0471\u0473\u0475\u0477\u0479\u047B\u047D\u047F\u0481\u048B\u048D\u048F\u0491\u0493\u0495\u0497\u0499\u049B\u049D\u049F\u04A1\u04A3\u04A5\u04A7\u04A9\u04AB\u04AD\u04AF\u04B1\u04B3\u04B5\u04B7\u04B9\u04BB\u04BD\u04BF\u04C2\u04C4\u04C6\u04C8\u04CA\u04CC\u04CE\u04CF\u04D1\u04D3\u04D5\u04D7\u04D9\u04DB\u04DD\u04DF\u04E1\u04E3\u04E5\u04E7\u04E9\u04EB\u04ED\u04EF\u04F1\u04F3\u04F5\u04F7\u04F9\u04FB\u04FD\u04FF\u0501\u0503\u0505\u0507\u0509\u050B\u050D\u050F\u0511\u0513\u0515\u0517\u0519\u051B\u051D\u051F\u0521\u0523\u0525\u0527\u0529\u052B\u052D\u052F\u0560-\u0588\u10D0-\u10FA\u10FD-\u10FF\u13F8-\u13FD\u1C80-\u1C88\u1D00-\u1D2B\u1D6B-\u1D77\u1D79-\u1D9A\u1E01\u1E03\u1E05\u1E07\u1E09\u1E0B\u1E0D\u1E0F\u1E11\u1E13\u1E15\u1E17\u1E19\u1E1B\u1E1D\u1E1F\u1E21\u1E23\u1E25\u1E27\u1E29\u1E2B\u1E2D\u1E2F\u1E31\u1E33\u1E35\u1E37\u1E39\u1E3B\u1E3D\u1E3F\u1E41\u1E43\u1E45\u1E47\u1E49\u1E4B\u1E4D\u1E4F\u1E51\u1E53\u1E55\u1E57\u1E59\u1E5B\u1E5D\u1E5F\u1E61\u1E63\u1E65\u1E67\u1E69\u1E6B\u1E6D\u1E6F\u1E71\u1E73\u1E75\u1E77\u1E79\u1E7B\u1E7D\u1E7F\u1E81\u1E83\u1E85\u1E87\u1E89\u1E8B\u1E8D\u1E8F\u1E91\u1E93\u1E95-\u1E9D\u1E9F\u1EA1\u1EA3\u1EA5\u1EA7\u1EA9\u1EAB\u1EAD\u1EAF\u1EB1\u1EB3\u1EB5\u1EB7\u1EB9\u1EBB\u1EBD\u1EBF\u1EC1\u1EC3\u1EC5\u1EC7\u1EC9\u1ECB\u1ECD\u1ECF\u1ED1\u1ED3\u1ED5\u1ED7\u1ED9\u1EDB\u1EDD\u1EDF\u1EE1\u1EE3\u1EE5\u1EE7\u1EE9\u1EEB\u1EED\u1EEF\u1EF1\u1EF3\u1EF5\u1EF7\u1EF9\u1EFB\u1EFD\u1EFF-\u1F07\u1F10-\u1F15\u1F20-\u1F27\u1F30-\u1F37\u1F40-\u1F45\u1F50-\u1F57\u1F60-\u1F67\u1F70-\u1F7D\u1F80-\u1F87\u1F90-\u1F97\u1FA0-\u1FA7\u1FB0-\u1FB4\u1FB6\u1FB7\u1FBE\u1FC2-\u1FC4\u1FC6\u1FC7\u1FD0-\u1FD3\u1FD6\u1FD7\u1FE0-\u1FE7\u1FF2-\u1FF4\u1FF6\u1FF7\u210A\u210E\u210F\u2113\u212F\u2134\u2139\u213C\u213D\u2146-\u2149\u214E\u2184\u2C30-\u2C5F\u2C61\u2C65\u2C66\u2C68\u2C6A\u2C6C\u2C71\u2C73\u2C74\u2C76-\u2C7B\u2C81\u2C83\u2C85\u2C87\u2C89\u2C8B\u2C8D\u2C8F\u2C91\u2C93\u2C95\u2C97\u2C99\u2C9B\u2C9D\u2C9F\u2CA1\u2CA3\u2CA5\u2CA7\u2CA9\u2CAB\u2CAD\u2CAF\u2CB1\u2CB3\u2CB5\u2CB7\u2CB9\u2CBB\u2CBD\u2CBF\u2CC1\u2CC3\u2CC5\u2CC7\u2CC9\u2CCB\u2CCD\u2CCF\u2CD1\u2CD3\u2CD5\u2CD7\u2CD9\u2CDB\u2CDD\u2CDF\u2CE1\u2CE3\u2CE4\u2CEC\u2CEE\u2CF3\u2D00-\u2D25\u2D27\u2D2D\uA641\uA643\uA645\uA647\uA649\uA64B\uA64D\uA64F\uA651\uA653\uA655\uA657\uA659\uA65B\uA65D\uA65F\uA661\uA663\uA665\uA667\uA669\uA66B\uA66D\uA681\uA683\uA685\uA687\uA689\uA68B\uA68D\uA68F\uA691\uA693\uA695\uA697\uA699\uA69B\uA723\uA725\uA727\uA729\uA72B\uA72D\uA72F-\uA731\uA733\uA735\uA737\uA739\uA73B\uA73D\uA73F\uA741\uA743\uA745\uA747\uA749\uA74B\uA74D\uA74F\uA751\uA753\uA755\uA757\uA759\uA75B\uA75D\uA75F\uA761\uA763\uA765\uA767\uA769\uA76B\uA76D\uA76F\uA771-\uA778\uA77A\uA77C\uA77F\uA781\uA783\uA785\uA787\uA78C\uA78E\uA791\uA793-\uA795\uA797\uA799\uA79B\uA79D\uA79F\uA7A1\uA7A3\uA7A5\uA7A7\uA7A9\uA7AF\uA7B5\uA7B7\uA7B9\uA7BB\uA7BD\uA7BF\uA7C1\uA7C3\uA7C8\uA7CA\uA7D1\uA7D3\uA7D5\uA7D7\uA7D9\uA7F6\uA7FA\uAB30-\uAB5A\uAB60-\uAB68\uAB70-\uABBF\uFB00-\uFB06\uFB13-\uFB17\uFF41-\uFF5A",
      'astral': "\uD801[\uDC28-\uDC4F\uDCD8-\uDCFB\uDD97-\uDDA1\uDDA3-\uDDB1\uDDB3-\uDDB9\uDDBB\uDDBC]|\uD803[\uDCC0-\uDCF2]|\uD806[\uDCC0-\uDCDF]|\uD81B[\uDE60-\uDE7F]|\uD835[\uDC1A-\uDC33\uDC4E-\uDC54\uDC56-\uDC67\uDC82-\uDC9B\uDCB6-\uDCB9\uDCBB\uDCBD-\uDCC3\uDCC5-\uDCCF\uDCEA-\uDD03\uDD1E-\uDD37\uDD52-\uDD6B\uDD86-\uDD9F\uDDBA-\uDDD3\uDDEE-\uDE07\uDE22-\uDE3B\uDE56-\uDE6F\uDE8A-\uDEA5\uDEC2-\uDEDA\uDEDC-\uDEE1\uDEFC-\uDF14\uDF16-\uDF1B\uDF36-\uDF4E\uDF50-\uDF55\uDF70-\uDF88\uDF8A-\uDF8F\uDFAA-\uDFC2\uDFC4-\uDFC9\uDFCB]|\uD837[\uDF00-\uDF09\uDF0B-\uDF1E]|\uD83A[\uDD22-\uDD43]"
    }, {
      'name': 'Lm',
      'alias': 'Modifier_Letter',
      'bmp': "\u02B0-\u02C1\u02C6-\u02D1\u02E0-\u02E4\u02EC\u02EE\u0374\u037A\u0559\u0640\u06E5\u06E6\u07F4\u07F5\u07FA\u081A\u0824\u0828\u08C9\u0971\u0E46\u0EC6\u10FC\u17D7\u1843\u1AA7\u1C78-\u1C7D\u1D2C-\u1D6A\u1D78\u1D9B-\u1DBF\u2071\u207F\u2090-\u209C\u2C7C\u2C7D\u2D6F\u2E2F\u3005\u3031-\u3035\u303B\u309D\u309E\u30FC-\u30FE\uA015\uA4F8-\uA4FD\uA60C\uA67F\uA69C\uA69D\uA717-\uA71F\uA770\uA788\uA7F2-\uA7F4\uA7F8\uA7F9\uA9CF\uA9E6\uAA70\uAADD\uAAF3\uAAF4\uAB5C-\uAB5F\uAB69\uFF70\uFF9E\uFF9F",
      'astral': "\uD801[\uDF80-\uDF85\uDF87-\uDFB0\uDFB2-\uDFBA]|\uD81A[\uDF40-\uDF43]|\uD81B[\uDF93-\uDF9F\uDFE0\uDFE1\uDFE3]|\uD82B[\uDFF0-\uDFF3\uDFF5-\uDFFB\uDFFD\uDFFE]|\uD838[\uDD37-\uDD3D]|\uD83A\uDD4B"
    }, {
      'name': 'Lo',
      'alias': 'Other_Letter',
      'bmp': "\xAA\xBA\u01BB\u01C0-\u01C3\u0294\u05D0-\u05EA\u05EF-\u05F2\u0620-\u063F\u0641-\u064A\u066E\u066F\u0671-\u06D3\u06D5\u06EE\u06EF\u06FA-\u06FC\u06FF\u0710\u0712-\u072F\u074D-\u07A5\u07B1\u07CA-\u07EA\u0800-\u0815\u0840-\u0858\u0860-\u086A\u0870-\u0887\u0889-\u088E\u08A0-\u08C8\u0904-\u0939\u093D\u0950\u0958-\u0961\u0972-\u0980\u0985-\u098C\u098F\u0990\u0993-\u09A8\u09AA-\u09B0\u09B2\u09B6-\u09B9\u09BD\u09CE\u09DC\u09DD\u09DF-\u09E1\u09F0\u09F1\u09FC\u0A05-\u0A0A\u0A0F\u0A10\u0A13-\u0A28\u0A2A-\u0A30\u0A32\u0A33\u0A35\u0A36\u0A38\u0A39\u0A59-\u0A5C\u0A5E\u0A72-\u0A74\u0A85-\u0A8D\u0A8F-\u0A91\u0A93-\u0AA8\u0AAA-\u0AB0\u0AB2\u0AB3\u0AB5-\u0AB9\u0ABD\u0AD0\u0AE0\u0AE1\u0AF9\u0B05-\u0B0C\u0B0F\u0B10\u0B13-\u0B28\u0B2A-\u0B30\u0B32\u0B33\u0B35-\u0B39\u0B3D\u0B5C\u0B5D\u0B5F-\u0B61\u0B71\u0B83\u0B85-\u0B8A\u0B8E-\u0B90\u0B92-\u0B95\u0B99\u0B9A\u0B9C\u0B9E\u0B9F\u0BA3\u0BA4\u0BA8-\u0BAA\u0BAE-\u0BB9\u0BD0\u0C05-\u0C0C\u0C0E-\u0C10\u0C12-\u0C28\u0C2A-\u0C39\u0C3D\u0C58-\u0C5A\u0C5D\u0C60\u0C61\u0C80\u0C85-\u0C8C\u0C8E-\u0C90\u0C92-\u0CA8\u0CAA-\u0CB3\u0CB5-\u0CB9\u0CBD\u0CDD\u0CDE\u0CE0\u0CE1\u0CF1\u0CF2\u0D04-\u0D0C\u0D0E-\u0D10\u0D12-\u0D3A\u0D3D\u0D4E\u0D54-\u0D56\u0D5F-\u0D61\u0D7A-\u0D7F\u0D85-\u0D96\u0D9A-\u0DB1\u0DB3-\u0DBB\u0DBD\u0DC0-\u0DC6\u0E01-\u0E30\u0E32\u0E33\u0E40-\u0E45\u0E81\u0E82\u0E84\u0E86-\u0E8A\u0E8C-\u0EA3\u0EA5\u0EA7-\u0EB0\u0EB2\u0EB3\u0EBD\u0EC0-\u0EC4\u0EDC-\u0EDF\u0F00\u0F40-\u0F47\u0F49-\u0F6C\u0F88-\u0F8C\u1000-\u102A\u103F\u1050-\u1055\u105A-\u105D\u1061\u1065\u1066\u106E-\u1070\u1075-\u1081\u108E\u1100-\u1248\u124A-\u124D\u1250-\u1256\u1258\u125A-\u125D\u1260-\u1288\u128A-\u128D\u1290-\u12B0\u12B2-\u12B5\u12B8-\u12BE\u12C0\u12C2-\u12C5\u12C8-\u12D6\u12D8-\u1310\u1312-\u1315\u1318-\u135A\u1380-\u138F\u1401-\u166C\u166F-\u167F\u1681-\u169A\u16A0-\u16EA\u16F1-\u16F8\u1700-\u1711\u171F-\u1731\u1740-\u1751\u1760-\u176C\u176E-\u1770\u1780-\u17B3\u17DC\u1820-\u1842\u1844-\u1878\u1880-\u1884\u1887-\u18A8\u18AA\u18B0-\u18F5\u1900-\u191E\u1950-\u196D\u1970-\u1974\u1980-\u19AB\u19B0-\u19C9\u1A00-\u1A16\u1A20-\u1A54\u1B05-\u1B33\u1B45-\u1B4C\u1B83-\u1BA0\u1BAE\u1BAF\u1BBA-\u1BE5\u1C00-\u1C23\u1C4D-\u1C4F\u1C5A-\u1C77\u1CE9-\u1CEC\u1CEE-\u1CF3\u1CF5\u1CF6\u1CFA\u2135-\u2138\u2D30-\u2D67\u2D80-\u2D96\u2DA0-\u2DA6\u2DA8-\u2DAE\u2DB0-\u2DB6\u2DB8-\u2DBE\u2DC0-\u2DC6\u2DC8-\u2DCE\u2DD0-\u2DD6\u2DD8-\u2DDE\u3006\u303C\u3041-\u3096\u309F\u30A1-\u30FA\u30FF\u3105-\u312F\u3131-\u318E\u31A0-\u31BF\u31F0-\u31FF\u3400-\u4DBF\u4E00-\uA014\uA016-\uA48C\uA4D0-\uA4F7\uA500-\uA60B\uA610-\uA61F\uA62A\uA62B\uA66E\uA6A0-\uA6E5\uA78F\uA7F7\uA7FB-\uA801\uA803-\uA805\uA807-\uA80A\uA80C-\uA822\uA840-\uA873\uA882-\uA8B3\uA8F2-\uA8F7\uA8FB\uA8FD\uA8FE\uA90A-\uA925\uA930-\uA946\uA960-\uA97C\uA984-\uA9B2\uA9E0-\uA9E4\uA9E7-\uA9EF\uA9FA-\uA9FE\uAA00-\uAA28\uAA40-\uAA42\uAA44-\uAA4B\uAA60-\uAA6F\uAA71-\uAA76\uAA7A\uAA7E-\uAAAF\uAAB1\uAAB5\uAAB6\uAAB9-\uAABD\uAAC0\uAAC2\uAADB\uAADC\uAAE0-\uAAEA\uAAF2\uAB01-\uAB06\uAB09-\uAB0E\uAB11-\uAB16\uAB20-\uAB26\uAB28-\uAB2E\uABC0-\uABE2\uAC00-\uD7A3\uD7B0-\uD7C6\uD7CB-\uD7FB\uF900-\uFA6D\uFA70-\uFAD9\uFB1D\uFB1F-\uFB28\uFB2A-\uFB36\uFB38-\uFB3C\uFB3E\uFB40\uFB41\uFB43\uFB44\uFB46-\uFBB1\uFBD3-\uFD3D\uFD50-\uFD8F\uFD92-\uFDC7\uFDF0-\uFDFB\uFE70-\uFE74\uFE76-\uFEFC\uFF66-\uFF6F\uFF71-\uFF9D\uFFA0-\uFFBE\uFFC2-\uFFC7\uFFCA-\uFFCF\uFFD2-\uFFD7\uFFDA-\uFFDC",
      'astral': "\uD800[\uDC00-\uDC0B\uDC0D-\uDC26\uDC28-\uDC3A\uDC3C\uDC3D\uDC3F-\uDC4D\uDC50-\uDC5D\uDC80-\uDCFA\uDE80-\uDE9C\uDEA0-\uDED0\uDF00-\uDF1F\uDF2D-\uDF40\uDF42-\uDF49\uDF50-\uDF75\uDF80-\uDF9D\uDFA0-\uDFC3\uDFC8-\uDFCF]|\uD801[\uDC50-\uDC9D\uDD00-\uDD27\uDD30-\uDD63\uDE00-\uDF36\uDF40-\uDF55\uDF60-\uDF67]|\uD802[\uDC00-\uDC05\uDC08\uDC0A-\uDC35\uDC37\uDC38\uDC3C\uDC3F-\uDC55\uDC60-\uDC76\uDC80-\uDC9E\uDCE0-\uDCF2\uDCF4\uDCF5\uDD00-\uDD15\uDD20-\uDD39\uDD80-\uDDB7\uDDBE\uDDBF\uDE00\uDE10-\uDE13\uDE15-\uDE17\uDE19-\uDE35\uDE60-\uDE7C\uDE80-\uDE9C\uDEC0-\uDEC7\uDEC9-\uDEE4\uDF00-\uDF35\uDF40-\uDF55\uDF60-\uDF72\uDF80-\uDF91]|\uD803[\uDC00-\uDC48\uDD00-\uDD23\uDE80-\uDEA9\uDEB0\uDEB1\uDF00-\uDF1C\uDF27\uDF30-\uDF45\uDF70-\uDF81\uDFB0-\uDFC4\uDFE0-\uDFF6]|\uD804[\uDC03-\uDC37\uDC71\uDC72\uDC75\uDC83-\uDCAF\uDCD0-\uDCE8\uDD03-\uDD26\uDD44\uDD47\uDD50-\uDD72\uDD76\uDD83-\uDDB2\uDDC1-\uDDC4\uDDDA\uDDDC\uDE00-\uDE11\uDE13-\uDE2B\uDE80-\uDE86\uDE88\uDE8A-\uDE8D\uDE8F-\uDE9D\uDE9F-\uDEA8\uDEB0-\uDEDE\uDF05-\uDF0C\uDF0F\uDF10\uDF13-\uDF28\uDF2A-\uDF30\uDF32\uDF33\uDF35-\uDF39\uDF3D\uDF50\uDF5D-\uDF61]|\uD805[\uDC00-\uDC34\uDC47-\uDC4A\uDC5F-\uDC61\uDC80-\uDCAF\uDCC4\uDCC5\uDCC7\uDD80-\uDDAE\uDDD8-\uDDDB\uDE00-\uDE2F\uDE44\uDE80-\uDEAA\uDEB8\uDF00-\uDF1A\uDF40-\uDF46]|\uD806[\uDC00-\uDC2B\uDCFF-\uDD06\uDD09\uDD0C-\uDD13\uDD15\uDD16\uDD18-\uDD2F\uDD3F\uDD41\uDDA0-\uDDA7\uDDAA-\uDDD0\uDDE1\uDDE3\uDE00\uDE0B-\uDE32\uDE3A\uDE50\uDE5C-\uDE89\uDE9D\uDEB0-\uDEF8]|\uD807[\uDC00-\uDC08\uDC0A-\uDC2E\uDC40\uDC72-\uDC8F\uDD00-\uDD06\uDD08\uDD09\uDD0B-\uDD30\uDD46\uDD60-\uDD65\uDD67\uDD68\uDD6A-\uDD89\uDD98\uDEE0-\uDEF2\uDFB0]|\uD808[\uDC00-\uDF99]|\uD809[\uDC80-\uDD43]|\uD80B[\uDF90-\uDFF0]|[\uD80C\uD81C-\uD820\uD822\uD840-\uD868\uD86A-\uD86C\uD86F-\uD872\uD874-\uD879\uD880-\uD883][\uDC00-\uDFFF]|\uD80D[\uDC00-\uDC2E]|\uD811[\uDC00-\uDE46]|\uD81A[\uDC00-\uDE38\uDE40-\uDE5E\uDE70-\uDEBE\uDED0-\uDEED\uDF00-\uDF2F\uDF63-\uDF77\uDF7D-\uDF8F]|\uD81B[\uDF00-\uDF4A\uDF50]|\uD821[\uDC00-\uDFF7]|\uD823[\uDC00-\uDCD5\uDD00-\uDD08]|\uD82C[\uDC00-\uDD22\uDD50-\uDD52\uDD64-\uDD67\uDD70-\uDEFB]|\uD82F[\uDC00-\uDC6A\uDC70-\uDC7C\uDC80-\uDC88\uDC90-\uDC99]|\uD837\uDF0A|\uD838[\uDD00-\uDD2C\uDD4E\uDE90-\uDEAD\uDEC0-\uDEEB]|\uD839[\uDFE0-\uDFE6\uDFE8-\uDFEB\uDFED\uDFEE\uDFF0-\uDFFE]|\uD83A[\uDC00-\uDCC4]|\uD83B[\uDE00-\uDE03\uDE05-\uDE1F\uDE21\uDE22\uDE24\uDE27\uDE29-\uDE32\uDE34-\uDE37\uDE39\uDE3B\uDE42\uDE47\uDE49\uDE4B\uDE4D-\uDE4F\uDE51\uDE52\uDE54\uDE57\uDE59\uDE5B\uDE5D\uDE5F\uDE61\uDE62\uDE64\uDE67-\uDE6A\uDE6C-\uDE72\uDE74-\uDE77\uDE79-\uDE7C\uDE7E\uDE80-\uDE89\uDE8B-\uDE9B\uDEA1-\uDEA3\uDEA5-\uDEA9\uDEAB-\uDEBB]|\uD869[\uDC00-\uDEDF\uDF00-\uDFFF]|\uD86D[\uDC00-\uDF38\uDF40-\uDFFF]|\uD86E[\uDC00-\uDC1D\uDC20-\uDFFF]|\uD873[\uDC00-\uDEA1\uDEB0-\uDFFF]|\uD87A[\uDC00-\uDFE0]|\uD87E[\uDC00-\uDE1D]|\uD884[\uDC00-\uDF4A]"
    }, {
      'name': 'Lt',
      'alias': 'Titlecase_Letter',
      'bmp': "\u01C5\u01C8\u01CB\u01F2\u1F88-\u1F8F\u1F98-\u1F9F\u1FA8-\u1FAF\u1FBC\u1FCC\u1FFC"
    }, {
      'name': 'Lu',
      'alias': 'Uppercase_Letter',
      'bmp': "A-Z\xC0-\xD6\xD8-\xDE\u0100\u0102\u0104\u0106\u0108\u010A\u010C\u010E\u0110\u0112\u0114\u0116\u0118\u011A\u011C\u011E\u0120\u0122\u0124\u0126\u0128\u012A\u012C\u012E\u0130\u0132\u0134\u0136\u0139\u013B\u013D\u013F\u0141\u0143\u0145\u0147\u014A\u014C\u014E\u0150\u0152\u0154\u0156\u0158\u015A\u015C\u015E\u0160\u0162\u0164\u0166\u0168\u016A\u016C\u016E\u0170\u0172\u0174\u0176\u0178\u0179\u017B\u017D\u0181\u0182\u0184\u0186\u0187\u0189-\u018B\u018E-\u0191\u0193\u0194\u0196-\u0198\u019C\u019D\u019F\u01A0\u01A2\u01A4\u01A6\u01A7\u01A9\u01AC\u01AE\u01AF\u01B1-\u01B3\u01B5\u01B7\u01B8\u01BC\u01C4\u01C7\u01CA\u01CD\u01CF\u01D1\u01D3\u01D5\u01D7\u01D9\u01DB\u01DE\u01E0\u01E2\u01E4\u01E6\u01E8\u01EA\u01EC\u01EE\u01F1\u01F4\u01F6-\u01F8\u01FA\u01FC\u01FE\u0200\u0202\u0204\u0206\u0208\u020A\u020C\u020E\u0210\u0212\u0214\u0216\u0218\u021A\u021C\u021E\u0220\u0222\u0224\u0226\u0228\u022A\u022C\u022E\u0230\u0232\u023A\u023B\u023D\u023E\u0241\u0243-\u0246\u0248\u024A\u024C\u024E\u0370\u0372\u0376\u037F\u0386\u0388-\u038A\u038C\u038E\u038F\u0391-\u03A1\u03A3-\u03AB\u03CF\u03D2-\u03D4\u03D8\u03DA\u03DC\u03DE\u03E0\u03E2\u03E4\u03E6\u03E8\u03EA\u03EC\u03EE\u03F4\u03F7\u03F9\u03FA\u03FD-\u042F\u0460\u0462\u0464\u0466\u0468\u046A\u046C\u046E\u0470\u0472\u0474\u0476\u0478\u047A\u047C\u047E\u0480\u048A\u048C\u048E\u0490\u0492\u0494\u0496\u0498\u049A\u049C\u049E\u04A0\u04A2\u04A4\u04A6\u04A8\u04AA\u04AC\u04AE\u04B0\u04B2\u04B4\u04B6\u04B8\u04BA\u04BC\u04BE\u04C0\u04C1\u04C3\u04C5\u04C7\u04C9\u04CB\u04CD\u04D0\u04D2\u04D4\u04D6\u04D8\u04DA\u04DC\u04DE\u04E0\u04E2\u04E4\u04E6\u04E8\u04EA\u04EC\u04EE\u04F0\u04F2\u04F4\u04F6\u04F8\u04FA\u04FC\u04FE\u0500\u0502\u0504\u0506\u0508\u050A\u050C\u050E\u0510\u0512\u0514\u0516\u0518\u051A\u051C\u051E\u0520\u0522\u0524\u0526\u0528\u052A\u052C\u052E\u0531-\u0556\u10A0-\u10C5\u10C7\u10CD\u13A0-\u13F5\u1C90-\u1CBA\u1CBD-\u1CBF\u1E00\u1E02\u1E04\u1E06\u1E08\u1E0A\u1E0C\u1E0E\u1E10\u1E12\u1E14\u1E16\u1E18\u1E1A\u1E1C\u1E1E\u1E20\u1E22\u1E24\u1E26\u1E28\u1E2A\u1E2C\u1E2E\u1E30\u1E32\u1E34\u1E36\u1E38\u1E3A\u1E3C\u1E3E\u1E40\u1E42\u1E44\u1E46\u1E48\u1E4A\u1E4C\u1E4E\u1E50\u1E52\u1E54\u1E56\u1E58\u1E5A\u1E5C\u1E5E\u1E60\u1E62\u1E64\u1E66\u1E68\u1E6A\u1E6C\u1E6E\u1E70\u1E72\u1E74\u1E76\u1E78\u1E7A\u1E7C\u1E7E\u1E80\u1E82\u1E84\u1E86\u1E88\u1E8A\u1E8C\u1E8E\u1E90\u1E92\u1E94\u1E9E\u1EA0\u1EA2\u1EA4\u1EA6\u1EA8\u1EAA\u1EAC\u1EAE\u1EB0\u1EB2\u1EB4\u1EB6\u1EB8\u1EBA\u1EBC\u1EBE\u1EC0\u1EC2\u1EC4\u1EC6\u1EC8\u1ECA\u1ECC\u1ECE\u1ED0\u1ED2\u1ED4\u1ED6\u1ED8\u1EDA\u1EDC\u1EDE\u1EE0\u1EE2\u1EE4\u1EE6\u1EE8\u1EEA\u1EEC\u1EEE\u1EF0\u1EF2\u1EF4\u1EF6\u1EF8\u1EFA\u1EFC\u1EFE\u1F08-\u1F0F\u1F18-\u1F1D\u1F28-\u1F2F\u1F38-\u1F3F\u1F48-\u1F4D\u1F59\u1F5B\u1F5D\u1F5F\u1F68-\u1F6F\u1FB8-\u1FBB\u1FC8-\u1FCB\u1FD8-\u1FDB\u1FE8-\u1FEC\u1FF8-\u1FFB\u2102\u2107\u210B-\u210D\u2110-\u2112\u2115\u2119-\u211D\u2124\u2126\u2128\u212A-\u212D\u2130-\u2133\u213E\u213F\u2145\u2183\u2C00-\u2C2F\u2C60\u2C62-\u2C64\u2C67\u2C69\u2C6B\u2C6D-\u2C70\u2C72\u2C75\u2C7E-\u2C80\u2C82\u2C84\u2C86\u2C88\u2C8A\u2C8C\u2C8E\u2C90\u2C92\u2C94\u2C96\u2C98\u2C9A\u2C9C\u2C9E\u2CA0\u2CA2\u2CA4\u2CA6\u2CA8\u2CAA\u2CAC\u2CAE\u2CB0\u2CB2\u2CB4\u2CB6\u2CB8\u2CBA\u2CBC\u2CBE\u2CC0\u2CC2\u2CC4\u2CC6\u2CC8\u2CCA\u2CCC\u2CCE\u2CD0\u2CD2\u2CD4\u2CD6\u2CD8\u2CDA\u2CDC\u2CDE\u2CE0\u2CE2\u2CEB\u2CED\u2CF2\uA640\uA642\uA644\uA646\uA648\uA64A\uA64C\uA64E\uA650\uA652\uA654\uA656\uA658\uA65A\uA65C\uA65E\uA660\uA662\uA664\uA666\uA668\uA66A\uA66C\uA680\uA682\uA684\uA686\uA688\uA68A\uA68C\uA68E\uA690\uA692\uA694\uA696\uA698\uA69A\uA722\uA724\uA726\uA728\uA72A\uA72C\uA72E\uA732\uA734\uA736\uA738\uA73A\uA73C\uA73E\uA740\uA742\uA744\uA746\uA748\uA74A\uA74C\uA74E\uA750\uA752\uA754\uA756\uA758\uA75A\uA75C\uA75E\uA760\uA762\uA764\uA766\uA768\uA76A\uA76C\uA76E\uA779\uA77B\uA77D\uA77E\uA780\uA782\uA784\uA786\uA78B\uA78D\uA790\uA792\uA796\uA798\uA79A\uA79C\uA79E\uA7A0\uA7A2\uA7A4\uA7A6\uA7A8\uA7AA-\uA7AE\uA7B0-\uA7B4\uA7B6\uA7B8\uA7BA\uA7BC\uA7BE\uA7C0\uA7C2\uA7C4-\uA7C7\uA7C9\uA7D0\uA7D6\uA7D8\uA7F5\uFF21-\uFF3A",
      'astral': "\uD801[\uDC00-\uDC27\uDCB0-\uDCD3\uDD70-\uDD7A\uDD7C-\uDD8A\uDD8C-\uDD92\uDD94\uDD95]|\uD803[\uDC80-\uDCB2]|\uD806[\uDCA0-\uDCBF]|\uD81B[\uDE40-\uDE5F]|\uD835[\uDC00-\uDC19\uDC34-\uDC4D\uDC68-\uDC81\uDC9C\uDC9E\uDC9F\uDCA2\uDCA5\uDCA6\uDCA9-\uDCAC\uDCAE-\uDCB5\uDCD0-\uDCE9\uDD04\uDD05\uDD07-\uDD0A\uDD0D-\uDD14\uDD16-\uDD1C\uDD38\uDD39\uDD3B-\uDD3E\uDD40-\uDD44\uDD46\uDD4A-\uDD50\uDD6C-\uDD85\uDDA0-\uDDB9\uDDD4-\uDDED\uDE08-\uDE21\uDE3C-\uDE55\uDE70-\uDE89\uDEA8-\uDEC0\uDEE2-\uDEFA\uDF1C-\uDF34\uDF56-\uDF6E\uDF90-\uDFA8\uDFCA]|\uD83A[\uDD00-\uDD21]"
    }, {
      'name': 'M',
      'alias': 'Mark',
      'bmp': "\u0300-\u036F\u0483-\u0489\u0591-\u05BD\u05BF\u05C1\u05C2\u05C4\u05C5\u05C7\u0610-\u061A\u064B-\u065F\u0670\u06D6-\u06DC\u06DF-\u06E4\u06E7\u06E8\u06EA-\u06ED\u0711\u0730-\u074A\u07A6-\u07B0\u07EB-\u07F3\u07FD\u0816-\u0819\u081B-\u0823\u0825-\u0827\u0829-\u082D\u0859-\u085B\u0898-\u089F\u08CA-\u08E1\u08E3-\u0903\u093A-\u093C\u093E-\u094F\u0951-\u0957\u0962\u0963\u0981-\u0983\u09BC\u09BE-\u09C4\u09C7\u09C8\u09CB-\u09CD\u09D7\u09E2\u09E3\u09FE\u0A01-\u0A03\u0A3C\u0A3E-\u0A42\u0A47\u0A48\u0A4B-\u0A4D\u0A51\u0A70\u0A71\u0A75\u0A81-\u0A83\u0ABC\u0ABE-\u0AC5\u0AC7-\u0AC9\u0ACB-\u0ACD\u0AE2\u0AE3\u0AFA-\u0AFF\u0B01-\u0B03\u0B3C\u0B3E-\u0B44\u0B47\u0B48\u0B4B-\u0B4D\u0B55-\u0B57\u0B62\u0B63\u0B82\u0BBE-\u0BC2\u0BC6-\u0BC8\u0BCA-\u0BCD\u0BD7\u0C00-\u0C04\u0C3C\u0C3E-\u0C44\u0C46-\u0C48\u0C4A-\u0C4D\u0C55\u0C56\u0C62\u0C63\u0C81-\u0C83\u0CBC\u0CBE-\u0CC4\u0CC6-\u0CC8\u0CCA-\u0CCD\u0CD5\u0CD6\u0CE2\u0CE3\u0D00-\u0D03\u0D3B\u0D3C\u0D3E-\u0D44\u0D46-\u0D48\u0D4A-\u0D4D\u0D57\u0D62\u0D63\u0D81-\u0D83\u0DCA\u0DCF-\u0DD4\u0DD6\u0DD8-\u0DDF\u0DF2\u0DF3\u0E31\u0E34-\u0E3A\u0E47-\u0E4E\u0EB1\u0EB4-\u0EBC\u0EC8-\u0ECD\u0F18\u0F19\u0F35\u0F37\u0F39\u0F3E\u0F3F\u0F71-\u0F84\u0F86\u0F87\u0F8D-\u0F97\u0F99-\u0FBC\u0FC6\u102B-\u103E\u1056-\u1059\u105E-\u1060\u1062-\u1064\u1067-\u106D\u1071-\u1074\u1082-\u108D\u108F\u109A-\u109D\u135D-\u135F\u1712-\u1715\u1732-\u1734\u1752\u1753\u1772\u1773\u17B4-\u17D3\u17DD\u180B-\u180D\u180F\u1885\u1886\u18A9\u1920-\u192B\u1930-\u193B\u1A17-\u1A1B\u1A55-\u1A5E\u1A60-\u1A7C\u1A7F\u1AB0-\u1ACE\u1B00-\u1B04\u1B34-\u1B44\u1B6B-\u1B73\u1B80-\u1B82\u1BA1-\u1BAD\u1BE6-\u1BF3\u1C24-\u1C37\u1CD0-\u1CD2\u1CD4-\u1CE8\u1CED\u1CF4\u1CF7-\u1CF9\u1DC0-\u1DFF\u20D0-\u20F0\u2CEF-\u2CF1\u2D7F\u2DE0-\u2DFF\u302A-\u302F\u3099\u309A\uA66F-\uA672\uA674-\uA67D\uA69E\uA69F\uA6F0\uA6F1\uA802\uA806\uA80B\uA823-\uA827\uA82C\uA880\uA881\uA8B4-\uA8C5\uA8E0-\uA8F1\uA8FF\uA926-\uA92D\uA947-\uA953\uA980-\uA983\uA9B3-\uA9C0\uA9E5\uAA29-\uAA36\uAA43\uAA4C\uAA4D\uAA7B-\uAA7D\uAAB0\uAAB2-\uAAB4\uAAB7\uAAB8\uAABE\uAABF\uAAC1\uAAEB-\uAAEF\uAAF5\uAAF6\uABE3-\uABEA\uABEC\uABED\uFB1E\uFE00-\uFE0F\uFE20-\uFE2F",
      'astral': "\uD800[\uDDFD\uDEE0\uDF76-\uDF7A]|\uD802[\uDE01-\uDE03\uDE05\uDE06\uDE0C-\uDE0F\uDE38-\uDE3A\uDE3F\uDEE5\uDEE6]|\uD803[\uDD24-\uDD27\uDEAB\uDEAC\uDF46-\uDF50\uDF82-\uDF85]|\uD804[\uDC00-\uDC02\uDC38-\uDC46\uDC70\uDC73\uDC74\uDC7F-\uDC82\uDCB0-\uDCBA\uDCC2\uDD00-\uDD02\uDD27-\uDD34\uDD45\uDD46\uDD73\uDD80-\uDD82\uDDB3-\uDDC0\uDDC9-\uDDCC\uDDCE\uDDCF\uDE2C-\uDE37\uDE3E\uDEDF-\uDEEA\uDF00-\uDF03\uDF3B\uDF3C\uDF3E-\uDF44\uDF47\uDF48\uDF4B-\uDF4D\uDF57\uDF62\uDF63\uDF66-\uDF6C\uDF70-\uDF74]|\uD805[\uDC35-\uDC46\uDC5E\uDCB0-\uDCC3\uDDAF-\uDDB5\uDDB8-\uDDC0\uDDDC\uDDDD\uDE30-\uDE40\uDEAB-\uDEB7\uDF1D-\uDF2B]|\uD806[\uDC2C-\uDC3A\uDD30-\uDD35\uDD37\uDD38\uDD3B-\uDD3E\uDD40\uDD42\uDD43\uDDD1-\uDDD7\uDDDA-\uDDE0\uDDE4\uDE01-\uDE0A\uDE33-\uDE39\uDE3B-\uDE3E\uDE47\uDE51-\uDE5B\uDE8A-\uDE99]|\uD807[\uDC2F-\uDC36\uDC38-\uDC3F\uDC92-\uDCA7\uDCA9-\uDCB6\uDD31-\uDD36\uDD3A\uDD3C\uDD3D\uDD3F-\uDD45\uDD47\uDD8A-\uDD8E\uDD90\uDD91\uDD93-\uDD97\uDEF3-\uDEF6]|\uD81A[\uDEF0-\uDEF4\uDF30-\uDF36]|\uD81B[\uDF4F\uDF51-\uDF87\uDF8F-\uDF92\uDFE4\uDFF0\uDFF1]|\uD82F[\uDC9D\uDC9E]|\uD833[\uDF00-\uDF2D\uDF30-\uDF46]|\uD834[\uDD65-\uDD69\uDD6D-\uDD72\uDD7B-\uDD82\uDD85-\uDD8B\uDDAA-\uDDAD\uDE42-\uDE44]|\uD836[\uDE00-\uDE36\uDE3B-\uDE6C\uDE75\uDE84\uDE9B-\uDE9F\uDEA1-\uDEAF]|\uD838[\uDC00-\uDC06\uDC08-\uDC18\uDC1B-\uDC21\uDC23\uDC24\uDC26-\uDC2A\uDD30-\uDD36\uDEAE\uDEEC-\uDEEF]|\uD83A[\uDCD0-\uDCD6\uDD44-\uDD4A]|\uDB40[\uDD00-\uDDEF]"
    }, {
      'name': 'Mc',
      'alias': 'Spacing_Mark',
      'bmp': "\u0903\u093B\u093E-\u0940\u0949-\u094C\u094E\u094F\u0982\u0983\u09BE-\u09C0\u09C7\u09C8\u09CB\u09CC\u09D7\u0A03\u0A3E-\u0A40\u0A83\u0ABE-\u0AC0\u0AC9\u0ACB\u0ACC\u0B02\u0B03\u0B3E\u0B40\u0B47\u0B48\u0B4B\u0B4C\u0B57\u0BBE\u0BBF\u0BC1\u0BC2\u0BC6-\u0BC8\u0BCA-\u0BCC\u0BD7\u0C01-\u0C03\u0C41-\u0C44\u0C82\u0C83\u0CBE\u0CC0-\u0CC4\u0CC7\u0CC8\u0CCA\u0CCB\u0CD5\u0CD6\u0D02\u0D03\u0D3E-\u0D40\u0D46-\u0D48\u0D4A-\u0D4C\u0D57\u0D82\u0D83\u0DCF-\u0DD1\u0DD8-\u0DDF\u0DF2\u0DF3\u0F3E\u0F3F\u0F7F\u102B\u102C\u1031\u1038\u103B\u103C\u1056\u1057\u1062-\u1064\u1067-\u106D\u1083\u1084\u1087-\u108C\u108F\u109A-\u109C\u1715\u1734\u17B6\u17BE-\u17C5\u17C7\u17C8\u1923-\u1926\u1929-\u192B\u1930\u1931\u1933-\u1938\u1A19\u1A1A\u1A55\u1A57\u1A61\u1A63\u1A64\u1A6D-\u1A72\u1B04\u1B35\u1B3B\u1B3D-\u1B41\u1B43\u1B44\u1B82\u1BA1\u1BA6\u1BA7\u1BAA\u1BE7\u1BEA-\u1BEC\u1BEE\u1BF2\u1BF3\u1C24-\u1C2B\u1C34\u1C35\u1CE1\u1CF7\u302E\u302F\uA823\uA824\uA827\uA880\uA881\uA8B4-\uA8C3\uA952\uA953\uA983\uA9B4\uA9B5\uA9BA\uA9BB\uA9BE-\uA9C0\uAA2F\uAA30\uAA33\uAA34\uAA4D\uAA7B\uAA7D\uAAEB\uAAEE\uAAEF\uAAF5\uABE3\uABE4\uABE6\uABE7\uABE9\uABEA\uABEC",
      'astral': "\uD804[\uDC00\uDC02\uDC82\uDCB0-\uDCB2\uDCB7\uDCB8\uDD2C\uDD45\uDD46\uDD82\uDDB3-\uDDB5\uDDBF\uDDC0\uDDCE\uDE2C-\uDE2E\uDE32\uDE33\uDE35\uDEE0-\uDEE2\uDF02\uDF03\uDF3E\uDF3F\uDF41-\uDF44\uDF47\uDF48\uDF4B-\uDF4D\uDF57\uDF62\uDF63]|\uD805[\uDC35-\uDC37\uDC40\uDC41\uDC45\uDCB0-\uDCB2\uDCB9\uDCBB-\uDCBE\uDCC1\uDDAF-\uDDB1\uDDB8-\uDDBB\uDDBE\uDE30-\uDE32\uDE3B\uDE3C\uDE3E\uDEAC\uDEAE\uDEAF\uDEB6\uDF20\uDF21\uDF26]|\uD806[\uDC2C-\uDC2E\uDC38\uDD30-\uDD35\uDD37\uDD38\uDD3D\uDD40\uDD42\uDDD1-\uDDD3\uDDDC-\uDDDF\uDDE4\uDE39\uDE57\uDE58\uDE97]|\uD807[\uDC2F\uDC3E\uDCA9\uDCB1\uDCB4\uDD8A-\uDD8E\uDD93\uDD94\uDD96\uDEF5\uDEF6]|\uD81B[\uDF51-\uDF87\uDFF0\uDFF1]|\uD834[\uDD65\uDD66\uDD6D-\uDD72]"
    }, {
      'name': 'Me',
      'alias': 'Enclosing_Mark',
      'bmp': "\u0488\u0489\u1ABE\u20DD-\u20E0\u20E2-\u20E4\uA670-\uA672"
    }, {
      'name': 'Mn',
      'alias': 'Nonspacing_Mark',
      'bmp': "\u0300-\u036F\u0483-\u0487\u0591-\u05BD\u05BF\u05C1\u05C2\u05C4\u05C5\u05C7\u0610-\u061A\u064B-\u065F\u0670\u06D6-\u06DC\u06DF-\u06E4\u06E7\u06E8\u06EA-\u06ED\u0711\u0730-\u074A\u07A6-\u07B0\u07EB-\u07F3\u07FD\u0816-\u0819\u081B-\u0823\u0825-\u0827\u0829-\u082D\u0859-\u085B\u0898-\u089F\u08CA-\u08E1\u08E3-\u0902\u093A\u093C\u0941-\u0948\u094D\u0951-\u0957\u0962\u0963\u0981\u09BC\u09C1-\u09C4\u09CD\u09E2\u09E3\u09FE\u0A01\u0A02\u0A3C\u0A41\u0A42\u0A47\u0A48\u0A4B-\u0A4D\u0A51\u0A70\u0A71\u0A75\u0A81\u0A82\u0ABC\u0AC1-\u0AC5\u0AC7\u0AC8\u0ACD\u0AE2\u0AE3\u0AFA-\u0AFF\u0B01\u0B3C\u0B3F\u0B41-\u0B44\u0B4D\u0B55\u0B56\u0B62\u0B63\u0B82\u0BC0\u0BCD\u0C00\u0C04\u0C3C\u0C3E-\u0C40\u0C46-\u0C48\u0C4A-\u0C4D\u0C55\u0C56\u0C62\u0C63\u0C81\u0CBC\u0CBF\u0CC6\u0CCC\u0CCD\u0CE2\u0CE3\u0D00\u0D01\u0D3B\u0D3C\u0D41-\u0D44\u0D4D\u0D62\u0D63\u0D81\u0DCA\u0DD2-\u0DD4\u0DD6\u0E31\u0E34-\u0E3A\u0E47-\u0E4E\u0EB1\u0EB4-\u0EBC\u0EC8-\u0ECD\u0F18\u0F19\u0F35\u0F37\u0F39\u0F71-\u0F7E\u0F80-\u0F84\u0F86\u0F87\u0F8D-\u0F97\u0F99-\u0FBC\u0FC6\u102D-\u1030\u1032-\u1037\u1039\u103A\u103D\u103E\u1058\u1059\u105E-\u1060\u1071-\u1074\u1082\u1085\u1086\u108D\u109D\u135D-\u135F\u1712-\u1714\u1732\u1733\u1752\u1753\u1772\u1773\u17B4\u17B5\u17B7-\u17BD\u17C6\u17C9-\u17D3\u17DD\u180B-\u180D\u180F\u1885\u1886\u18A9\u1920-\u1922\u1927\u1928\u1932\u1939-\u193B\u1A17\u1A18\u1A1B\u1A56\u1A58-\u1A5E\u1A60\u1A62\u1A65-\u1A6C\u1A73-\u1A7C\u1A7F\u1AB0-\u1ABD\u1ABF-\u1ACE\u1B00-\u1B03\u1B34\u1B36-\u1B3A\u1B3C\u1B42\u1B6B-\u1B73\u1B80\u1B81\u1BA2-\u1BA5\u1BA8\u1BA9\u1BAB-\u1BAD\u1BE6\u1BE8\u1BE9\u1BED\u1BEF-\u1BF1\u1C2C-\u1C33\u1C36\u1C37\u1CD0-\u1CD2\u1CD4-\u1CE0\u1CE2-\u1CE8\u1CED\u1CF4\u1CF8\u1CF9\u1DC0-\u1DFF\u20D0-\u20DC\u20E1\u20E5-\u20F0\u2CEF-\u2CF1\u2D7F\u2DE0-\u2DFF\u302A-\u302D\u3099\u309A\uA66F\uA674-\uA67D\uA69E\uA69F\uA6F0\uA6F1\uA802\uA806\uA80B\uA825\uA826\uA82C\uA8C4\uA8C5\uA8E0-\uA8F1\uA8FF\uA926-\uA92D\uA947-\uA951\uA980-\uA982\uA9B3\uA9B6-\uA9B9\uA9BC\uA9BD\uA9E5\uAA29-\uAA2E\uAA31\uAA32\uAA35\uAA36\uAA43\uAA4C\uAA7C\uAAB0\uAAB2-\uAAB4\uAAB7\uAAB8\uAABE\uAABF\uAAC1\uAAEC\uAAED\uAAF6\uABE5\uABE8\uABED\uFB1E\uFE00-\uFE0F\uFE20-\uFE2F",
      'astral': "\uD800[\uDDFD\uDEE0\uDF76-\uDF7A]|\uD802[\uDE01-\uDE03\uDE05\uDE06\uDE0C-\uDE0F\uDE38-\uDE3A\uDE3F\uDEE5\uDEE6]|\uD803[\uDD24-\uDD27\uDEAB\uDEAC\uDF46-\uDF50\uDF82-\uDF85]|\uD804[\uDC01\uDC38-\uDC46\uDC70\uDC73\uDC74\uDC7F-\uDC81\uDCB3-\uDCB6\uDCB9\uDCBA\uDCC2\uDD00-\uDD02\uDD27-\uDD2B\uDD2D-\uDD34\uDD73\uDD80\uDD81\uDDB6-\uDDBE\uDDC9-\uDDCC\uDDCF\uDE2F-\uDE31\uDE34\uDE36\uDE37\uDE3E\uDEDF\uDEE3-\uDEEA\uDF00\uDF01\uDF3B\uDF3C\uDF40\uDF66-\uDF6C\uDF70-\uDF74]|\uD805[\uDC38-\uDC3F\uDC42-\uDC44\uDC46\uDC5E\uDCB3-\uDCB8\uDCBA\uDCBF\uDCC0\uDCC2\uDCC3\uDDB2-\uDDB5\uDDBC\uDDBD\uDDBF\uDDC0\uDDDC\uDDDD\uDE33-\uDE3A\uDE3D\uDE3F\uDE40\uDEAB\uDEAD\uDEB0-\uDEB5\uDEB7\uDF1D-\uDF1F\uDF22-\uDF25\uDF27-\uDF2B]|\uD806[\uDC2F-\uDC37\uDC39\uDC3A\uDD3B\uDD3C\uDD3E\uDD43\uDDD4-\uDDD7\uDDDA\uDDDB\uDDE0\uDE01-\uDE0A\uDE33-\uDE38\uDE3B-\uDE3E\uDE47\uDE51-\uDE56\uDE59-\uDE5B\uDE8A-\uDE96\uDE98\uDE99]|\uD807[\uDC30-\uDC36\uDC38-\uDC3D\uDC3F\uDC92-\uDCA7\uDCAA-\uDCB0\uDCB2\uDCB3\uDCB5\uDCB6\uDD31-\uDD36\uDD3A\uDD3C\uDD3D\uDD3F-\uDD45\uDD47\uDD90\uDD91\uDD95\uDD97\uDEF3\uDEF4]|\uD81A[\uDEF0-\uDEF4\uDF30-\uDF36]|\uD81B[\uDF4F\uDF8F-\uDF92\uDFE4]|\uD82F[\uDC9D\uDC9E]|\uD833[\uDF00-\uDF2D\uDF30-\uDF46]|\uD834[\uDD67-\uDD69\uDD7B-\uDD82\uDD85-\uDD8B\uDDAA-\uDDAD\uDE42-\uDE44]|\uD836[\uDE00-\uDE36\uDE3B-\uDE6C\uDE75\uDE84\uDE9B-\uDE9F\uDEA1-\uDEAF]|\uD838[\uDC00-\uDC06\uDC08-\uDC18\uDC1B-\uDC21\uDC23\uDC24\uDC26-\uDC2A\uDD30-\uDD36\uDEAE\uDEEC-\uDEEF]|\uD83A[\uDCD0-\uDCD6\uDD44-\uDD4A]|\uDB40[\uDD00-\uDDEF]"
    }, {
      'name': 'N',
      'alias': 'Number',
      'bmp': "0-9\xB2\xB3\xB9\xBC-\xBE\u0660-\u0669\u06F0-\u06F9\u07C0-\u07C9\u0966-\u096F\u09E6-\u09EF\u09F4-\u09F9\u0A66-\u0A6F\u0AE6-\u0AEF\u0B66-\u0B6F\u0B72-\u0B77\u0BE6-\u0BF2\u0C66-\u0C6F\u0C78-\u0C7E\u0CE6-\u0CEF\u0D58-\u0D5E\u0D66-\u0D78\u0DE6-\u0DEF\u0E50-\u0E59\u0ED0-\u0ED9\u0F20-\u0F33\u1040-\u1049\u1090-\u1099\u1369-\u137C\u16EE-\u16F0\u17E0-\u17E9\u17F0-\u17F9\u1810-\u1819\u1946-\u194F\u19D0-\u19DA\u1A80-\u1A89\u1A90-\u1A99\u1B50-\u1B59\u1BB0-\u1BB9\u1C40-\u1C49\u1C50-\u1C59\u2070\u2074-\u2079\u2080-\u2089\u2150-\u2182\u2185-\u2189\u2460-\u249B\u24EA-\u24FF\u2776-\u2793\u2CFD\u3007\u3021-\u3029\u3038-\u303A\u3192-\u3195\u3220-\u3229\u3248-\u324F\u3251-\u325F\u3280-\u3289\u32B1-\u32BF\uA620-\uA629\uA6E6-\uA6EF\uA830-\uA835\uA8D0-\uA8D9\uA900-\uA909\uA9D0-\uA9D9\uA9F0-\uA9F9\uAA50-\uAA59\uABF0-\uABF9\uFF10-\uFF19",
      'astral': "\uD800[\uDD07-\uDD33\uDD40-\uDD78\uDD8A\uDD8B\uDEE1-\uDEFB\uDF20-\uDF23\uDF41\uDF4A\uDFD1-\uDFD5]|\uD801[\uDCA0-\uDCA9]|\uD802[\uDC58-\uDC5F\uDC79-\uDC7F\uDCA7-\uDCAF\uDCFB-\uDCFF\uDD16-\uDD1B\uDDBC\uDDBD\uDDC0-\uDDCF\uDDD2-\uDDFF\uDE40-\uDE48\uDE7D\uDE7E\uDE9D-\uDE9F\uDEEB-\uDEEF\uDF58-\uDF5F\uDF78-\uDF7F\uDFA9-\uDFAF]|\uD803[\uDCFA-\uDCFF\uDD30-\uDD39\uDE60-\uDE7E\uDF1D-\uDF26\uDF51-\uDF54\uDFC5-\uDFCB]|\uD804[\uDC52-\uDC6F\uDCF0-\uDCF9\uDD36-\uDD3F\uDDD0-\uDDD9\uDDE1-\uDDF4\uDEF0-\uDEF9]|\uD805[\uDC50-\uDC59\uDCD0-\uDCD9\uDE50-\uDE59\uDEC0-\uDEC9\uDF30-\uDF3B]|\uD806[\uDCE0-\uDCF2\uDD50-\uDD59]|\uD807[\uDC50-\uDC6C\uDD50-\uDD59\uDDA0-\uDDA9\uDFC0-\uDFD4]|\uD809[\uDC00-\uDC6E]|\uD81A[\uDE60-\uDE69\uDEC0-\uDEC9\uDF50-\uDF59\uDF5B-\uDF61]|\uD81B[\uDE80-\uDE96]|\uD834[\uDEE0-\uDEF3\uDF60-\uDF78]|\uD835[\uDFCE-\uDFFF]|\uD838[\uDD40-\uDD49\uDEF0-\uDEF9]|\uD83A[\uDCC7-\uDCCF\uDD50-\uDD59]|\uD83B[\uDC71-\uDCAB\uDCAD-\uDCAF\uDCB1-\uDCB4\uDD01-\uDD2D\uDD2F-\uDD3D]|\uD83C[\uDD00-\uDD0C]|\uD83E[\uDFF0-\uDFF9]"
    }, {
      'name': 'Nd',
      'alias': 'Decimal_Number',
      'bmp': "0-9\u0660-\u0669\u06F0-\u06F9\u07C0-\u07C9\u0966-\u096F\u09E6-\u09EF\u0A66-\u0A6F\u0AE6-\u0AEF\u0B66-\u0B6F\u0BE6-\u0BEF\u0C66-\u0C6F\u0CE6-\u0CEF\u0D66-\u0D6F\u0DE6-\u0DEF\u0E50-\u0E59\u0ED0-\u0ED9\u0F20-\u0F29\u1040-\u1049\u1090-\u1099\u17E0-\u17E9\u1810-\u1819\u1946-\u194F\u19D0-\u19D9\u1A80-\u1A89\u1A90-\u1A99\u1B50-\u1B59\u1BB0-\u1BB9\u1C40-\u1C49\u1C50-\u1C59\uA620-\uA629\uA8D0-\uA8D9\uA900-\uA909\uA9D0-\uA9D9\uA9F0-\uA9F9\uAA50-\uAA59\uABF0-\uABF9\uFF10-\uFF19",
      'astral': "\uD801[\uDCA0-\uDCA9]|\uD803[\uDD30-\uDD39]|\uD804[\uDC66-\uDC6F\uDCF0-\uDCF9\uDD36-\uDD3F\uDDD0-\uDDD9\uDEF0-\uDEF9]|\uD805[\uDC50-\uDC59\uDCD0-\uDCD9\uDE50-\uDE59\uDEC0-\uDEC9\uDF30-\uDF39]|\uD806[\uDCE0-\uDCE9\uDD50-\uDD59]|\uD807[\uDC50-\uDC59\uDD50-\uDD59\uDDA0-\uDDA9]|\uD81A[\uDE60-\uDE69\uDEC0-\uDEC9\uDF50-\uDF59]|\uD835[\uDFCE-\uDFFF]|\uD838[\uDD40-\uDD49\uDEF0-\uDEF9]|\uD83A[\uDD50-\uDD59]|\uD83E[\uDFF0-\uDFF9]"
    }, {
      'name': 'Nl',
      'alias': 'Letter_Number',
      'bmp': "\u16EE-\u16F0\u2160-\u2182\u2185-\u2188\u3007\u3021-\u3029\u3038-\u303A\uA6E6-\uA6EF",
      'astral': "\uD800[\uDD40-\uDD74\uDF41\uDF4A\uDFD1-\uDFD5]|\uD809[\uDC00-\uDC6E]"
    }, {
      'name': 'No',
      'alias': 'Other_Number',
      'bmp': "\xB2\xB3\xB9\xBC-\xBE\u09F4-\u09F9\u0B72-\u0B77\u0BF0-\u0BF2\u0C78-\u0C7E\u0D58-\u0D5E\u0D70-\u0D78\u0F2A-\u0F33\u1369-\u137C\u17F0-\u17F9\u19DA\u2070\u2074-\u2079\u2080-\u2089\u2150-\u215F\u2189\u2460-\u249B\u24EA-\u24FF\u2776-\u2793\u2CFD\u3192-\u3195\u3220-\u3229\u3248-\u324F\u3251-\u325F\u3280-\u3289\u32B1-\u32BF\uA830-\uA835",
      'astral': "\uD800[\uDD07-\uDD33\uDD75-\uDD78\uDD8A\uDD8B\uDEE1-\uDEFB\uDF20-\uDF23]|\uD802[\uDC58-\uDC5F\uDC79-\uDC7F\uDCA7-\uDCAF\uDCFB-\uDCFF\uDD16-\uDD1B\uDDBC\uDDBD\uDDC0-\uDDCF\uDDD2-\uDDFF\uDE40-\uDE48\uDE7D\uDE7E\uDE9D-\uDE9F\uDEEB-\uDEEF\uDF58-\uDF5F\uDF78-\uDF7F\uDFA9-\uDFAF]|\uD803[\uDCFA-\uDCFF\uDE60-\uDE7E\uDF1D-\uDF26\uDF51-\uDF54\uDFC5-\uDFCB]|\uD804[\uDC52-\uDC65\uDDE1-\uDDF4]|\uD805[\uDF3A\uDF3B]|\uD806[\uDCEA-\uDCF2]|\uD807[\uDC5A-\uDC6C\uDFC0-\uDFD4]|\uD81A[\uDF5B-\uDF61]|\uD81B[\uDE80-\uDE96]|\uD834[\uDEE0-\uDEF3\uDF60-\uDF78]|\uD83A[\uDCC7-\uDCCF]|\uD83B[\uDC71-\uDCAB\uDCAD-\uDCAF\uDCB1-\uDCB4\uDD01-\uDD2D\uDD2F-\uDD3D]|\uD83C[\uDD00-\uDD0C]"
    }, {
      'name': 'P',
      'alias': 'Punctuation',
      'bmp': "!-#%-\\*,-\\/:;\\?@\\[-\\]_\\{\\}\xA1\xA7\xAB\xB6\xB7\xBB\xBF\u037E\u0387\u055A-\u055F\u0589\u058A\u05BE\u05C0\u05C3\u05C6\u05F3\u05F4\u0609\u060A\u060C\u060D\u061B\u061D-\u061F\u066A-\u066D\u06D4\u0700-\u070D\u07F7-\u07F9\u0830-\u083E\u085E\u0964\u0965\u0970\u09FD\u0A76\u0AF0\u0C77\u0C84\u0DF4\u0E4F\u0E5A\u0E5B\u0F04-\u0F12\u0F14\u0F3A-\u0F3D\u0F85\u0FD0-\u0FD4\u0FD9\u0FDA\u104A-\u104F\u10FB\u1360-\u1368\u1400\u166E\u169B\u169C\u16EB-\u16ED\u1735\u1736\u17D4-\u17D6\u17D8-\u17DA\u1800-\u180A\u1944\u1945\u1A1E\u1A1F\u1AA0-\u1AA6\u1AA8-\u1AAD\u1B5A-\u1B60\u1B7D\u1B7E\u1BFC-\u1BFF\u1C3B-\u1C3F\u1C7E\u1C7F\u1CC0-\u1CC7\u1CD3\u2010-\u2027\u2030-\u2043\u2045-\u2051\u2053-\u205E\u207D\u207E\u208D\u208E\u2308-\u230B\u2329\u232A\u2768-\u2775\u27C5\u27C6\u27E6-\u27EF\u2983-\u2998\u29D8-\u29DB\u29FC\u29FD\u2CF9-\u2CFC\u2CFE\u2CFF\u2D70\u2E00-\u2E2E\u2E30-\u2E4F\u2E52-\u2E5D\u3001-\u3003\u3008-\u3011\u3014-\u301F\u3030\u303D\u30A0\u30FB\uA4FE\uA4FF\uA60D-\uA60F\uA673\uA67E\uA6F2-\uA6F7\uA874-\uA877\uA8CE\uA8CF\uA8F8-\uA8FA\uA8FC\uA92E\uA92F\uA95F\uA9C1-\uA9CD\uA9DE\uA9DF\uAA5C-\uAA5F\uAADE\uAADF\uAAF0\uAAF1\uABEB\uFD3E\uFD3F\uFE10-\uFE19\uFE30-\uFE52\uFE54-\uFE61\uFE63\uFE68\uFE6A\uFE6B\uFF01-\uFF03\uFF05-\uFF0A\uFF0C-\uFF0F\uFF1A\uFF1B\uFF1F\uFF20\uFF3B-\uFF3D\uFF3F\uFF5B\uFF5D\uFF5F-\uFF65",
      'astral': "\uD800[\uDD00-\uDD02\uDF9F\uDFD0]|\uD801\uDD6F|\uD802[\uDC57\uDD1F\uDD3F\uDE50-\uDE58\uDE7F\uDEF0-\uDEF6\uDF39-\uDF3F\uDF99-\uDF9C]|\uD803[\uDEAD\uDF55-\uDF59\uDF86-\uDF89]|\uD804[\uDC47-\uDC4D\uDCBB\uDCBC\uDCBE-\uDCC1\uDD40-\uDD43\uDD74\uDD75\uDDC5-\uDDC8\uDDCD\uDDDB\uDDDD-\uDDDF\uDE38-\uDE3D\uDEA9]|\uD805[\uDC4B-\uDC4F\uDC5A\uDC5B\uDC5D\uDCC6\uDDC1-\uDDD7\uDE41-\uDE43\uDE60-\uDE6C\uDEB9\uDF3C-\uDF3E]|\uD806[\uDC3B\uDD44-\uDD46\uDDE2\uDE3F-\uDE46\uDE9A-\uDE9C\uDE9E-\uDEA2]|\uD807[\uDC41-\uDC45\uDC70\uDC71\uDEF7\uDEF8\uDFFF]|\uD809[\uDC70-\uDC74]|\uD80B[\uDFF1\uDFF2]|\uD81A[\uDE6E\uDE6F\uDEF5\uDF37-\uDF3B\uDF44]|\uD81B[\uDE97-\uDE9A\uDFE2]|\uD82F\uDC9F|\uD836[\uDE87-\uDE8B]|\uD83A[\uDD5E\uDD5F]"
    }, {
      'name': 'Pc',
      'alias': 'Connector_Punctuation',
      'bmp': "_\u203F\u2040\u2054\uFE33\uFE34\uFE4D-\uFE4F\uFF3F"
    }, {
      'name': 'Pd',
      'alias': 'Dash_Punctuation',
      'bmp': "\\-\u058A\u05BE\u1400\u1806\u2010-\u2015\u2E17\u2E1A\u2E3A\u2E3B\u2E40\u2E5D\u301C\u3030\u30A0\uFE31\uFE32\uFE58\uFE63\uFF0D",
      'astral': "\uD803\uDEAD"
    }, {
      'name': 'Pe',
      'alias': 'Close_Punctuation',
      'bmp': "\\)\\]\\}\u0F3B\u0F3D\u169C\u2046\u207E\u208E\u2309\u230B\u232A\u2769\u276B\u276D\u276F\u2771\u2773\u2775\u27C6\u27E7\u27E9\u27EB\u27ED\u27EF\u2984\u2986\u2988\u298A\u298C\u298E\u2990\u2992\u2994\u2996\u2998\u29D9\u29DB\u29FD\u2E23\u2E25\u2E27\u2E29\u2E56\u2E58\u2E5A\u2E5C\u3009\u300B\u300D\u300F\u3011\u3015\u3017\u3019\u301B\u301E\u301F\uFD3E\uFE18\uFE36\uFE38\uFE3A\uFE3C\uFE3E\uFE40\uFE42\uFE44\uFE48\uFE5A\uFE5C\uFE5E\uFF09\uFF3D\uFF5D\uFF60\uFF63"
    }, {
      'name': 'Pf',
      'alias': 'Final_Punctuation',
      'bmp': "\xBB\u2019\u201D\u203A\u2E03\u2E05\u2E0A\u2E0D\u2E1D\u2E21"
    }, {
      'name': 'Pi',
      'alias': 'Initial_Punctuation',
      'bmp': "\xAB\u2018\u201B\u201C\u201F\u2039\u2E02\u2E04\u2E09\u2E0C\u2E1C\u2E20"
    }, {
      'name': 'Po',
      'alias': 'Other_Punctuation',
      'bmp': "!-#%-'\\*,\\.\\/:;\\?@\\\xA1\xA7\xB6\xB7\xBF\u037E\u0387\u055A-\u055F\u0589\u05C0\u05C3\u05C6\u05F3\u05F4\u0609\u060A\u060C\u060D\u061B\u061D-\u061F\u066A-\u066D\u06D4\u0700-\u070D\u07F7-\u07F9\u0830-\u083E\u085E\u0964\u0965\u0970\u09FD\u0A76\u0AF0\u0C77\u0C84\u0DF4\u0E4F\u0E5A\u0E5B\u0F04-\u0F12\u0F14\u0F85\u0FD0-\u0FD4\u0FD9\u0FDA\u104A-\u104F\u10FB\u1360-\u1368\u166E\u16EB-\u16ED\u1735\u1736\u17D4-\u17D6\u17D8-\u17DA\u1800-\u1805\u1807-\u180A\u1944\u1945\u1A1E\u1A1F\u1AA0-\u1AA6\u1AA8-\u1AAD\u1B5A-\u1B60\u1B7D\u1B7E\u1BFC-\u1BFF\u1C3B-\u1C3F\u1C7E\u1C7F\u1CC0-\u1CC7\u1CD3\u2016\u2017\u2020-\u2027\u2030-\u2038\u203B-\u203E\u2041-\u2043\u2047-\u2051\u2053\u2055-\u205E\u2CF9-\u2CFC\u2CFE\u2CFF\u2D70\u2E00\u2E01\u2E06-\u2E08\u2E0B\u2E0E-\u2E16\u2E18\u2E19\u2E1B\u2E1E\u2E1F\u2E2A-\u2E2E\u2E30-\u2E39\u2E3C-\u2E3F\u2E41\u2E43-\u2E4F\u2E52-\u2E54\u3001-\u3003\u303D\u30FB\uA4FE\uA4FF\uA60D-\uA60F\uA673\uA67E\uA6F2-\uA6F7\uA874-\uA877\uA8CE\uA8CF\uA8F8-\uA8FA\uA8FC\uA92E\uA92F\uA95F\uA9C1-\uA9CD\uA9DE\uA9DF\uAA5C-\uAA5F\uAADE\uAADF\uAAF0\uAAF1\uABEB\uFE10-\uFE16\uFE19\uFE30\uFE45\uFE46\uFE49-\uFE4C\uFE50-\uFE52\uFE54-\uFE57\uFE5F-\uFE61\uFE68\uFE6A\uFE6B\uFF01-\uFF03\uFF05-\uFF07\uFF0A\uFF0C\uFF0E\uFF0F\uFF1A\uFF1B\uFF1F\uFF20\uFF3C\uFF61\uFF64\uFF65",
      'astral': "\uD800[\uDD00-\uDD02\uDF9F\uDFD0]|\uD801\uDD6F|\uD802[\uDC57\uDD1F\uDD3F\uDE50-\uDE58\uDE7F\uDEF0-\uDEF6\uDF39-\uDF3F\uDF99-\uDF9C]|\uD803[\uDF55-\uDF59\uDF86-\uDF89]|\uD804[\uDC47-\uDC4D\uDCBB\uDCBC\uDCBE-\uDCC1\uDD40-\uDD43\uDD74\uDD75\uDDC5-\uDDC8\uDDCD\uDDDB\uDDDD-\uDDDF\uDE38-\uDE3D\uDEA9]|\uD805[\uDC4B-\uDC4F\uDC5A\uDC5B\uDC5D\uDCC6\uDDC1-\uDDD7\uDE41-\uDE43\uDE60-\uDE6C\uDEB9\uDF3C-\uDF3E]|\uD806[\uDC3B\uDD44-\uDD46\uDDE2\uDE3F-\uDE46\uDE9A-\uDE9C\uDE9E-\uDEA2]|\uD807[\uDC41-\uDC45\uDC70\uDC71\uDEF7\uDEF8\uDFFF]|\uD809[\uDC70-\uDC74]|\uD80B[\uDFF1\uDFF2]|\uD81A[\uDE6E\uDE6F\uDEF5\uDF37-\uDF3B\uDF44]|\uD81B[\uDE97-\uDE9A\uDFE2]|\uD82F\uDC9F|\uD836[\uDE87-\uDE8B]|\uD83A[\uDD5E\uDD5F]"
    }, {
      'name': 'Ps',
      'alias': 'Open_Punctuation',
      'bmp': "\\(\\[\\{\u0F3A\u0F3C\u169B\u201A\u201E\u2045\u207D\u208D\u2308\u230A\u2329\u2768\u276A\u276C\u276E\u2770\u2772\u2774\u27C5\u27E6\u27E8\u27EA\u27EC\u27EE\u2983\u2985\u2987\u2989\u298B\u298D\u298F\u2991\u2993\u2995\u2997\u29D8\u29DA\u29FC\u2E22\u2E24\u2E26\u2E28\u2E42\u2E55\u2E57\u2E59\u2E5B\u3008\u300A\u300C\u300E\u3010\u3014\u3016\u3018\u301A\u301D\uFD3F\uFE17\uFE35\uFE37\uFE39\uFE3B\uFE3D\uFE3F\uFE41\uFE43\uFE47\uFE59\uFE5B\uFE5D\uFF08\uFF3B\uFF5B\uFF5F\uFF62"
    }, {
      'name': 'S',
      'alias': 'Symbol',
      'bmp': "\\$\\+<->\\^`\\|~\xA2-\xA6\xA8\xA9\xAC\xAE-\xB1\xB4\xB8\xD7\xF7\u02C2-\u02C5\u02D2-\u02DF\u02E5-\u02EB\u02ED\u02EF-\u02FF\u0375\u0384\u0385\u03F6\u0482\u058D-\u058F\u0606-\u0608\u060B\u060E\u060F\u06DE\u06E9\u06FD\u06FE\u07F6\u07FE\u07FF\u0888\u09F2\u09F3\u09FA\u09FB\u0AF1\u0B70\u0BF3-\u0BFA\u0C7F\u0D4F\u0D79\u0E3F\u0F01-\u0F03\u0F13\u0F15-\u0F17\u0F1A-\u0F1F\u0F34\u0F36\u0F38\u0FBE-\u0FC5\u0FC7-\u0FCC\u0FCE\u0FCF\u0FD5-\u0FD8\u109E\u109F\u1390-\u1399\u166D\u17DB\u1940\u19DE-\u19FF\u1B61-\u1B6A\u1B74-\u1B7C\u1FBD\u1FBF-\u1FC1\u1FCD-\u1FCF\u1FDD-\u1FDF\u1FED-\u1FEF\u1FFD\u1FFE\u2044\u2052\u207A-\u207C\u208A-\u208C\u20A0-\u20C0\u2100\u2101\u2103-\u2106\u2108\u2109\u2114\u2116-\u2118\u211E-\u2123\u2125\u2127\u2129\u212E\u213A\u213B\u2140-\u2144\u214A-\u214D\u214F\u218A\u218B\u2190-\u2307\u230C-\u2328\u232B-\u2426\u2440-\u244A\u249C-\u24E9\u2500-\u2767\u2794-\u27C4\u27C7-\u27E5\u27F0-\u2982\u2999-\u29D7\u29DC-\u29FB\u29FE-\u2B73\u2B76-\u2B95\u2B97-\u2BFF\u2CE5-\u2CEA\u2E50\u2E51\u2E80-\u2E99\u2E9B-\u2EF3\u2F00-\u2FD5\u2FF0-\u2FFB\u3004\u3012\u3013\u3020\u3036\u3037\u303E\u303F\u309B\u309C\u3190\u3191\u3196-\u319F\u31C0-\u31E3\u3200-\u321E\u322A-\u3247\u3250\u3260-\u327F\u328A-\u32B0\u32C0-\u33FF\u4DC0-\u4DFF\uA490-\uA4C6\uA700-\uA716\uA720\uA721\uA789\uA78A\uA828-\uA82B\uA836-\uA839\uAA77-\uAA79\uAB5B\uAB6A\uAB6B\uFB29\uFBB2-\uFBC2\uFD40-\uFD4F\uFDCF\uFDFC-\uFDFF\uFE62\uFE64-\uFE66\uFE69\uFF04\uFF0B\uFF1C-\uFF1E\uFF3E\uFF40\uFF5C\uFF5E\uFFE0-\uFFE6\uFFE8-\uFFEE\uFFFC\uFFFD",
      'astral': "\uD800[\uDD37-\uDD3F\uDD79-\uDD89\uDD8C-\uDD8E\uDD90-\uDD9C\uDDA0\uDDD0-\uDDFC]|\uD802[\uDC77\uDC78\uDEC8]|\uD805\uDF3F|\uD807[\uDFD5-\uDFF1]|\uD81A[\uDF3C-\uDF3F\uDF45]|\uD82F\uDC9C|\uD833[\uDF50-\uDFC3]|\uD834[\uDC00-\uDCF5\uDD00-\uDD26\uDD29-\uDD64\uDD6A-\uDD6C\uDD83\uDD84\uDD8C-\uDDA9\uDDAE-\uDDEA\uDE00-\uDE41\uDE45\uDF00-\uDF56]|\uD835[\uDEC1\uDEDB\uDEFB\uDF15\uDF35\uDF4F\uDF6F\uDF89\uDFA9\uDFC3]|\uD836[\uDC00-\uDDFF\uDE37-\uDE3A\uDE6D-\uDE74\uDE76-\uDE83\uDE85\uDE86]|\uD838[\uDD4F\uDEFF]|\uD83B[\uDCAC\uDCB0\uDD2E\uDEF0\uDEF1]|\uD83C[\uDC00-\uDC2B\uDC30-\uDC93\uDCA0-\uDCAE\uDCB1-\uDCBF\uDCC1-\uDCCF\uDCD1-\uDCF5\uDD0D-\uDDAD\uDDE6-\uDE02\uDE10-\uDE3B\uDE40-\uDE48\uDE50\uDE51\uDE60-\uDE65\uDF00-\uDFFF]|\uD83D[\uDC00-\uDED7\uDEDD-\uDEEC\uDEF0-\uDEFC\uDF00-\uDF73\uDF80-\uDFD8\uDFE0-\uDFEB\uDFF0]|\uD83E[\uDC00-\uDC0B\uDC10-\uDC47\uDC50-\uDC59\uDC60-\uDC87\uDC90-\uDCAD\uDCB0\uDCB1\uDD00-\uDE53\uDE60-\uDE6D\uDE70-\uDE74\uDE78-\uDE7C\uDE80-\uDE86\uDE90-\uDEAC\uDEB0-\uDEBA\uDEC0-\uDEC5\uDED0-\uDED9\uDEE0-\uDEE7\uDEF0-\uDEF6\uDF00-\uDF92\uDF94-\uDFCA]"
    }, {
      'name': 'Sc',
      'alias': 'Currency_Symbol',
      'bmp': "\\$\xA2-\xA5\u058F\u060B\u07FE\u07FF\u09F2\u09F3\u09FB\u0AF1\u0BF9\u0E3F\u17DB\u20A0-\u20C0\uA838\uFDFC\uFE69\uFF04\uFFE0\uFFE1\uFFE5\uFFE6",
      'astral': "\uD807[\uDFDD-\uDFE0]|\uD838\uDEFF|\uD83B\uDCB0"
    }, {
      'name': 'Sk',
      'alias': 'Modifier_Symbol',
      'bmp': "\\^`\xA8\xAF\xB4\xB8\u02C2-\u02C5\u02D2-\u02DF\u02E5-\u02EB\u02ED\u02EF-\u02FF\u0375\u0384\u0385\u0888\u1FBD\u1FBF-\u1FC1\u1FCD-\u1FCF\u1FDD-\u1FDF\u1FED-\u1FEF\u1FFD\u1FFE\u309B\u309C\uA700-\uA716\uA720\uA721\uA789\uA78A\uAB5B\uAB6A\uAB6B\uFBB2-\uFBC2\uFF3E\uFF40\uFFE3",
      'astral': "\uD83C[\uDFFB-\uDFFF]"
    }, {
      'name': 'Sm',
      'alias': 'Math_Symbol',
      'bmp': "\\+<->\\|~\xAC\xB1\xD7\xF7\u03F6\u0606-\u0608\u2044\u2052\u207A-\u207C\u208A-\u208C\u2118\u2140-\u2144\u214B\u2190-\u2194\u219A\u219B\u21A0\u21A3\u21A6\u21AE\u21CE\u21CF\u21D2\u21D4\u21F4-\u22FF\u2320\u2321\u237C\u239B-\u23B3\u23DC-\u23E1\u25B7\u25C1\u25F8-\u25FF\u266F\u27C0-\u27C4\u27C7-\u27E5\u27F0-\u27FF\u2900-\u2982\u2999-\u29D7\u29DC-\u29FB\u29FE-\u2AFF\u2B30-\u2B44\u2B47-\u2B4C\uFB29\uFE62\uFE64-\uFE66\uFF0B\uFF1C-\uFF1E\uFF5C\uFF5E\uFFE2\uFFE9-\uFFEC",
      'astral': "\uD835[\uDEC1\uDEDB\uDEFB\uDF15\uDF35\uDF4F\uDF6F\uDF89\uDFA9\uDFC3]|\uD83B[\uDEF0\uDEF1]"
    }, {
      'name': 'So',
      'alias': 'Other_Symbol',
      'bmp': "\xA6\xA9\xAE\xB0\u0482\u058D\u058E\u060E\u060F\u06DE\u06E9\u06FD\u06FE\u07F6\u09FA\u0B70\u0BF3-\u0BF8\u0BFA\u0C7F\u0D4F\u0D79\u0F01-\u0F03\u0F13\u0F15-\u0F17\u0F1A-\u0F1F\u0F34\u0F36\u0F38\u0FBE-\u0FC5\u0FC7-\u0FCC\u0FCE\u0FCF\u0FD5-\u0FD8\u109E\u109F\u1390-\u1399\u166D\u1940\u19DE-\u19FF\u1B61-\u1B6A\u1B74-\u1B7C\u2100\u2101\u2103-\u2106\u2108\u2109\u2114\u2116\u2117\u211E-\u2123\u2125\u2127\u2129\u212E\u213A\u213B\u214A\u214C\u214D\u214F\u218A\u218B\u2195-\u2199\u219C-\u219F\u21A1\u21A2\u21A4\u21A5\u21A7-\u21AD\u21AF-\u21CD\u21D0\u21D1\u21D3\u21D5-\u21F3\u2300-\u2307\u230C-\u231F\u2322-\u2328\u232B-\u237B\u237D-\u239A\u23B4-\u23DB\u23E2-\u2426\u2440-\u244A\u249C-\u24E9\u2500-\u25B6\u25B8-\u25C0\u25C2-\u25F7\u2600-\u266E\u2670-\u2767\u2794-\u27BF\u2800-\u28FF\u2B00-\u2B2F\u2B45\u2B46\u2B4D-\u2B73\u2B76-\u2B95\u2B97-\u2BFF\u2CE5-\u2CEA\u2E50\u2E51\u2E80-\u2E99\u2E9B-\u2EF3\u2F00-\u2FD5\u2FF0-\u2FFB\u3004\u3012\u3013\u3020\u3036\u3037\u303E\u303F\u3190\u3191\u3196-\u319F\u31C0-\u31E3\u3200-\u321E\u322A-\u3247\u3250\u3260-\u327F\u328A-\u32B0\u32C0-\u33FF\u4DC0-\u4DFF\uA490-\uA4C6\uA828-\uA82B\uA836\uA837\uA839\uAA77-\uAA79\uFD40-\uFD4F\uFDCF\uFDFD-\uFDFF\uFFE4\uFFE8\uFFED\uFFEE\uFFFC\uFFFD",
      'astral': "\uD800[\uDD37-\uDD3F\uDD79-\uDD89\uDD8C-\uDD8E\uDD90-\uDD9C\uDDA0\uDDD0-\uDDFC]|\uD802[\uDC77\uDC78\uDEC8]|\uD805\uDF3F|\uD807[\uDFD5-\uDFDC\uDFE1-\uDFF1]|\uD81A[\uDF3C-\uDF3F\uDF45]|\uD82F\uDC9C|\uD833[\uDF50-\uDFC3]|\uD834[\uDC00-\uDCF5\uDD00-\uDD26\uDD29-\uDD64\uDD6A-\uDD6C\uDD83\uDD84\uDD8C-\uDDA9\uDDAE-\uDDEA\uDE00-\uDE41\uDE45\uDF00-\uDF56]|\uD836[\uDC00-\uDDFF\uDE37-\uDE3A\uDE6D-\uDE74\uDE76-\uDE83\uDE85\uDE86]|\uD838\uDD4F|\uD83B[\uDCAC\uDD2E]|\uD83C[\uDC00-\uDC2B\uDC30-\uDC93\uDCA0-\uDCAE\uDCB1-\uDCBF\uDCC1-\uDCCF\uDCD1-\uDCF5\uDD0D-\uDDAD\uDDE6-\uDE02\uDE10-\uDE3B\uDE40-\uDE48\uDE50\uDE51\uDE60-\uDE65\uDF00-\uDFFA]|\uD83D[\uDC00-\uDED7\uDEDD-\uDEEC\uDEF0-\uDEFC\uDF00-\uDF73\uDF80-\uDFD8\uDFE0-\uDFEB\uDFF0]|\uD83E[\uDC00-\uDC0B\uDC10-\uDC47\uDC50-\uDC59\uDC60-\uDC87\uDC90-\uDCAD\uDCB0\uDCB1\uDD00-\uDE53\uDE60-\uDE6D\uDE70-\uDE74\uDE78-\uDE7C\uDE80-\uDE86\uDE90-\uDEAC\uDEB0-\uDEBA\uDEC0-\uDEC5\uDED0-\uDED9\uDEE0-\uDEE7\uDEF0-\uDEF6\uDF00-\uDF92\uDF94-\uDFCA]"
    }, {
      'name': 'Z',
      'alias': 'Separator',
      'bmp': " \xA0\u1680\u2000-\u200A\u2028\u2029\u202F\u205F\u3000"
    }, {
      'name': 'Zl',
      'alias': 'Line_Separator',
      'bmp': "\u2028"
    }, {
      'name': 'Zp',
      'alias': 'Paragraph_Separator',
      'bmp': "\u2029"
    }, {
      'name': 'Zs',
      'alias': 'Space_Separator',
      'bmp': " \xA0\u1680\u2000-\u200A\u202F\u205F\u3000"
    }];
    var categories$1 = /*@__PURE__*/getDefaultExportFromCjs$1(categories);

    /*!
     * XRegExp Unicode Categories 5.1.1
     * <xregexp.com>
     * Steven Levithan (c) 2010-present MIT License
     * Unicode data by Mathias Bynens <mathiasbynens.be>
     */

    var unicodeCategories = (function (XRegExp) {
      /**
       * Adds support for Unicode's general categories. E.g., `\p{Lu}` or `\p{Uppercase Letter}`. See
       * category descriptions in UAX #44 <http://unicode.org/reports/tr44/#GC_Values_Table>. Token
       * names are case insensitive, and any spaces, hyphens, and underscores are ignored.
       *
       * Uses Unicode 14.0.0.
       *
       * @requires XRegExp, Unicode Base
       */

      if (!XRegExp.addUnicodeData) {
        throw new ReferenceError('Unicode Base must be loaded before Unicode Categories');
      }
      XRegExp.addUnicodeData(categories$1);
    });

    var properties = [{
      'name': 'ASCII',
      'bmp': '\0-\x7F'
    }, {
      'name': 'Alphabetic',
      'bmp': "A-Za-z\xAA\xB5\xBA\xC0-\xD6\xD8-\xF6\xF8-\u02C1\u02C6-\u02D1\u02E0-\u02E4\u02EC\u02EE\u0345\u0370-\u0374\u0376\u0377\u037A-\u037D\u037F\u0386\u0388-\u038A\u038C\u038E-\u03A1\u03A3-\u03F5\u03F7-\u0481\u048A-\u052F\u0531-\u0556\u0559\u0560-\u0588\u05B0-\u05BD\u05BF\u05C1\u05C2\u05C4\u05C5\u05C7\u05D0-\u05EA\u05EF-\u05F2\u0610-\u061A\u0620-\u0657\u0659-\u065F\u066E-\u06D3\u06D5-\u06DC\u06E1-\u06E8\u06ED-\u06EF\u06FA-\u06FC\u06FF\u0710-\u073F\u074D-\u07B1\u07CA-\u07EA\u07F4\u07F5\u07FA\u0800-\u0817\u081A-\u082C\u0840-\u0858\u0860-\u086A\u0870-\u0887\u0889-\u088E\u08A0-\u08C9\u08D4-\u08DF\u08E3-\u08E9\u08F0-\u093B\u093D-\u094C\u094E-\u0950\u0955-\u0963\u0971-\u0983\u0985-\u098C\u098F\u0990\u0993-\u09A8\u09AA-\u09B0\u09B2\u09B6-\u09B9\u09BD-\u09C4\u09C7\u09C8\u09CB\u09CC\u09CE\u09D7\u09DC\u09DD\u09DF-\u09E3\u09F0\u09F1\u09FC\u0A01-\u0A03\u0A05-\u0A0A\u0A0F\u0A10\u0A13-\u0A28\u0A2A-\u0A30\u0A32\u0A33\u0A35\u0A36\u0A38\u0A39\u0A3E-\u0A42\u0A47\u0A48\u0A4B\u0A4C\u0A51\u0A59-\u0A5C\u0A5E\u0A70-\u0A75\u0A81-\u0A83\u0A85-\u0A8D\u0A8F-\u0A91\u0A93-\u0AA8\u0AAA-\u0AB0\u0AB2\u0AB3\u0AB5-\u0AB9\u0ABD-\u0AC5\u0AC7-\u0AC9\u0ACB\u0ACC\u0AD0\u0AE0-\u0AE3\u0AF9-\u0AFC\u0B01-\u0B03\u0B05-\u0B0C\u0B0F\u0B10\u0B13-\u0B28\u0B2A-\u0B30\u0B32\u0B33\u0B35-\u0B39\u0B3D-\u0B44\u0B47\u0B48\u0B4B\u0B4C\u0B56\u0B57\u0B5C\u0B5D\u0B5F-\u0B63\u0B71\u0B82\u0B83\u0B85-\u0B8A\u0B8E-\u0B90\u0B92-\u0B95\u0B99\u0B9A\u0B9C\u0B9E\u0B9F\u0BA3\u0BA4\u0BA8-\u0BAA\u0BAE-\u0BB9\u0BBE-\u0BC2\u0BC6-\u0BC8\u0BCA-\u0BCC\u0BD0\u0BD7\u0C00-\u0C03\u0C05-\u0C0C\u0C0E-\u0C10\u0C12-\u0C28\u0C2A-\u0C39\u0C3D-\u0C44\u0C46-\u0C48\u0C4A-\u0C4C\u0C55\u0C56\u0C58-\u0C5A\u0C5D\u0C60-\u0C63\u0C80-\u0C83\u0C85-\u0C8C\u0C8E-\u0C90\u0C92-\u0CA8\u0CAA-\u0CB3\u0CB5-\u0CB9\u0CBD-\u0CC4\u0CC6-\u0CC8\u0CCA-\u0CCC\u0CD5\u0CD6\u0CDD\u0CDE\u0CE0-\u0CE3\u0CF1\u0CF2\u0D00-\u0D0C\u0D0E-\u0D10\u0D12-\u0D3A\u0D3D-\u0D44\u0D46-\u0D48\u0D4A-\u0D4C\u0D4E\u0D54-\u0D57\u0D5F-\u0D63\u0D7A-\u0D7F\u0D81-\u0D83\u0D85-\u0D96\u0D9A-\u0DB1\u0DB3-\u0DBB\u0DBD\u0DC0-\u0DC6\u0DCF-\u0DD4\u0DD6\u0DD8-\u0DDF\u0DF2\u0DF3\u0E01-\u0E3A\u0E40-\u0E46\u0E4D\u0E81\u0E82\u0E84\u0E86-\u0E8A\u0E8C-\u0EA3\u0EA5\u0EA7-\u0EB9\u0EBB-\u0EBD\u0EC0-\u0EC4\u0EC6\u0ECD\u0EDC-\u0EDF\u0F00\u0F40-\u0F47\u0F49-\u0F6C\u0F71-\u0F81\u0F88-\u0F97\u0F99-\u0FBC\u1000-\u1036\u1038\u103B-\u103F\u1050-\u108F\u109A-\u109D\u10A0-\u10C5\u10C7\u10CD\u10D0-\u10FA\u10FC-\u1248\u124A-\u124D\u1250-\u1256\u1258\u125A-\u125D\u1260-\u1288\u128A-\u128D\u1290-\u12B0\u12B2-\u12B5\u12B8-\u12BE\u12C0\u12C2-\u12C5\u12C8-\u12D6\u12D8-\u1310\u1312-\u1315\u1318-\u135A\u1380-\u138F\u13A0-\u13F5\u13F8-\u13FD\u1401-\u166C\u166F-\u167F\u1681-\u169A\u16A0-\u16EA\u16EE-\u16F8\u1700-\u1713\u171F-\u1733\u1740-\u1753\u1760-\u176C\u176E-\u1770\u1772\u1773\u1780-\u17B3\u17B6-\u17C8\u17D7\u17DC\u1820-\u1878\u1880-\u18AA\u18B0-\u18F5\u1900-\u191E\u1920-\u192B\u1930-\u1938\u1950-\u196D\u1970-\u1974\u1980-\u19AB\u19B0-\u19C9\u1A00-\u1A1B\u1A20-\u1A5E\u1A61-\u1A74\u1AA7\u1ABF\u1AC0\u1ACC-\u1ACE\u1B00-\u1B33\u1B35-\u1B43\u1B45-\u1B4C\u1B80-\u1BA9\u1BAC-\u1BAF\u1BBA-\u1BE5\u1BE7-\u1BF1\u1C00-\u1C36\u1C4D-\u1C4F\u1C5A-\u1C7D\u1C80-\u1C88\u1C90-\u1CBA\u1CBD-\u1CBF\u1CE9-\u1CEC\u1CEE-\u1CF3\u1CF5\u1CF6\u1CFA\u1D00-\u1DBF\u1DE7-\u1DF4\u1E00-\u1F15\u1F18-\u1F1D\u1F20-\u1F45\u1F48-\u1F4D\u1F50-\u1F57\u1F59\u1F5B\u1F5D\u1F5F-\u1F7D\u1F80-\u1FB4\u1FB6-\u1FBC\u1FBE\u1FC2-\u1FC4\u1FC6-\u1FCC\u1FD0-\u1FD3\u1FD6-\u1FDB\u1FE0-\u1FEC\u1FF2-\u1FF4\u1FF6-\u1FFC\u2071\u207F\u2090-\u209C\u2102\u2107\u210A-\u2113\u2115\u2119-\u211D\u2124\u2126\u2128\u212A-\u212D\u212F-\u2139\u213C-\u213F\u2145-\u2149\u214E\u2160-\u2188\u24B6-\u24E9\u2C00-\u2CE4\u2CEB-\u2CEE\u2CF2\u2CF3\u2D00-\u2D25\u2D27\u2D2D\u2D30-\u2D67\u2D6F\u2D80-\u2D96\u2DA0-\u2DA6\u2DA8-\u2DAE\u2DB0-\u2DB6\u2DB8-\u2DBE\u2DC0-\u2DC6\u2DC8-\u2DCE\u2DD0-\u2DD6\u2DD8-\u2DDE\u2DE0-\u2DFF\u2E2F\u3005-\u3007\u3021-\u3029\u3031-\u3035\u3038-\u303C\u3041-\u3096\u309D-\u309F\u30A1-\u30FA\u30FC-\u30FF\u3105-\u312F\u3131-\u318E\u31A0-\u31BF\u31F0-\u31FF\u3400-\u4DBF\u4E00-\uA48C\uA4D0-\uA4FD\uA500-\uA60C\uA610-\uA61F\uA62A\uA62B\uA640-\uA66E\uA674-\uA67B\uA67F-\uA6EF\uA717-\uA71F\uA722-\uA788\uA78B-\uA7CA\uA7D0\uA7D1\uA7D3\uA7D5-\uA7D9\uA7F2-\uA805\uA807-\uA827\uA840-\uA873\uA880-\uA8C3\uA8C5\uA8F2-\uA8F7\uA8FB\uA8FD-\uA8FF\uA90A-\uA92A\uA930-\uA952\uA960-\uA97C\uA980-\uA9B2\uA9B4-\uA9BF\uA9CF\uA9E0-\uA9EF\uA9FA-\uA9FE\uAA00-\uAA36\uAA40-\uAA4D\uAA60-\uAA76\uAA7A-\uAABE\uAAC0\uAAC2\uAADB-\uAADD\uAAE0-\uAAEF\uAAF2-\uAAF5\uAB01-\uAB06\uAB09-\uAB0E\uAB11-\uAB16\uAB20-\uAB26\uAB28-\uAB2E\uAB30-\uAB5A\uAB5C-\uAB69\uAB70-\uABEA\uAC00-\uD7A3\uD7B0-\uD7C6\uD7CB-\uD7FB\uF900-\uFA6D\uFA70-\uFAD9\uFB00-\uFB06\uFB13-\uFB17\uFB1D-\uFB28\uFB2A-\uFB36\uFB38-\uFB3C\uFB3E\uFB40\uFB41\uFB43\uFB44\uFB46-\uFBB1\uFBD3-\uFD3D\uFD50-\uFD8F\uFD92-\uFDC7\uFDF0-\uFDFB\uFE70-\uFE74\uFE76-\uFEFC\uFF21-\uFF3A\uFF41-\uFF5A\uFF66-\uFFBE\uFFC2-\uFFC7\uFFCA-\uFFCF\uFFD2-\uFFD7\uFFDA-\uFFDC",
      'astral': "\uD800[\uDC00-\uDC0B\uDC0D-\uDC26\uDC28-\uDC3A\uDC3C\uDC3D\uDC3F-\uDC4D\uDC50-\uDC5D\uDC80-\uDCFA\uDD40-\uDD74\uDE80-\uDE9C\uDEA0-\uDED0\uDF00-\uDF1F\uDF2D-\uDF4A\uDF50-\uDF7A\uDF80-\uDF9D\uDFA0-\uDFC3\uDFC8-\uDFCF\uDFD1-\uDFD5]|\uD801[\uDC00-\uDC9D\uDCB0-\uDCD3\uDCD8-\uDCFB\uDD00-\uDD27\uDD30-\uDD63\uDD70-\uDD7A\uDD7C-\uDD8A\uDD8C-\uDD92\uDD94\uDD95\uDD97-\uDDA1\uDDA3-\uDDB1\uDDB3-\uDDB9\uDDBB\uDDBC\uDE00-\uDF36\uDF40-\uDF55\uDF60-\uDF67\uDF80-\uDF85\uDF87-\uDFB0\uDFB2-\uDFBA]|\uD802[\uDC00-\uDC05\uDC08\uDC0A-\uDC35\uDC37\uDC38\uDC3C\uDC3F-\uDC55\uDC60-\uDC76\uDC80-\uDC9E\uDCE0-\uDCF2\uDCF4\uDCF5\uDD00-\uDD15\uDD20-\uDD39\uDD80-\uDDB7\uDDBE\uDDBF\uDE00-\uDE03\uDE05\uDE06\uDE0C-\uDE13\uDE15-\uDE17\uDE19-\uDE35\uDE60-\uDE7C\uDE80-\uDE9C\uDEC0-\uDEC7\uDEC9-\uDEE4\uDF00-\uDF35\uDF40-\uDF55\uDF60-\uDF72\uDF80-\uDF91]|\uD803[\uDC00-\uDC48\uDC80-\uDCB2\uDCC0-\uDCF2\uDD00-\uDD27\uDE80-\uDEA9\uDEAB\uDEAC\uDEB0\uDEB1\uDF00-\uDF1C\uDF27\uDF30-\uDF45\uDF70-\uDF81\uDFB0-\uDFC4\uDFE0-\uDFF6]|\uD804[\uDC00-\uDC45\uDC71-\uDC75\uDC82-\uDCB8\uDCC2\uDCD0-\uDCE8\uDD00-\uDD32\uDD44-\uDD47\uDD50-\uDD72\uDD76\uDD80-\uDDBF\uDDC1-\uDDC4\uDDCE\uDDCF\uDDDA\uDDDC\uDE00-\uDE11\uDE13-\uDE34\uDE37\uDE3E\uDE80-\uDE86\uDE88\uDE8A-\uDE8D\uDE8F-\uDE9D\uDE9F-\uDEA8\uDEB0-\uDEE8\uDF00-\uDF03\uDF05-\uDF0C\uDF0F\uDF10\uDF13-\uDF28\uDF2A-\uDF30\uDF32\uDF33\uDF35-\uDF39\uDF3D-\uDF44\uDF47\uDF48\uDF4B\uDF4C\uDF50\uDF57\uDF5D-\uDF63]|\uD805[\uDC00-\uDC41\uDC43-\uDC45\uDC47-\uDC4A\uDC5F-\uDC61\uDC80-\uDCC1\uDCC4\uDCC5\uDCC7\uDD80-\uDDB5\uDDB8-\uDDBE\uDDD8-\uDDDD\uDE00-\uDE3E\uDE40\uDE44\uDE80-\uDEB5\uDEB8\uDF00-\uDF1A\uDF1D-\uDF2A\uDF40-\uDF46]|\uD806[\uDC00-\uDC38\uDCA0-\uDCDF\uDCFF-\uDD06\uDD09\uDD0C-\uDD13\uDD15\uDD16\uDD18-\uDD35\uDD37\uDD38\uDD3B\uDD3C\uDD3F-\uDD42\uDDA0-\uDDA7\uDDAA-\uDDD7\uDDDA-\uDDDF\uDDE1\uDDE3\uDDE4\uDE00-\uDE32\uDE35-\uDE3E\uDE50-\uDE97\uDE9D\uDEB0-\uDEF8]|\uD807[\uDC00-\uDC08\uDC0A-\uDC36\uDC38-\uDC3E\uDC40\uDC72-\uDC8F\uDC92-\uDCA7\uDCA9-\uDCB6\uDD00-\uDD06\uDD08\uDD09\uDD0B-\uDD36\uDD3A\uDD3C\uDD3D\uDD3F-\uDD41\uDD43\uDD46\uDD47\uDD60-\uDD65\uDD67\uDD68\uDD6A-\uDD8E\uDD90\uDD91\uDD93-\uDD96\uDD98\uDEE0-\uDEF6\uDFB0]|\uD808[\uDC00-\uDF99]|\uD809[\uDC00-\uDC6E\uDC80-\uDD43]|\uD80B[\uDF90-\uDFF0]|[\uD80C\uD81C-\uD820\uD822\uD840-\uD868\uD86A-\uD86C\uD86F-\uD872\uD874-\uD879\uD880-\uD883][\uDC00-\uDFFF]|\uD80D[\uDC00-\uDC2E]|\uD811[\uDC00-\uDE46]|\uD81A[\uDC00-\uDE38\uDE40-\uDE5E\uDE70-\uDEBE\uDED0-\uDEED\uDF00-\uDF2F\uDF40-\uDF43\uDF63-\uDF77\uDF7D-\uDF8F]|\uD81B[\uDE40-\uDE7F\uDF00-\uDF4A\uDF4F-\uDF87\uDF8F-\uDF9F\uDFE0\uDFE1\uDFE3\uDFF0\uDFF1]|\uD821[\uDC00-\uDFF7]|\uD823[\uDC00-\uDCD5\uDD00-\uDD08]|\uD82B[\uDFF0-\uDFF3\uDFF5-\uDFFB\uDFFD\uDFFE]|\uD82C[\uDC00-\uDD22\uDD50-\uDD52\uDD64-\uDD67\uDD70-\uDEFB]|\uD82F[\uDC00-\uDC6A\uDC70-\uDC7C\uDC80-\uDC88\uDC90-\uDC99\uDC9E]|\uD835[\uDC00-\uDC54\uDC56-\uDC9C\uDC9E\uDC9F\uDCA2\uDCA5\uDCA6\uDCA9-\uDCAC\uDCAE-\uDCB9\uDCBB\uDCBD-\uDCC3\uDCC5-\uDD05\uDD07-\uDD0A\uDD0D-\uDD14\uDD16-\uDD1C\uDD1E-\uDD39\uDD3B-\uDD3E\uDD40-\uDD44\uDD46\uDD4A-\uDD50\uDD52-\uDEA5\uDEA8-\uDEC0\uDEC2-\uDEDA\uDEDC-\uDEFA\uDEFC-\uDF14\uDF16-\uDF34\uDF36-\uDF4E\uDF50-\uDF6E\uDF70-\uDF88\uDF8A-\uDFA8\uDFAA-\uDFC2\uDFC4-\uDFCB]|\uD837[\uDF00-\uDF1E]|\uD838[\uDC00-\uDC06\uDC08-\uDC18\uDC1B-\uDC21\uDC23\uDC24\uDC26-\uDC2A\uDD00-\uDD2C\uDD37-\uDD3D\uDD4E\uDE90-\uDEAD\uDEC0-\uDEEB]|\uD839[\uDFE0-\uDFE6\uDFE8-\uDFEB\uDFED\uDFEE\uDFF0-\uDFFE]|\uD83A[\uDC00-\uDCC4\uDD00-\uDD43\uDD47\uDD4B]|\uD83B[\uDE00-\uDE03\uDE05-\uDE1F\uDE21\uDE22\uDE24\uDE27\uDE29-\uDE32\uDE34-\uDE37\uDE39\uDE3B\uDE42\uDE47\uDE49\uDE4B\uDE4D-\uDE4F\uDE51\uDE52\uDE54\uDE57\uDE59\uDE5B\uDE5D\uDE5F\uDE61\uDE62\uDE64\uDE67-\uDE6A\uDE6C-\uDE72\uDE74-\uDE77\uDE79-\uDE7C\uDE7E\uDE80-\uDE89\uDE8B-\uDE9B\uDEA1-\uDEA3\uDEA5-\uDEA9\uDEAB-\uDEBB]|\uD83C[\uDD30-\uDD49\uDD50-\uDD69\uDD70-\uDD89]|\uD869[\uDC00-\uDEDF\uDF00-\uDFFF]|\uD86D[\uDC00-\uDF38\uDF40-\uDFFF]|\uD86E[\uDC00-\uDC1D\uDC20-\uDFFF]|\uD873[\uDC00-\uDEA1\uDEB0-\uDFFF]|\uD87A[\uDC00-\uDFE0]|\uD87E[\uDC00-\uDE1D]|\uD884[\uDC00-\uDF4A]"
    }, {
      'name': 'Any',
      'isBmpLast': true,
      'bmp': "\0-\uFFFF",
      'astral': "[\uD800-\uDBFF][\uDC00-\uDFFF]"
    }, {
      'name': 'Default_Ignorable_Code_Point',
      'bmp': "\xAD\u034F\u061C\u115F\u1160\u17B4\u17B5\u180B-\u180F\u200B-\u200F\u202A-\u202E\u2060-\u206F\u3164\uFE00-\uFE0F\uFEFF\uFFA0\uFFF0-\uFFF8",
      'astral': "\uD82F[\uDCA0-\uDCA3]|\uD834[\uDD73-\uDD7A]|[\uDB40-\uDB43][\uDC00-\uDFFF]"
    }, {
      'name': 'Lowercase',
      'bmp': "a-z\xAA\xB5\xBA\xDF-\xF6\xF8-\xFF\u0101\u0103\u0105\u0107\u0109\u010B\u010D\u010F\u0111\u0113\u0115\u0117\u0119\u011B\u011D\u011F\u0121\u0123\u0125\u0127\u0129\u012B\u012D\u012F\u0131\u0133\u0135\u0137\u0138\u013A\u013C\u013E\u0140\u0142\u0144\u0146\u0148\u0149\u014B\u014D\u014F\u0151\u0153\u0155\u0157\u0159\u015B\u015D\u015F\u0161\u0163\u0165\u0167\u0169\u016B\u016D\u016F\u0171\u0173\u0175\u0177\u017A\u017C\u017E-\u0180\u0183\u0185\u0188\u018C\u018D\u0192\u0195\u0199-\u019B\u019E\u01A1\u01A3\u01A5\u01A8\u01AA\u01AB\u01AD\u01B0\u01B4\u01B6\u01B9\u01BA\u01BD-\u01BF\u01C6\u01C9\u01CC\u01CE\u01D0\u01D2\u01D4\u01D6\u01D8\u01DA\u01DC\u01DD\u01DF\u01E1\u01E3\u01E5\u01E7\u01E9\u01EB\u01ED\u01EF\u01F0\u01F3\u01F5\u01F9\u01FB\u01FD\u01FF\u0201\u0203\u0205\u0207\u0209\u020B\u020D\u020F\u0211\u0213\u0215\u0217\u0219\u021B\u021D\u021F\u0221\u0223\u0225\u0227\u0229\u022B\u022D\u022F\u0231\u0233-\u0239\u023C\u023F\u0240\u0242\u0247\u0249\u024B\u024D\u024F-\u0293\u0295-\u02B8\u02C0\u02C1\u02E0-\u02E4\u0345\u0371\u0373\u0377\u037A-\u037D\u0390\u03AC-\u03CE\u03D0\u03D1\u03D5-\u03D7\u03D9\u03DB\u03DD\u03DF\u03E1\u03E3\u03E5\u03E7\u03E9\u03EB\u03ED\u03EF-\u03F3\u03F5\u03F8\u03FB\u03FC\u0430-\u045F\u0461\u0463\u0465\u0467\u0469\u046B\u046D\u046F\u0471\u0473\u0475\u0477\u0479\u047B\u047D\u047F\u0481\u048B\u048D\u048F\u0491\u0493\u0495\u0497\u0499\u049B\u049D\u049F\u04A1\u04A3\u04A5\u04A7\u04A9\u04AB\u04AD\u04AF\u04B1\u04B3\u04B5\u04B7\u04B9\u04BB\u04BD\u04BF\u04C2\u04C4\u04C6\u04C8\u04CA\u04CC\u04CE\u04CF\u04D1\u04D3\u04D5\u04D7\u04D9\u04DB\u04DD\u04DF\u04E1\u04E3\u04E5\u04E7\u04E9\u04EB\u04ED\u04EF\u04F1\u04F3\u04F5\u04F7\u04F9\u04FB\u04FD\u04FF\u0501\u0503\u0505\u0507\u0509\u050B\u050D\u050F\u0511\u0513\u0515\u0517\u0519\u051B\u051D\u051F\u0521\u0523\u0525\u0527\u0529\u052B\u052D\u052F\u0560-\u0588\u10D0-\u10FA\u10FD-\u10FF\u13F8-\u13FD\u1C80-\u1C88\u1D00-\u1DBF\u1E01\u1E03\u1E05\u1E07\u1E09\u1E0B\u1E0D\u1E0F\u1E11\u1E13\u1E15\u1E17\u1E19\u1E1B\u1E1D\u1E1F\u1E21\u1E23\u1E25\u1E27\u1E29\u1E2B\u1E2D\u1E2F\u1E31\u1E33\u1E35\u1E37\u1E39\u1E3B\u1E3D\u1E3F\u1E41\u1E43\u1E45\u1E47\u1E49\u1E4B\u1E4D\u1E4F\u1E51\u1E53\u1E55\u1E57\u1E59\u1E5B\u1E5D\u1E5F\u1E61\u1E63\u1E65\u1E67\u1E69\u1E6B\u1E6D\u1E6F\u1E71\u1E73\u1E75\u1E77\u1E79\u1E7B\u1E7D\u1E7F\u1E81\u1E83\u1E85\u1E87\u1E89\u1E8B\u1E8D\u1E8F\u1E91\u1E93\u1E95-\u1E9D\u1E9F\u1EA1\u1EA3\u1EA5\u1EA7\u1EA9\u1EAB\u1EAD\u1EAF\u1EB1\u1EB3\u1EB5\u1EB7\u1EB9\u1EBB\u1EBD\u1EBF\u1EC1\u1EC3\u1EC5\u1EC7\u1EC9\u1ECB\u1ECD\u1ECF\u1ED1\u1ED3\u1ED5\u1ED7\u1ED9\u1EDB\u1EDD\u1EDF\u1EE1\u1EE3\u1EE5\u1EE7\u1EE9\u1EEB\u1EED\u1EEF\u1EF1\u1EF3\u1EF5\u1EF7\u1EF9\u1EFB\u1EFD\u1EFF-\u1F07\u1F10-\u1F15\u1F20-\u1F27\u1F30-\u1F37\u1F40-\u1F45\u1F50-\u1F57\u1F60-\u1F67\u1F70-\u1F7D\u1F80-\u1F87\u1F90-\u1F97\u1FA0-\u1FA7\u1FB0-\u1FB4\u1FB6\u1FB7\u1FBE\u1FC2-\u1FC4\u1FC6\u1FC7\u1FD0-\u1FD3\u1FD6\u1FD7\u1FE0-\u1FE7\u1FF2-\u1FF4\u1FF6\u1FF7\u2071\u207F\u2090-\u209C\u210A\u210E\u210F\u2113\u212F\u2134\u2139\u213C\u213D\u2146-\u2149\u214E\u2170-\u217F\u2184\u24D0-\u24E9\u2C30-\u2C5F\u2C61\u2C65\u2C66\u2C68\u2C6A\u2C6C\u2C71\u2C73\u2C74\u2C76-\u2C7D\u2C81\u2C83\u2C85\u2C87\u2C89\u2C8B\u2C8D\u2C8F\u2C91\u2C93\u2C95\u2C97\u2C99\u2C9B\u2C9D\u2C9F\u2CA1\u2CA3\u2CA5\u2CA7\u2CA9\u2CAB\u2CAD\u2CAF\u2CB1\u2CB3\u2CB5\u2CB7\u2CB9\u2CBB\u2CBD\u2CBF\u2CC1\u2CC3\u2CC5\u2CC7\u2CC9\u2CCB\u2CCD\u2CCF\u2CD1\u2CD3\u2CD5\u2CD7\u2CD9\u2CDB\u2CDD\u2CDF\u2CE1\u2CE3\u2CE4\u2CEC\u2CEE\u2CF3\u2D00-\u2D25\u2D27\u2D2D\uA641\uA643\uA645\uA647\uA649\uA64B\uA64D\uA64F\uA651\uA653\uA655\uA657\uA659\uA65B\uA65D\uA65F\uA661\uA663\uA665\uA667\uA669\uA66B\uA66D\uA681\uA683\uA685\uA687\uA689\uA68B\uA68D\uA68F\uA691\uA693\uA695\uA697\uA699\uA69B-\uA69D\uA723\uA725\uA727\uA729\uA72B\uA72D\uA72F-\uA731\uA733\uA735\uA737\uA739\uA73B\uA73D\uA73F\uA741\uA743\uA745\uA747\uA749\uA74B\uA74D\uA74F\uA751\uA753\uA755\uA757\uA759\uA75B\uA75D\uA75F\uA761\uA763\uA765\uA767\uA769\uA76B\uA76D\uA76F-\uA778\uA77A\uA77C\uA77F\uA781\uA783\uA785\uA787\uA78C\uA78E\uA791\uA793-\uA795\uA797\uA799\uA79B\uA79D\uA79F\uA7A1\uA7A3\uA7A5\uA7A7\uA7A9\uA7AF\uA7B5\uA7B7\uA7B9\uA7BB\uA7BD\uA7BF\uA7C1\uA7C3\uA7C8\uA7CA\uA7D1\uA7D3\uA7D5\uA7D7\uA7D9\uA7F6\uA7F8-\uA7FA\uAB30-\uAB5A\uAB5C-\uAB68\uAB70-\uABBF\uFB00-\uFB06\uFB13-\uFB17\uFF41-\uFF5A",
      'astral': "\uD801[\uDC28-\uDC4F\uDCD8-\uDCFB\uDD97-\uDDA1\uDDA3-\uDDB1\uDDB3-\uDDB9\uDDBB\uDDBC\uDF80\uDF83-\uDF85\uDF87-\uDFB0\uDFB2-\uDFBA]|\uD803[\uDCC0-\uDCF2]|\uD806[\uDCC0-\uDCDF]|\uD81B[\uDE60-\uDE7F]|\uD835[\uDC1A-\uDC33\uDC4E-\uDC54\uDC56-\uDC67\uDC82-\uDC9B\uDCB6-\uDCB9\uDCBB\uDCBD-\uDCC3\uDCC5-\uDCCF\uDCEA-\uDD03\uDD1E-\uDD37\uDD52-\uDD6B\uDD86-\uDD9F\uDDBA-\uDDD3\uDDEE-\uDE07\uDE22-\uDE3B\uDE56-\uDE6F\uDE8A-\uDEA5\uDEC2-\uDEDA\uDEDC-\uDEE1\uDEFC-\uDF14\uDF16-\uDF1B\uDF36-\uDF4E\uDF50-\uDF55\uDF70-\uDF88\uDF8A-\uDF8F\uDFAA-\uDFC2\uDFC4-\uDFC9\uDFCB]|\uD837[\uDF00-\uDF09\uDF0B-\uDF1E]|\uD83A[\uDD22-\uDD43]"
    }, {
      'name': 'Noncharacter_Code_Point',
      'bmp': "\uFDD0-\uFDEF\uFFFE\uFFFF",
      'astral': "[\uD83F\uD87F\uD8BF\uD8FF\uD93F\uD97F\uD9BF\uD9FF\uDA3F\uDA7F\uDABF\uDAFF\uDB3F\uDB7F\uDBBF\uDBFF][\uDFFE\uDFFF]"
    }, {
      'name': 'Uppercase',
      'bmp': "A-Z\xC0-\xD6\xD8-\xDE\u0100\u0102\u0104\u0106\u0108\u010A\u010C\u010E\u0110\u0112\u0114\u0116\u0118\u011A\u011C\u011E\u0120\u0122\u0124\u0126\u0128\u012A\u012C\u012E\u0130\u0132\u0134\u0136\u0139\u013B\u013D\u013F\u0141\u0143\u0145\u0147\u014A\u014C\u014E\u0150\u0152\u0154\u0156\u0158\u015A\u015C\u015E\u0160\u0162\u0164\u0166\u0168\u016A\u016C\u016E\u0170\u0172\u0174\u0176\u0178\u0179\u017B\u017D\u0181\u0182\u0184\u0186\u0187\u0189-\u018B\u018E-\u0191\u0193\u0194\u0196-\u0198\u019C\u019D\u019F\u01A0\u01A2\u01A4\u01A6\u01A7\u01A9\u01AC\u01AE\u01AF\u01B1-\u01B3\u01B5\u01B7\u01B8\u01BC\u01C4\u01C7\u01CA\u01CD\u01CF\u01D1\u01D3\u01D5\u01D7\u01D9\u01DB\u01DE\u01E0\u01E2\u01E4\u01E6\u01E8\u01EA\u01EC\u01EE\u01F1\u01F4\u01F6-\u01F8\u01FA\u01FC\u01FE\u0200\u0202\u0204\u0206\u0208\u020A\u020C\u020E\u0210\u0212\u0214\u0216\u0218\u021A\u021C\u021E\u0220\u0222\u0224\u0226\u0228\u022A\u022C\u022E\u0230\u0232\u023A\u023B\u023D\u023E\u0241\u0243-\u0246\u0248\u024A\u024C\u024E\u0370\u0372\u0376\u037F\u0386\u0388-\u038A\u038C\u038E\u038F\u0391-\u03A1\u03A3-\u03AB\u03CF\u03D2-\u03D4\u03D8\u03DA\u03DC\u03DE\u03E0\u03E2\u03E4\u03E6\u03E8\u03EA\u03EC\u03EE\u03F4\u03F7\u03F9\u03FA\u03FD-\u042F\u0460\u0462\u0464\u0466\u0468\u046A\u046C\u046E\u0470\u0472\u0474\u0476\u0478\u047A\u047C\u047E\u0480\u048A\u048C\u048E\u0490\u0492\u0494\u0496\u0498\u049A\u049C\u049E\u04A0\u04A2\u04A4\u04A6\u04A8\u04AA\u04AC\u04AE\u04B0\u04B2\u04B4\u04B6\u04B8\u04BA\u04BC\u04BE\u04C0\u04C1\u04C3\u04C5\u04C7\u04C9\u04CB\u04CD\u04D0\u04D2\u04D4\u04D6\u04D8\u04DA\u04DC\u04DE\u04E0\u04E2\u04E4\u04E6\u04E8\u04EA\u04EC\u04EE\u04F0\u04F2\u04F4\u04F6\u04F8\u04FA\u04FC\u04FE\u0500\u0502\u0504\u0506\u0508\u050A\u050C\u050E\u0510\u0512\u0514\u0516\u0518\u051A\u051C\u051E\u0520\u0522\u0524\u0526\u0528\u052A\u052C\u052E\u0531-\u0556\u10A0-\u10C5\u10C7\u10CD\u13A0-\u13F5\u1C90-\u1CBA\u1CBD-\u1CBF\u1E00\u1E02\u1E04\u1E06\u1E08\u1E0A\u1E0C\u1E0E\u1E10\u1E12\u1E14\u1E16\u1E18\u1E1A\u1E1C\u1E1E\u1E20\u1E22\u1E24\u1E26\u1E28\u1E2A\u1E2C\u1E2E\u1E30\u1E32\u1E34\u1E36\u1E38\u1E3A\u1E3C\u1E3E\u1E40\u1E42\u1E44\u1E46\u1E48\u1E4A\u1E4C\u1E4E\u1E50\u1E52\u1E54\u1E56\u1E58\u1E5A\u1E5C\u1E5E\u1E60\u1E62\u1E64\u1E66\u1E68\u1E6A\u1E6C\u1E6E\u1E70\u1E72\u1E74\u1E76\u1E78\u1E7A\u1E7C\u1E7E\u1E80\u1E82\u1E84\u1E86\u1E88\u1E8A\u1E8C\u1E8E\u1E90\u1E92\u1E94\u1E9E\u1EA0\u1EA2\u1EA4\u1EA6\u1EA8\u1EAA\u1EAC\u1EAE\u1EB0\u1EB2\u1EB4\u1EB6\u1EB8\u1EBA\u1EBC\u1EBE\u1EC0\u1EC2\u1EC4\u1EC6\u1EC8\u1ECA\u1ECC\u1ECE\u1ED0\u1ED2\u1ED4\u1ED6\u1ED8\u1EDA\u1EDC\u1EDE\u1EE0\u1EE2\u1EE4\u1EE6\u1EE8\u1EEA\u1EEC\u1EEE\u1EF0\u1EF2\u1EF4\u1EF6\u1EF8\u1EFA\u1EFC\u1EFE\u1F08-\u1F0F\u1F18-\u1F1D\u1F28-\u1F2F\u1F38-\u1F3F\u1F48-\u1F4D\u1F59\u1F5B\u1F5D\u1F5F\u1F68-\u1F6F\u1FB8-\u1FBB\u1FC8-\u1FCB\u1FD8-\u1FDB\u1FE8-\u1FEC\u1FF8-\u1FFB\u2102\u2107\u210B-\u210D\u2110-\u2112\u2115\u2119-\u211D\u2124\u2126\u2128\u212A-\u212D\u2130-\u2133\u213E\u213F\u2145\u2160-\u216F\u2183\u24B6-\u24CF\u2C00-\u2C2F\u2C60\u2C62-\u2C64\u2C67\u2C69\u2C6B\u2C6D-\u2C70\u2C72\u2C75\u2C7E-\u2C80\u2C82\u2C84\u2C86\u2C88\u2C8A\u2C8C\u2C8E\u2C90\u2C92\u2C94\u2C96\u2C98\u2C9A\u2C9C\u2C9E\u2CA0\u2CA2\u2CA4\u2CA6\u2CA8\u2CAA\u2CAC\u2CAE\u2CB0\u2CB2\u2CB4\u2CB6\u2CB8\u2CBA\u2CBC\u2CBE\u2CC0\u2CC2\u2CC4\u2CC6\u2CC8\u2CCA\u2CCC\u2CCE\u2CD0\u2CD2\u2CD4\u2CD6\u2CD8\u2CDA\u2CDC\u2CDE\u2CE0\u2CE2\u2CEB\u2CED\u2CF2\uA640\uA642\uA644\uA646\uA648\uA64A\uA64C\uA64E\uA650\uA652\uA654\uA656\uA658\uA65A\uA65C\uA65E\uA660\uA662\uA664\uA666\uA668\uA66A\uA66C\uA680\uA682\uA684\uA686\uA688\uA68A\uA68C\uA68E\uA690\uA692\uA694\uA696\uA698\uA69A\uA722\uA724\uA726\uA728\uA72A\uA72C\uA72E\uA732\uA734\uA736\uA738\uA73A\uA73C\uA73E\uA740\uA742\uA744\uA746\uA748\uA74A\uA74C\uA74E\uA750\uA752\uA754\uA756\uA758\uA75A\uA75C\uA75E\uA760\uA762\uA764\uA766\uA768\uA76A\uA76C\uA76E\uA779\uA77B\uA77D\uA77E\uA780\uA782\uA784\uA786\uA78B\uA78D\uA790\uA792\uA796\uA798\uA79A\uA79C\uA79E\uA7A0\uA7A2\uA7A4\uA7A6\uA7A8\uA7AA-\uA7AE\uA7B0-\uA7B4\uA7B6\uA7B8\uA7BA\uA7BC\uA7BE\uA7C0\uA7C2\uA7C4-\uA7C7\uA7C9\uA7D0\uA7D6\uA7D8\uA7F5\uFF21-\uFF3A",
      'astral': "\uD801[\uDC00-\uDC27\uDCB0-\uDCD3\uDD70-\uDD7A\uDD7C-\uDD8A\uDD8C-\uDD92\uDD94\uDD95]|\uD803[\uDC80-\uDCB2]|\uD806[\uDCA0-\uDCBF]|\uD81B[\uDE40-\uDE5F]|\uD835[\uDC00-\uDC19\uDC34-\uDC4D\uDC68-\uDC81\uDC9C\uDC9E\uDC9F\uDCA2\uDCA5\uDCA6\uDCA9-\uDCAC\uDCAE-\uDCB5\uDCD0-\uDCE9\uDD04\uDD05\uDD07-\uDD0A\uDD0D-\uDD14\uDD16-\uDD1C\uDD38\uDD39\uDD3B-\uDD3E\uDD40-\uDD44\uDD46\uDD4A-\uDD50\uDD6C-\uDD85\uDDA0-\uDDB9\uDDD4-\uDDED\uDE08-\uDE21\uDE3C-\uDE55\uDE70-\uDE89\uDEA8-\uDEC0\uDEE2-\uDEFA\uDF1C-\uDF34\uDF56-\uDF6E\uDF90-\uDFA8\uDFCA]|\uD83A[\uDD00-\uDD21]|\uD83C[\uDD30-\uDD49\uDD50-\uDD69\uDD70-\uDD89]"
    }, {
      'name': 'White_Space',
      'bmp': "\t-\r \x85\xA0\u1680\u2000-\u200A\u2028\u2029\u202F\u205F\u3000"
    }];
    var properties$1 = /*@__PURE__*/getDefaultExportFromCjs$1(properties);

    /*!
     * XRegExp Unicode Properties 5.1.1
     * <xregexp.com>
     * Steven Levithan (c) 2012-present MIT License
     * Unicode data by Mathias Bynens <mathiasbynens.be>
     */

    var unicodeProperties = (function (XRegExp) {
      /**
       * Adds properties to meet the UTS #18 Level 1 RL1.2 requirements for Unicode regex support. See
       * <http://unicode.org/reports/tr18/#RL1.2>. Following are definitions of these properties from
       * UAX #44 <http://unicode.org/reports/tr44/>:
       *
       * - Alphabetic
       *   Characters with the Alphabetic property. Generated from: Lowercase + Uppercase + Lt + Lm +
       *   Lo + Nl + Other_Alphabetic.
       *
       * - Default_Ignorable_Code_Point
       *   For programmatic determination of default ignorable code points. New characters that should
       *   be ignored in rendering (unless explicitly supported) will be assigned in these ranges,
       *   permitting programs to correctly handle the default rendering of such characters when not
       *   otherwise supported.
       *
       * - Lowercase
       *   Characters with the Lowercase property. Generated from: Ll + Other_Lowercase.
       *
       * - Noncharacter_Code_Point
       *   Code points permanently reserved for internal use.
       *
       * - Uppercase
       *   Characters with the Uppercase property. Generated from: Lu + Other_Uppercase.
       *
       * - White_Space
       *   Spaces, separator characters and other control characters which should be treated by
       *   programming languages as "white space" for the purpose of parsing elements.
       *
       * The properties ASCII, Any, and Assigned are also included but are not defined in UAX #44. UTS
       * #18 RL1.2 additionally requires support for Unicode scripts and general categories. These are
       * included in XRegExp's Unicode Categories and Unicode Scripts addons.
       *
       * Token names are case insensitive, and any spaces, hyphens, and underscores are ignored.
       *
       * Uses Unicode 14.0.0.
       *
       * @requires XRegExp, Unicode Base
       */

      if (!XRegExp.addUnicodeData) {
        throw new ReferenceError('Unicode Base must be loaded before Unicode Properties');
      }
      var unicodeData = properties$1;

      // Add non-generated data
      unicodeData.push({
        name: 'Assigned',
        // Since this is defined as the inverse of Unicode category Cn (Unassigned), the Unicode
        // Categories addon is required to use this property
        inverseOf: 'Cn'
      });
      XRegExp.addUnicodeData(unicodeData);
    });

    var scripts = [{
      'name': 'Adlam',
      'astral': "\uD83A[\uDD00-\uDD4B\uDD50-\uDD59\uDD5E\uDD5F]"
    }, {
      'name': 'Ahom',
      'astral': "\uD805[\uDF00-\uDF1A\uDF1D-\uDF2B\uDF30-\uDF46]"
    }, {
      'name': 'Anatolian_Hieroglyphs',
      'astral': "\uD811[\uDC00-\uDE46]"
    }, {
      'name': 'Arabic',
      'bmp': "\u0600-\u0604\u0606-\u060B\u060D-\u061A\u061C-\u061E\u0620-\u063F\u0641-\u064A\u0656-\u066F\u0671-\u06DC\u06DE-\u06FF\u0750-\u077F\u0870-\u088E\u0890\u0891\u0898-\u08E1\u08E3-\u08FF\uFB50-\uFBC2\uFBD3-\uFD3D\uFD40-\uFD8F\uFD92-\uFDC7\uFDCF\uFDF0-\uFDFF\uFE70-\uFE74\uFE76-\uFEFC",
      'astral': "\uD803[\uDE60-\uDE7E]|\uD83B[\uDE00-\uDE03\uDE05-\uDE1F\uDE21\uDE22\uDE24\uDE27\uDE29-\uDE32\uDE34-\uDE37\uDE39\uDE3B\uDE42\uDE47\uDE49\uDE4B\uDE4D-\uDE4F\uDE51\uDE52\uDE54\uDE57\uDE59\uDE5B\uDE5D\uDE5F\uDE61\uDE62\uDE64\uDE67-\uDE6A\uDE6C-\uDE72\uDE74-\uDE77\uDE79-\uDE7C\uDE7E\uDE80-\uDE89\uDE8B-\uDE9B\uDEA1-\uDEA3\uDEA5-\uDEA9\uDEAB-\uDEBB\uDEF0\uDEF1]"
    }, {
      'name': 'Armenian',
      'bmp': "\u0531-\u0556\u0559-\u058A\u058D-\u058F\uFB13-\uFB17"
    }, {
      'name': 'Avestan',
      'astral': "\uD802[\uDF00-\uDF35\uDF39-\uDF3F]"
    }, {
      'name': 'Balinese',
      'bmp': "\u1B00-\u1B4C\u1B50-\u1B7E"
    }, {
      'name': 'Bamum',
      'bmp': "\uA6A0-\uA6F7",
      'astral': "\uD81A[\uDC00-\uDE38]"
    }, {
      'name': 'Bassa_Vah',
      'astral': "\uD81A[\uDED0-\uDEED\uDEF0-\uDEF5]"
    }, {
      'name': 'Batak',
      'bmp': "\u1BC0-\u1BF3\u1BFC-\u1BFF"
    }, {
      'name': 'Bengali',
      'bmp': "\u0980-\u0983\u0985-\u098C\u098F\u0990\u0993-\u09A8\u09AA-\u09B0\u09B2\u09B6-\u09B9\u09BC-\u09C4\u09C7\u09C8\u09CB-\u09CE\u09D7\u09DC\u09DD\u09DF-\u09E3\u09E6-\u09FE"
    }, {
      'name': 'Bhaiksuki',
      'astral': "\uD807[\uDC00-\uDC08\uDC0A-\uDC36\uDC38-\uDC45\uDC50-\uDC6C]"
    }, {
      'name': 'Bopomofo',
      'bmp': "\u02EA\u02EB\u3105-\u312F\u31A0-\u31BF"
    }, {
      'name': 'Brahmi',
      'astral': "\uD804[\uDC00-\uDC4D\uDC52-\uDC75\uDC7F]"
    }, {
      'name': 'Braille',
      'bmp': "\u2800-\u28FF"
    }, {
      'name': 'Buginese',
      'bmp': "\u1A00-\u1A1B\u1A1E\u1A1F"
    }, {
      'name': 'Buhid',
      'bmp': "\u1740-\u1753"
    }, {
      'name': 'Canadian_Aboriginal',
      'bmp': "\u1400-\u167F\u18B0-\u18F5",
      'astral': "\uD806[\uDEB0-\uDEBF]"
    }, {
      'name': 'Carian',
      'astral': "\uD800[\uDEA0-\uDED0]"
    }, {
      'name': 'Caucasian_Albanian',
      'astral': "\uD801[\uDD30-\uDD63\uDD6F]"
    }, {
      'name': 'Chakma',
      'astral': "\uD804[\uDD00-\uDD34\uDD36-\uDD47]"
    }, {
      'name': 'Cham',
      'bmp': "\uAA00-\uAA36\uAA40-\uAA4D\uAA50-\uAA59\uAA5C-\uAA5F"
    }, {
      'name': 'Cherokee',
      'bmp': "\u13A0-\u13F5\u13F8-\u13FD\uAB70-\uABBF"
    }, {
      'name': 'Chorasmian',
      'astral': "\uD803[\uDFB0-\uDFCB]"
    }, {
      'name': 'Common',
      'bmp': "\0-@\\[-`\\{-\xA9\xAB-\xB9\xBB-\xBF\xD7\xF7\u02B9-\u02DF\u02E5-\u02E9\u02EC-\u02FF\u0374\u037E\u0385\u0387\u0605\u060C\u061B\u061F\u0640\u06DD\u08E2\u0964\u0965\u0E3F\u0FD5-\u0FD8\u10FB\u16EB-\u16ED\u1735\u1736\u1802\u1803\u1805\u1CD3\u1CE1\u1CE9-\u1CEC\u1CEE-\u1CF3\u1CF5-\u1CF7\u1CFA\u2000-\u200B\u200E-\u2064\u2066-\u2070\u2074-\u207E\u2080-\u208E\u20A0-\u20C0\u2100-\u2125\u2127-\u2129\u212C-\u2131\u2133-\u214D\u214F-\u215F\u2189-\u218B\u2190-\u2426\u2440-\u244A\u2460-\u27FF\u2900-\u2B73\u2B76-\u2B95\u2B97-\u2BFF\u2E00-\u2E5D\u2FF0-\u2FFB\u3000-\u3004\u3006\u3008-\u3020\u3030-\u3037\u303C-\u303F\u309B\u309C\u30A0\u30FB\u30FC\u3190-\u319F\u31C0-\u31E3\u3220-\u325F\u327F-\u32CF\u32FF\u3358-\u33FF\u4DC0-\u4DFF\uA700-\uA721\uA788-\uA78A\uA830-\uA839\uA92E\uA9CF\uAB5B\uAB6A\uAB6B\uFD3E\uFD3F\uFE10-\uFE19\uFE30-\uFE52\uFE54-\uFE66\uFE68-\uFE6B\uFEFF\uFF01-\uFF20\uFF3B-\uFF40\uFF5B-\uFF65\uFF70\uFF9E\uFF9F\uFFE0-\uFFE6\uFFE8-\uFFEE\uFFF9-\uFFFD",
      'astral': "\uD800[\uDD00-\uDD02\uDD07-\uDD33\uDD37-\uDD3F\uDD90-\uDD9C\uDDD0-\uDDFC\uDEE1-\uDEFB]|\uD82F[\uDCA0-\uDCA3]|\uD833[\uDF50-\uDFC3]|\uD834[\uDC00-\uDCF5\uDD00-\uDD26\uDD29-\uDD66\uDD6A-\uDD7A\uDD83\uDD84\uDD8C-\uDDA9\uDDAE-\uDDEA\uDEE0-\uDEF3\uDF00-\uDF56\uDF60-\uDF78]|\uD835[\uDC00-\uDC54\uDC56-\uDC9C\uDC9E\uDC9F\uDCA2\uDCA5\uDCA6\uDCA9-\uDCAC\uDCAE-\uDCB9\uDCBB\uDCBD-\uDCC3\uDCC5-\uDD05\uDD07-\uDD0A\uDD0D-\uDD14\uDD16-\uDD1C\uDD1E-\uDD39\uDD3B-\uDD3E\uDD40-\uDD44\uDD46\uDD4A-\uDD50\uDD52-\uDEA5\uDEA8-\uDFCB\uDFCE-\uDFFF]|\uD83B[\uDC71-\uDCB4\uDD01-\uDD3D]|\uD83C[\uDC00-\uDC2B\uDC30-\uDC93\uDCA0-\uDCAE\uDCB1-\uDCBF\uDCC1-\uDCCF\uDCD1-\uDCF5\uDD00-\uDDAD\uDDE6-\uDDFF\uDE01\uDE02\uDE10-\uDE3B\uDE40-\uDE48\uDE50\uDE51\uDE60-\uDE65\uDF00-\uDFFF]|\uD83D[\uDC00-\uDED7\uDEDD-\uDEEC\uDEF0-\uDEFC\uDF00-\uDF73\uDF80-\uDFD8\uDFE0-\uDFEB\uDFF0]|\uD83E[\uDC00-\uDC0B\uDC10-\uDC47\uDC50-\uDC59\uDC60-\uDC87\uDC90-\uDCAD\uDCB0\uDCB1\uDD00-\uDE53\uDE60-\uDE6D\uDE70-\uDE74\uDE78-\uDE7C\uDE80-\uDE86\uDE90-\uDEAC\uDEB0-\uDEBA\uDEC0-\uDEC5\uDED0-\uDED9\uDEE0-\uDEE7\uDEF0-\uDEF6\uDF00-\uDF92\uDF94-\uDFCA\uDFF0-\uDFF9]|\uDB40[\uDC01\uDC20-\uDC7F]"
    }, {
      'name': 'Coptic',
      'bmp': "\u03E2-\u03EF\u2C80-\u2CF3\u2CF9-\u2CFF"
    }, {
      'name': 'Cuneiform',
      'astral': "\uD808[\uDC00-\uDF99]|\uD809[\uDC00-\uDC6E\uDC70-\uDC74\uDC80-\uDD43]"
    }, {
      'name': 'Cypriot',
      'astral': "\uD802[\uDC00-\uDC05\uDC08\uDC0A-\uDC35\uDC37\uDC38\uDC3C\uDC3F]"
    }, {
      'name': 'Cypro_Minoan',
      'astral': "\uD80B[\uDF90-\uDFF2]"
    }, {
      'name': 'Cyrillic',
      'bmp': "\u0400-\u0484\u0487-\u052F\u1C80-\u1C88\u1D2B\u1D78\u2DE0-\u2DFF\uA640-\uA69F\uFE2E\uFE2F"
    }, {
      'name': 'Deseret',
      'astral': "\uD801[\uDC00-\uDC4F]"
    }, {
      'name': 'Devanagari',
      'bmp': "\u0900-\u0950\u0955-\u0963\u0966-\u097F\uA8E0-\uA8FF"
    }, {
      'name': 'Dives_Akuru',
      'astral': "\uD806[\uDD00-\uDD06\uDD09\uDD0C-\uDD13\uDD15\uDD16\uDD18-\uDD35\uDD37\uDD38\uDD3B-\uDD46\uDD50-\uDD59]"
    }, {
      'name': 'Dogra',
      'astral': "\uD806[\uDC00-\uDC3B]"
    }, {
      'name': 'Duployan',
      'astral': "\uD82F[\uDC00-\uDC6A\uDC70-\uDC7C\uDC80-\uDC88\uDC90-\uDC99\uDC9C-\uDC9F]"
    }, {
      'name': 'Egyptian_Hieroglyphs',
      'astral': "\uD80C[\uDC00-\uDFFF]|\uD80D[\uDC00-\uDC2E\uDC30-\uDC38]"
    }, {
      'name': 'Elbasan',
      'astral': "\uD801[\uDD00-\uDD27]"
    }, {
      'name': 'Elymaic',
      'astral': "\uD803[\uDFE0-\uDFF6]"
    }, {
      'name': 'Ethiopic',
      'bmp': "\u1200-\u1248\u124A-\u124D\u1250-\u1256\u1258\u125A-\u125D\u1260-\u1288\u128A-\u128D\u1290-\u12B0\u12B2-\u12B5\u12B8-\u12BE\u12C0\u12C2-\u12C5\u12C8-\u12D6\u12D8-\u1310\u1312-\u1315\u1318-\u135A\u135D-\u137C\u1380-\u1399\u2D80-\u2D96\u2DA0-\u2DA6\u2DA8-\u2DAE\u2DB0-\u2DB6\u2DB8-\u2DBE\u2DC0-\u2DC6\u2DC8-\u2DCE\u2DD0-\u2DD6\u2DD8-\u2DDE\uAB01-\uAB06\uAB09-\uAB0E\uAB11-\uAB16\uAB20-\uAB26\uAB28-\uAB2E",
      'astral': "\uD839[\uDFE0-\uDFE6\uDFE8-\uDFEB\uDFED\uDFEE\uDFF0-\uDFFE]"
    }, {
      'name': 'Georgian',
      'bmp': "\u10A0-\u10C5\u10C7\u10CD\u10D0-\u10FA\u10FC-\u10FF\u1C90-\u1CBA\u1CBD-\u1CBF\u2D00-\u2D25\u2D27\u2D2D"
    }, {
      'name': 'Glagolitic',
      'bmp': "\u2C00-\u2C5F",
      'astral': "\uD838[\uDC00-\uDC06\uDC08-\uDC18\uDC1B-\uDC21\uDC23\uDC24\uDC26-\uDC2A]"
    }, {
      'name': 'Gothic',
      'astral': "\uD800[\uDF30-\uDF4A]"
    }, {
      'name': 'Grantha',
      'astral': "\uD804[\uDF00-\uDF03\uDF05-\uDF0C\uDF0F\uDF10\uDF13-\uDF28\uDF2A-\uDF30\uDF32\uDF33\uDF35-\uDF39\uDF3C-\uDF44\uDF47\uDF48\uDF4B-\uDF4D\uDF50\uDF57\uDF5D-\uDF63\uDF66-\uDF6C\uDF70-\uDF74]"
    }, {
      'name': 'Greek',
      'bmp': "\u0370-\u0373\u0375-\u0377\u037A-\u037D\u037F\u0384\u0386\u0388-\u038A\u038C\u038E-\u03A1\u03A3-\u03E1\u03F0-\u03FF\u1D26-\u1D2A\u1D5D-\u1D61\u1D66-\u1D6A\u1DBF\u1F00-\u1F15\u1F18-\u1F1D\u1F20-\u1F45\u1F48-\u1F4D\u1F50-\u1F57\u1F59\u1F5B\u1F5D\u1F5F-\u1F7D\u1F80-\u1FB4\u1FB6-\u1FC4\u1FC6-\u1FD3\u1FD6-\u1FDB\u1FDD-\u1FEF\u1FF2-\u1FF4\u1FF6-\u1FFE\u2126\uAB65",
      'astral': "\uD800[\uDD40-\uDD8E\uDDA0]|\uD834[\uDE00-\uDE45]"
    }, {
      'name': 'Gujarati',
      'bmp': "\u0A81-\u0A83\u0A85-\u0A8D\u0A8F-\u0A91\u0A93-\u0AA8\u0AAA-\u0AB0\u0AB2\u0AB3\u0AB5-\u0AB9\u0ABC-\u0AC5\u0AC7-\u0AC9\u0ACB-\u0ACD\u0AD0\u0AE0-\u0AE3\u0AE6-\u0AF1\u0AF9-\u0AFF"
    }, {
      'name': 'Gunjala_Gondi',
      'astral': "\uD807[\uDD60-\uDD65\uDD67\uDD68\uDD6A-\uDD8E\uDD90\uDD91\uDD93-\uDD98\uDDA0-\uDDA9]"
    }, {
      'name': 'Gurmukhi',
      'bmp': "\u0A01-\u0A03\u0A05-\u0A0A\u0A0F\u0A10\u0A13-\u0A28\u0A2A-\u0A30\u0A32\u0A33\u0A35\u0A36\u0A38\u0A39\u0A3C\u0A3E-\u0A42\u0A47\u0A48\u0A4B-\u0A4D\u0A51\u0A59-\u0A5C\u0A5E\u0A66-\u0A76"
    }, {
      'name': 'Han',
      'bmp': "\u2E80-\u2E99\u2E9B-\u2EF3\u2F00-\u2FD5\u3005\u3007\u3021-\u3029\u3038-\u303B\u3400-\u4DBF\u4E00-\u9FFF\uF900-\uFA6D\uFA70-\uFAD9",
      'astral': "\uD81B[\uDFE2\uDFE3\uDFF0\uDFF1]|[\uD840-\uD868\uD86A-\uD86C\uD86F-\uD872\uD874-\uD879\uD880-\uD883][\uDC00-\uDFFF]|\uD869[\uDC00-\uDEDF\uDF00-\uDFFF]|\uD86D[\uDC00-\uDF38\uDF40-\uDFFF]|\uD86E[\uDC00-\uDC1D\uDC20-\uDFFF]|\uD873[\uDC00-\uDEA1\uDEB0-\uDFFF]|\uD87A[\uDC00-\uDFE0]|\uD87E[\uDC00-\uDE1D]|\uD884[\uDC00-\uDF4A]"
    }, {
      'name': 'Hangul',
      'bmp': "\u1100-\u11FF\u302E\u302F\u3131-\u318E\u3200-\u321E\u3260-\u327E\uA960-\uA97C\uAC00-\uD7A3\uD7B0-\uD7C6\uD7CB-\uD7FB\uFFA0-\uFFBE\uFFC2-\uFFC7\uFFCA-\uFFCF\uFFD2-\uFFD7\uFFDA-\uFFDC"
    }, {
      'name': 'Hanifi_Rohingya',
      'astral': "\uD803[\uDD00-\uDD27\uDD30-\uDD39]"
    }, {
      'name': 'Hanunoo',
      'bmp': "\u1720-\u1734"
    }, {
      'name': 'Hatran',
      'astral': "\uD802[\uDCE0-\uDCF2\uDCF4\uDCF5\uDCFB-\uDCFF]"
    }, {
      'name': 'Hebrew',
      'bmp': "\u0591-\u05C7\u05D0-\u05EA\u05EF-\u05F4\uFB1D-\uFB36\uFB38-\uFB3C\uFB3E\uFB40\uFB41\uFB43\uFB44\uFB46-\uFB4F"
    }, {
      'name': 'Hiragana',
      'bmp': "\u3041-\u3096\u309D-\u309F",
      'astral': "\uD82C[\uDC01-\uDD1F\uDD50-\uDD52]|\uD83C\uDE00"
    }, {
      'name': 'Imperial_Aramaic',
      'astral': "\uD802[\uDC40-\uDC55\uDC57-\uDC5F]"
    }, {
      'name': 'Inherited',
      'bmp': "\u0300-\u036F\u0485\u0486\u064B-\u0655\u0670\u0951-\u0954\u1AB0-\u1ACE\u1CD0-\u1CD2\u1CD4-\u1CE0\u1CE2-\u1CE8\u1CED\u1CF4\u1CF8\u1CF9\u1DC0-\u1DFF\u200C\u200D\u20D0-\u20F0\u302A-\u302D\u3099\u309A\uFE00-\uFE0F\uFE20-\uFE2D",
      'astral': "\uD800[\uDDFD\uDEE0]|\uD804\uDF3B|\uD833[\uDF00-\uDF2D\uDF30-\uDF46]|\uD834[\uDD67-\uDD69\uDD7B-\uDD82\uDD85-\uDD8B\uDDAA-\uDDAD]|\uDB40[\uDD00-\uDDEF]"
    }, {
      'name': 'Inscriptional_Pahlavi',
      'astral': "\uD802[\uDF60-\uDF72\uDF78-\uDF7F]"
    }, {
      'name': 'Inscriptional_Parthian',
      'astral': "\uD802[\uDF40-\uDF55\uDF58-\uDF5F]"
    }, {
      'name': 'Javanese',
      'bmp': "\uA980-\uA9CD\uA9D0-\uA9D9\uA9DE\uA9DF"
    }, {
      'name': 'Kaithi',
      'astral': "\uD804[\uDC80-\uDCC2\uDCCD]"
    }, {
      'name': 'Kannada',
      'bmp': "\u0C80-\u0C8C\u0C8E-\u0C90\u0C92-\u0CA8\u0CAA-\u0CB3\u0CB5-\u0CB9\u0CBC-\u0CC4\u0CC6-\u0CC8\u0CCA-\u0CCD\u0CD5\u0CD6\u0CDD\u0CDE\u0CE0-\u0CE3\u0CE6-\u0CEF\u0CF1\u0CF2"
    }, {
      'name': 'Katakana',
      'bmp': "\u30A1-\u30FA\u30FD-\u30FF\u31F0-\u31FF\u32D0-\u32FE\u3300-\u3357\uFF66-\uFF6F\uFF71-\uFF9D",
      'astral': "\uD82B[\uDFF0-\uDFF3\uDFF5-\uDFFB\uDFFD\uDFFE]|\uD82C[\uDC00\uDD20-\uDD22\uDD64-\uDD67]"
    }, {
      'name': 'Kayah_Li',
      'bmp': "\uA900-\uA92D\uA92F"
    }, {
      'name': 'Kharoshthi',
      'astral': "\uD802[\uDE00-\uDE03\uDE05\uDE06\uDE0C-\uDE13\uDE15-\uDE17\uDE19-\uDE35\uDE38-\uDE3A\uDE3F-\uDE48\uDE50-\uDE58]"
    }, {
      'name': 'Khitan_Small_Script',
      'astral': "\uD81B\uDFE4|\uD822[\uDF00-\uDFFF]|\uD823[\uDC00-\uDCD5]"
    }, {
      'name': 'Khmer',
      'bmp': "\u1780-\u17DD\u17E0-\u17E9\u17F0-\u17F9\u19E0-\u19FF"
    }, {
      'name': 'Khojki',
      'astral': "\uD804[\uDE00-\uDE11\uDE13-\uDE3E]"
    }, {
      'name': 'Khudawadi',
      'astral': "\uD804[\uDEB0-\uDEEA\uDEF0-\uDEF9]"
    }, {
      'name': 'Lao',
      'bmp': "\u0E81\u0E82\u0E84\u0E86-\u0E8A\u0E8C-\u0EA3\u0EA5\u0EA7-\u0EBD\u0EC0-\u0EC4\u0EC6\u0EC8-\u0ECD\u0ED0-\u0ED9\u0EDC-\u0EDF"
    }, {
      'name': 'Latin',
      'bmp': "A-Za-z\xAA\xBA\xC0-\xD6\xD8-\xF6\xF8-\u02B8\u02E0-\u02E4\u1D00-\u1D25\u1D2C-\u1D5C\u1D62-\u1D65\u1D6B-\u1D77\u1D79-\u1DBE\u1E00-\u1EFF\u2071\u207F\u2090-\u209C\u212A\u212B\u2132\u214E\u2160-\u2188\u2C60-\u2C7F\uA722-\uA787\uA78B-\uA7CA\uA7D0\uA7D1\uA7D3\uA7D5-\uA7D9\uA7F2-\uA7FF\uAB30-\uAB5A\uAB5C-\uAB64\uAB66-\uAB69\uFB00-\uFB06\uFF21-\uFF3A\uFF41-\uFF5A",
      'astral': "\uD801[\uDF80-\uDF85\uDF87-\uDFB0\uDFB2-\uDFBA]|\uD837[\uDF00-\uDF1E]"
    }, {
      'name': 'Lepcha',
      'bmp': "\u1C00-\u1C37\u1C3B-\u1C49\u1C4D-\u1C4F"
    }, {
      'name': 'Limbu',
      'bmp': "\u1900-\u191E\u1920-\u192B\u1930-\u193B\u1940\u1944-\u194F"
    }, {
      'name': 'Linear_A',
      'astral': "\uD801[\uDE00-\uDF36\uDF40-\uDF55\uDF60-\uDF67]"
    }, {
      'name': 'Linear_B',
      'astral': "\uD800[\uDC00-\uDC0B\uDC0D-\uDC26\uDC28-\uDC3A\uDC3C\uDC3D\uDC3F-\uDC4D\uDC50-\uDC5D\uDC80-\uDCFA]"
    }, {
      'name': 'Lisu',
      'bmp': "\uA4D0-\uA4FF",
      'astral': "\uD807\uDFB0"
    }, {
      'name': 'Lycian',
      'astral': "\uD800[\uDE80-\uDE9C]"
    }, {
      'name': 'Lydian',
      'astral': "\uD802[\uDD20-\uDD39\uDD3F]"
    }, {
      'name': 'Mahajani',
      'astral': "\uD804[\uDD50-\uDD76]"
    }, {
      'name': 'Makasar',
      'astral': "\uD807[\uDEE0-\uDEF8]"
    }, {
      'name': 'Malayalam',
      'bmp': "\u0D00-\u0D0C\u0D0E-\u0D10\u0D12-\u0D44\u0D46-\u0D48\u0D4A-\u0D4F\u0D54-\u0D63\u0D66-\u0D7F"
    }, {
      'name': 'Mandaic',
      'bmp': "\u0840-\u085B\u085E"
    }, {
      'name': 'Manichaean',
      'astral': "\uD802[\uDEC0-\uDEE6\uDEEB-\uDEF6]"
    }, {
      'name': 'Marchen',
      'astral': "\uD807[\uDC70-\uDC8F\uDC92-\uDCA7\uDCA9-\uDCB6]"
    }, {
      'name': 'Masaram_Gondi',
      'astral': "\uD807[\uDD00-\uDD06\uDD08\uDD09\uDD0B-\uDD36\uDD3A\uDD3C\uDD3D\uDD3F-\uDD47\uDD50-\uDD59]"
    }, {
      'name': 'Medefaidrin',
      'astral': "\uD81B[\uDE40-\uDE9A]"
    }, {
      'name': 'Meetei_Mayek',
      'bmp': "\uAAE0-\uAAF6\uABC0-\uABED\uABF0-\uABF9"
    }, {
      'name': 'Mende_Kikakui',
      'astral': "\uD83A[\uDC00-\uDCC4\uDCC7-\uDCD6]"
    }, {
      'name': 'Meroitic_Cursive',
      'astral': "\uD802[\uDDA0-\uDDB7\uDDBC-\uDDCF\uDDD2-\uDDFF]"
    }, {
      'name': 'Meroitic_Hieroglyphs',
      'astral': "\uD802[\uDD80-\uDD9F]"
    }, {
      'name': 'Miao',
      'astral': "\uD81B[\uDF00-\uDF4A\uDF4F-\uDF87\uDF8F-\uDF9F]"
    }, {
      'name': 'Modi',
      'astral': "\uD805[\uDE00-\uDE44\uDE50-\uDE59]"
    }, {
      'name': 'Mongolian',
      'bmp': "\u1800\u1801\u1804\u1806-\u1819\u1820-\u1878\u1880-\u18AA",
      'astral': "\uD805[\uDE60-\uDE6C]"
    }, {
      'name': 'Mro',
      'astral': "\uD81A[\uDE40-\uDE5E\uDE60-\uDE69\uDE6E\uDE6F]"
    }, {
      'name': 'Multani',
      'astral': "\uD804[\uDE80-\uDE86\uDE88\uDE8A-\uDE8D\uDE8F-\uDE9D\uDE9F-\uDEA9]"
    }, {
      'name': 'Myanmar',
      'bmp': "\u1000-\u109F\uA9E0-\uA9FE\uAA60-\uAA7F"
    }, {
      'name': 'Nabataean',
      'astral': "\uD802[\uDC80-\uDC9E\uDCA7-\uDCAF]"
    }, {
      'name': 'Nandinagari',
      'astral': "\uD806[\uDDA0-\uDDA7\uDDAA-\uDDD7\uDDDA-\uDDE4]"
    }, {
      'name': 'New_Tai_Lue',
      'bmp': "\u1980-\u19AB\u19B0-\u19C9\u19D0-\u19DA\u19DE\u19DF"
    }, {
      'name': 'Newa',
      'astral': "\uD805[\uDC00-\uDC5B\uDC5D-\uDC61]"
    }, {
      'name': 'Nko',
      'bmp': "\u07C0-\u07FA\u07FD-\u07FF"
    }, {
      'name': 'Nushu',
      'astral': "\uD81B\uDFE1|\uD82C[\uDD70-\uDEFB]"
    }, {
      'name': 'Nyiakeng_Puachue_Hmong',
      'astral': "\uD838[\uDD00-\uDD2C\uDD30-\uDD3D\uDD40-\uDD49\uDD4E\uDD4F]"
    }, {
      'name': 'Ogham',
      'bmp': "\u1680-\u169C"
    }, {
      'name': 'Ol_Chiki',
      'bmp': "\u1C50-\u1C7F"
    }, {
      'name': 'Old_Hungarian',
      'astral': "\uD803[\uDC80-\uDCB2\uDCC0-\uDCF2\uDCFA-\uDCFF]"
    }, {
      'name': 'Old_Italic',
      'astral': "\uD800[\uDF00-\uDF23\uDF2D-\uDF2F]"
    }, {
      'name': 'Old_North_Arabian',
      'astral': "\uD802[\uDE80-\uDE9F]"
    }, {
      'name': 'Old_Permic',
      'astral': "\uD800[\uDF50-\uDF7A]"
    }, {
      'name': 'Old_Persian',
      'astral': "\uD800[\uDFA0-\uDFC3\uDFC8-\uDFD5]"
    }, {
      'name': 'Old_Sogdian',
      'astral': "\uD803[\uDF00-\uDF27]"
    }, {
      'name': 'Old_South_Arabian',
      'astral': "\uD802[\uDE60-\uDE7F]"
    }, {
      'name': 'Old_Turkic',
      'astral': "\uD803[\uDC00-\uDC48]"
    }, {
      'name': 'Old_Uyghur',
      'astral': "\uD803[\uDF70-\uDF89]"
    }, {
      'name': 'Oriya',
      'bmp': "\u0B01-\u0B03\u0B05-\u0B0C\u0B0F\u0B10\u0B13-\u0B28\u0B2A-\u0B30\u0B32\u0B33\u0B35-\u0B39\u0B3C-\u0B44\u0B47\u0B48\u0B4B-\u0B4D\u0B55-\u0B57\u0B5C\u0B5D\u0B5F-\u0B63\u0B66-\u0B77"
    }, {
      'name': 'Osage',
      'astral': "\uD801[\uDCB0-\uDCD3\uDCD8-\uDCFB]"
    }, {
      'name': 'Osmanya',
      'astral': "\uD801[\uDC80-\uDC9D\uDCA0-\uDCA9]"
    }, {
      'name': 'Pahawh_Hmong',
      'astral': "\uD81A[\uDF00-\uDF45\uDF50-\uDF59\uDF5B-\uDF61\uDF63-\uDF77\uDF7D-\uDF8F]"
    }, {
      'name': 'Palmyrene',
      'astral': "\uD802[\uDC60-\uDC7F]"
    }, {
      'name': 'Pau_Cin_Hau',
      'astral': "\uD806[\uDEC0-\uDEF8]"
    }, {
      'name': 'Phags_Pa',
      'bmp': "\uA840-\uA877"
    }, {
      'name': 'Phoenician',
      'astral': "\uD802[\uDD00-\uDD1B\uDD1F]"
    }, {
      'name': 'Psalter_Pahlavi',
      'astral': "\uD802[\uDF80-\uDF91\uDF99-\uDF9C\uDFA9-\uDFAF]"
    }, {
      'name': 'Rejang',
      'bmp': "\uA930-\uA953\uA95F"
    }, {
      'name': 'Runic',
      'bmp': "\u16A0-\u16EA\u16EE-\u16F8"
    }, {
      'name': 'Samaritan',
      'bmp': "\u0800-\u082D\u0830-\u083E"
    }, {
      'name': 'Saurashtra',
      'bmp': "\uA880-\uA8C5\uA8CE-\uA8D9"
    }, {
      'name': 'Sharada',
      'astral': "\uD804[\uDD80-\uDDDF]"
    }, {
      'name': 'Shavian',
      'astral': "\uD801[\uDC50-\uDC7F]"
    }, {
      'name': 'Siddham',
      'astral': "\uD805[\uDD80-\uDDB5\uDDB8-\uDDDD]"
    }, {
      'name': 'SignWriting',
      'astral': "\uD836[\uDC00-\uDE8B\uDE9B-\uDE9F\uDEA1-\uDEAF]"
    }, {
      'name': 'Sinhala',
      'bmp': "\u0D81-\u0D83\u0D85-\u0D96\u0D9A-\u0DB1\u0DB3-\u0DBB\u0DBD\u0DC0-\u0DC6\u0DCA\u0DCF-\u0DD4\u0DD6\u0DD8-\u0DDF\u0DE6-\u0DEF\u0DF2-\u0DF4",
      'astral': "\uD804[\uDDE1-\uDDF4]"
    }, {
      'name': 'Sogdian',
      'astral': "\uD803[\uDF30-\uDF59]"
    }, {
      'name': 'Sora_Sompeng',
      'astral': "\uD804[\uDCD0-\uDCE8\uDCF0-\uDCF9]"
    }, {
      'name': 'Soyombo',
      'astral': "\uD806[\uDE50-\uDEA2]"
    }, {
      'name': 'Sundanese',
      'bmp': "\u1B80-\u1BBF\u1CC0-\u1CC7"
    }, {
      'name': 'Syloti_Nagri',
      'bmp': "\uA800-\uA82C"
    }, {
      'name': 'Syriac',
      'bmp': "\u0700-\u070D\u070F-\u074A\u074D-\u074F\u0860-\u086A"
    }, {
      'name': 'Tagalog',
      'bmp': "\u1700-\u1715\u171F"
    }, {
      'name': 'Tagbanwa',
      'bmp': "\u1760-\u176C\u176E-\u1770\u1772\u1773"
    }, {
      'name': 'Tai_Le',
      'bmp': "\u1950-\u196D\u1970-\u1974"
    }, {
      'name': 'Tai_Tham',
      'bmp': "\u1A20-\u1A5E\u1A60-\u1A7C\u1A7F-\u1A89\u1A90-\u1A99\u1AA0-\u1AAD"
    }, {
      'name': 'Tai_Viet',
      'bmp': "\uAA80-\uAAC2\uAADB-\uAADF"
    }, {
      'name': 'Takri',
      'astral': "\uD805[\uDE80-\uDEB9\uDEC0-\uDEC9]"
    }, {
      'name': 'Tamil',
      'bmp': "\u0B82\u0B83\u0B85-\u0B8A\u0B8E-\u0B90\u0B92-\u0B95\u0B99\u0B9A\u0B9C\u0B9E\u0B9F\u0BA3\u0BA4\u0BA8-\u0BAA\u0BAE-\u0BB9\u0BBE-\u0BC2\u0BC6-\u0BC8\u0BCA-\u0BCD\u0BD0\u0BD7\u0BE6-\u0BFA",
      'astral': "\uD807[\uDFC0-\uDFF1\uDFFF]"
    }, {
      'name': 'Tangsa',
      'astral': "\uD81A[\uDE70-\uDEBE\uDEC0-\uDEC9]"
    }, {
      'name': 'Tangut',
      'astral': "\uD81B\uDFE0|[\uD81C-\uD820][\uDC00-\uDFFF]|\uD821[\uDC00-\uDFF7]|\uD822[\uDC00-\uDEFF]|\uD823[\uDD00-\uDD08]"
    }, {
      'name': 'Telugu',
      'bmp': "\u0C00-\u0C0C\u0C0E-\u0C10\u0C12-\u0C28\u0C2A-\u0C39\u0C3C-\u0C44\u0C46-\u0C48\u0C4A-\u0C4D\u0C55\u0C56\u0C58-\u0C5A\u0C5D\u0C60-\u0C63\u0C66-\u0C6F\u0C77-\u0C7F"
    }, {
      'name': 'Thaana',
      'bmp': "\u0780-\u07B1"
    }, {
      'name': 'Thai',
      'bmp': "\u0E01-\u0E3A\u0E40-\u0E5B"
    }, {
      'name': 'Tibetan',
      'bmp': "\u0F00-\u0F47\u0F49-\u0F6C\u0F71-\u0F97\u0F99-\u0FBC\u0FBE-\u0FCC\u0FCE-\u0FD4\u0FD9\u0FDA"
    }, {
      'name': 'Tifinagh',
      'bmp': "\u2D30-\u2D67\u2D6F\u2D70\u2D7F"
    }, {
      'name': 'Tirhuta',
      'astral': "\uD805[\uDC80-\uDCC7\uDCD0-\uDCD9]"
    }, {
      'name': 'Toto',
      'astral': "\uD838[\uDE90-\uDEAE]"
    }, {
      'name': 'Ugaritic',
      'astral': "\uD800[\uDF80-\uDF9D\uDF9F]"
    }, {
      'name': 'Vai',
      'bmp': "\uA500-\uA62B"
    }, {
      'name': 'Vithkuqi',
      'astral': "\uD801[\uDD70-\uDD7A\uDD7C-\uDD8A\uDD8C-\uDD92\uDD94\uDD95\uDD97-\uDDA1\uDDA3-\uDDB1\uDDB3-\uDDB9\uDDBB\uDDBC]"
    }, {
      'name': 'Wancho',
      'astral': "\uD838[\uDEC0-\uDEF9\uDEFF]"
    }, {
      'name': 'Warang_Citi',
      'astral': "\uD806[\uDCA0-\uDCF2\uDCFF]"
    }, {
      'name': 'Yezidi',
      'astral': "\uD803[\uDE80-\uDEA9\uDEAB-\uDEAD\uDEB0\uDEB1]"
    }, {
      'name': 'Yi',
      'bmp': "\uA000-\uA48C\uA490-\uA4C6"
    }, {
      'name': 'Zanabazar_Square',
      'astral': "\uD806[\uDE00-\uDE47]"
    }];
    var scripts$1 = /*@__PURE__*/getDefaultExportFromCjs$1(scripts);

    /*!
     * XRegExp Unicode Scripts 5.1.1
     * <xregexp.com>
     * Steven Levithan (c) 2010-present MIT License
     * Unicode data by Mathias Bynens <mathiasbynens.be>
     */

    var unicodeScripts = (function (XRegExp) {
      /**
       * Adds support for all Unicode scripts. E.g., `\p{Latin}`. Token names are case insensitive,
       * and any spaces, hyphens, and underscores are ignored.
       *
       * Uses Unicode 14.0.0.
       *
       * @requires XRegExp, Unicode Base
       */

      if (!XRegExp.addUnicodeData) {
        throw new ReferenceError('Unicode Base must be loaded before Unicode Scripts');
      }
      XRegExp.addUnicodeData(scripts$1, 'Script');
    });

    build(XRegExp);
    matchRecursive(XRegExp);
    unicodeBase(XRegExp);
    unicodeCategories(XRegExp);
    unicodeProperties(XRegExp);
    unicodeScripts(XRegExp);

    var toString = Object.prototype.toString;
    var kindOf = function kindOf(val) {
      if (val === void 0) return 'undefined';
      if (val === null) return 'null';
      var type = typeof val;
      if (type === 'boolean') return 'boolean';
      if (type === 'string') return 'string';
      if (type === 'number') return 'number';
      if (type === 'symbol') return 'symbol';
      if (type === 'function') {
        return isGeneratorFn(val) ? 'generatorfunction' : 'function';
      }
      if (isArray(val)) return 'array';
      if (isBuffer(val)) return 'buffer';
      if (isArguments(val)) return 'arguments';
      if (isDate(val)) return 'date';
      if (isError(val)) return 'error';
      if (isRegexp(val)) return 'regexp';
      switch (ctorName(val)) {
        case 'Symbol':
          return 'symbol';
        case 'Promise':
          return 'promise';

        // Set, Map, WeakSet, WeakMap
        case 'WeakMap':
          return 'weakmap';
        case 'WeakSet':
          return 'weakset';
        case 'Map':
          return 'map';
        case 'Set':
          return 'set';

        // 8-bit typed arrays
        case 'Int8Array':
          return 'int8array';
        case 'Uint8Array':
          return 'uint8array';
        case 'Uint8ClampedArray':
          return 'uint8clampedarray';

        // 16-bit typed arrays
        case 'Int16Array':
          return 'int16array';
        case 'Uint16Array':
          return 'uint16array';

        // 32-bit typed arrays
        case 'Int32Array':
          return 'int32array';
        case 'Uint32Array':
          return 'uint32array';
        case 'Float32Array':
          return 'float32array';
        case 'Float64Array':
          return 'float64array';
      }
      if (isGeneratorObj(val)) {
        return 'generator';
      }

      // Non-plain objects
      type = toString.call(val);
      switch (type) {
        case '[object Object]':
          return 'object';
        // iterators
        case '[object Map Iterator]':
          return 'mapiterator';
        case '[object Set Iterator]':
          return 'setiterator';
        case '[object String Iterator]':
          return 'stringiterator';
        case '[object Array Iterator]':
          return 'arrayiterator';
      }

      // other
      return type.slice(8, -1).toLowerCase().replace(/\s/g, '');
    };
    function ctorName(val) {
      return typeof val.constructor === 'function' ? val.constructor.name : null;
    }
    function isArray(val) {
      if (Array.isArray) return Array.isArray(val);
      return val instanceof Array;
    }
    function isError(val) {
      return val instanceof Error || typeof val.message === 'string' && val.constructor && typeof val.constructor.stackTraceLimit === 'number';
    }
    function isDate(val) {
      if (val instanceof Date) return true;
      return typeof val.toDateString === 'function' && typeof val.getDate === 'function' && typeof val.setDate === 'function';
    }
    function isRegexp(val) {
      if (val instanceof RegExp) return true;
      return typeof val.flags === 'string' && typeof val.ignoreCase === 'boolean' && typeof val.multiline === 'boolean' && typeof val.global === 'boolean';
    }
    function isGeneratorFn(name, val) {
      return ctorName(name) === 'GeneratorFunction';
    }
    function isGeneratorObj(val) {
      return typeof val.throw === 'function' && typeof val.return === 'function' && typeof val.next === 'function';
    }
    function isArguments(val) {
      try {
        if (typeof val.length === 'number' && typeof val.callee === 'function') {
          return true;
        }
      } catch (err) {
        if (err.message.indexOf('callee') !== -1) {
          return true;
        }
      }
      return false;
    }

    /**
     * If you need to support Safari 5-7 (8-10 yr-old browser),
     * take a look at https://github.com/feross/is-buffer
     */

    function isBuffer(val) {
      if (val.constructor && typeof val.constructor.isBuffer === 'function') {
        return val.constructor.isBuffer(val);
      }
      return false;
    }

    /*!
     * shallow-clone <https://github.com/jonschlinkert/shallow-clone>
     *
     * Copyright (c) 2015-present, Jon Schlinkert.
     * Released under the MIT License.
     */
    var valueOf = Symbol.prototype.valueOf;
    var typeOf$1 = kindOf;
    function clone$2(val, deep) {
      switch (typeOf$1(val)) {
        case 'array':
          return val.slice();
        case 'object':
          return Object.assign({}, val);
        case 'date':
          return new val.constructor(Number(val));
        case 'map':
          return new Map(val);
        case 'set':
          return new Set(val);
        case 'buffer':
          return cloneBuffer(val);
        case 'symbol':
          return cloneSymbol(val);
        case 'arraybuffer':
          return cloneArrayBuffer(val);
        case 'float32array':
        case 'float64array':
        case 'int16array':
        case 'int32array':
        case 'int8array':
        case 'uint16array':
        case 'uint32array':
        case 'uint8clampedarray':
        case 'uint8array':
          return cloneTypedArray(val);
        case 'regexp':
          return cloneRegExp(val);
        case 'error':
          return Object.create(val);
        default:
          {
            return val;
          }
      }
    }
    function cloneRegExp(val) {
      var flags = val.flags !== void 0 ? val.flags : /\w+$/.exec(val) || void 0;
      var re = new val.constructor(val.source, flags);
      re.lastIndex = val.lastIndex;
      return re;
    }
    function cloneArrayBuffer(val) {
      var res = new val.constructor(val.byteLength);
      new Uint8Array(res).set(new Uint8Array(val));
      return res;
    }
    function cloneTypedArray(val, deep) {
      return new val.constructor(val.buffer, val.byteOffset, val.length);
    }
    function cloneBuffer(val) {
      var len = val.length;
      var buf = Buffer.allocUnsafe ? Buffer.allocUnsafe(len) : Buffer.from(len);
      val.copy(buf);
      return buf;
    }
    function cloneSymbol(val) {
      return valueOf ? Object(valueOf.call(val)) : {};
    }

    /**
     * Expose `clone`
     */

    var shallowClone = clone$2;

    /*!
     * isobject <https://github.com/jonschlinkert/isobject>
     *
     * Copyright (c) 2014-2017, Jon Schlinkert.
     * Released under the MIT License.
     */
    var isobject = function isObject(val) {
      return val != null && typeof val === 'object' && Array.isArray(val) === false;
    };

    /*!
     * is-plain-object <https://github.com/jonschlinkert/is-plain-object>
     *
     * Copyright (c) 2014-2017, Jon Schlinkert.
     * Released under the MIT License.
     */
    var isObject$3 = isobject;
    function isObjectObject(o) {
      return isObject$3(o) === true && Object.prototype.toString.call(o) === '[object Object]';
    }
    var isPlainObject$1 = function isPlainObject(o) {
      var ctor, prot;
      if (isObjectObject(o) === false) return false;

      // If has modified constructor
      ctor = o.constructor;
      if (typeof ctor !== 'function') return false;

      // If has modified prototype
      prot = ctor.prototype;
      if (isObjectObject(prot) === false) return false;

      // If constructor does not have an Object-specific method
      if (prot.hasOwnProperty('isPrototypeOf') === false) {
        return false;
      }

      // Most likely a plain Object
      return true;
    };

    /**
     * Module dependenices
     */

    var clone$1 = shallowClone;
    var typeOf = kindOf;
    var isPlainObject = isPlainObject$1;
    function cloneDeep(val, instanceClone) {
      switch (typeOf(val)) {
        case 'object':
          return cloneObjectDeep(val, instanceClone);
        case 'array':
          return cloneArrayDeep(val, instanceClone);
        default:
          {
            return clone$1(val);
          }
      }
    }
    function cloneObjectDeep(val, instanceClone) {
      if (typeof instanceClone === 'function') {
        return instanceClone(val);
      }
      if (instanceClone || isPlainObject(val)) {
        var res = new val.constructor();
        for (var key in val) {
          res[key] = cloneDeep(val[key], instanceClone);
        }
        return res;
      }
      return val;
    }
    function cloneArrayDeep(val, instanceClone) {
      var res = new val.constructor(val.length);
      for (var i = 0; i < val.length; i++) {
        res[i] = cloneDeep(val[i], instanceClone);
      }
      return res;
    }

    /**
     * Expose `cloneDeep`
     */

    var cloneDeep_1 = cloneDeep;
    var cloneDeep$1 = /*@__PURE__*/getDefaultExportFromCjs$1(cloneDeep_1);

    var compatibilityTableData$1 = {};

    /**
    * @file Compatibility tables data for AGTree
    *
    * This file is auto-generated from YAML files in the "compatibility-tables" directory.
    * It is optimized for better runtime usage and storage efficiency.
    *
    * We use "shared" section to share the same values between different map keys
    * to reduce the storage usage.
    */
    Object.defineProperty(compatibilityTableData$1, '__esModule', {
      value: true
    });
    var modifiersCompatibilityTableData = {
      shared: [{
        shared: [{
          name: "all",
          aliases: null,
          description: "$all modifier is made of $document, $popup, and all content-type modifiers combined.",
          docs: "https://adguard.app/kb/general/ad-filtering/create-own-filters/#all-modifier",
          versionAdded: null,
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          conflicts: null,
          inverseConflicts: false,
          assignable: false,
          negatable: false,
          blockOnly: true,
          exceptionOnly: false,
          valueOptional: false,
          valueFormat: null
        }, {
          name: "all",
          aliases: null,
          description: "The `all` option is equivalent to specifying all network-based types\n+ `popup`, `document`, `inline-font` and `inline-script`.",
          docs: "https://github.com/gorhill/uBlock/wiki/Static-filter-syntax#all",
          versionAdded: null,
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          conflicts: null,
          inverseConflicts: false,
          assignable: false,
          negatable: false,
          blockOnly: false,
          exceptionOnly: false,
          valueOptional: false,
          valueFormat: null
        }],
        map: {
          "1": 0,
          "2": 0,
          "4": 0,
          "8": 0,
          "16": 0,
          "32": 0,
          "64": 0,
          "256": 0,
          "512": 0,
          "1024": 1,
          "2048": 1,
          "4096": 1,
          "8192": 1
        }
      }, {
        shared: [{
          name: "app",
          aliases: null,
          description: "The `$app` modifier lets you narrow the rule coverage down to a specific application or a list of applications.\nThe modifier's behavior and syntax perfectly match the corresponding basic rules `$app` modifier.",
          docs: "https://adguard.app/kb/general/ad-filtering/create-own-filters/#app-modifier",
          versionAdded: null,
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          conflicts: null,
          inverseConflicts: false,
          assignable: true,
          negatable: false,
          blockOnly: false,
          exceptionOnly: false,
          valueOptional: false,
          valueFormat: "pipe_separated_apps"
        }],
        map: {
          "1": 0,
          "2": 0,
          "4": 0
        }
      }, {
        shared: [{
          name: "badfilter",
          aliases: null,
          description: "The rules with the `$badfilter` modifier disable other basic rules to which they refer. It means that\nthe text of the disabled rule should match the text of the `$badfilter` rule (without the `$badfilter` modifier).",
          docs: "https://adguard.app/kb/general/ad-filtering/create-own-filters/#badfilter-modifier",
          versionAdded: null,
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          conflicts: null,
          inverseConflicts: false,
          assignable: false,
          negatable: false,
          blockOnly: false,
          exceptionOnly: false,
          valueOptional: false,
          valueFormat: null
        }, {
          name: "badfilter",
          aliases: null,
          description: "The rules with the `$badfilter` modifier disable other basic rules to which they refer. It means that\nthe text of the disabled rule should match the text of the `$badfilter` rule (without the `$badfilter` modifier).",
          docs: "https://github.com/gorhill/uBlock/wiki/Static-filter-syntax#badfilter",
          versionAdded: null,
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          conflicts: null,
          inverseConflicts: false,
          assignable: false,
          negatable: false,
          blockOnly: false,
          exceptionOnly: false,
          valueOptional: false,
          valueFormat: null
        }],
        map: {
          "1": 0,
          "2": 0,
          "4": 0,
          "8": 0,
          "16": 0,
          "32": 0,
          "64": 0,
          "256": 0,
          "512": 0,
          "1024": 1,
          "2048": 1,
          "4096": 1,
          "8192": 1
        }
      }, {
        shared: [{
          name: "cname",
          aliases: null,
          description: "When used in an exception filter,\nit will bypass blocking CNAME uncloaked requests for the current (specified) document.",
          docs: "https://github.com/gorhill/uBlock/wiki/Static-filter-syntax#cname",
          versionAdded: null,
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          conflicts: null,
          inverseConflicts: false,
          assignable: false,
          negatable: false,
          blockOnly: false,
          exceptionOnly: true,
          valueOptional: false,
          valueFormat: null
        }],
        map: {
          "1024": 0,
          "2048": 0,
          "4096": 0,
          "8192": 0
        }
      }, {
        shared: [{
          name: "content",
          aliases: null,
          description: "Disables HTML filtering and `$replace` rules on the pages that match the rule.",
          docs: "https://adguard.app/kb/general/ad-filtering/create-own-filters/#content-modifier",
          versionAdded: null,
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          conflicts: null,
          inverseConflicts: false,
          assignable: false,
          negatable: false,
          blockOnly: false,
          exceptionOnly: true,
          valueOptional: false,
          valueFormat: null
        }],
        map: {
          "1": 0,
          "2": 0,
          "4": 0
        }
      }, {
        shared: [{
          name: "cookie",
          aliases: null,
          description: "The `$cookie` modifier completely changes rule behavior.\nInstead of blocking a request, this modifier makes us suppress or modify the Cookie and Set-Cookie headers.",
          docs: "https://adguard.app/kb/general/ad-filtering/create-own-filters/#cookie-modifier",
          versionAdded: null,
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          conflicts: null,
          inverseConflicts: false,
          assignable: true,
          negatable: false,
          blockOnly: false,
          exceptionOnly: false,
          valueOptional: true,
          valueFormat: "^([^;=\\s]*?)((?:;(maxAge=\\d+;?)?|(sameSite=(lax|none|strict);?)?){1,3})(?<!;)$"
        }],
        map: {
          "1": 0,
          "2": 0,
          "4": 0,
          "8": 0,
          "16": 0,
          "32": 0,
          "64": 0
        }
      }, {
        shared: [{
          name: "csp",
          aliases: null,
          description: "This modifier completely changes the rule behavior.\nIf it is applied to a rule, it will not block the matching request.\nThe response headers are going to be modified instead.",
          docs: "https://adguard.app/kb/general/ad-filtering/create-own-filters/#csp-modifier",
          versionAdded: null,
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          conflicts: ["domain", "important", "subdocument", "badfilter"],
          inverseConflicts: true,
          assignable: true,
          negatable: false,
          blockOnly: false,
          exceptionOnly: false,
          valueOptional: true,
          valueFormat: "csp_value"
        }, {
          name: "csp",
          aliases: null,
          description: "This modifier completely changes the rule behavior.\nIf it is applied to a rule, it will not block the matching request.\nThe response headers are going to be modified instead.",
          docs: "https://github.com/gorhill/uBlock/wiki/Static-filter-syntax#csp",
          versionAdded: null,
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          conflicts: ["1p", "3p", "domain", "badfilter"],
          inverseConflicts: true,
          assignable: true,
          negatable: false,
          blockOnly: false,
          exceptionOnly: false,
          valueOptional: true,
          valueFormat: "csp_value"
        }, {
          name: "csp",
          aliases: null,
          description: "This modifier completely changes the rule behavior.\nIf it is applied to a rule, it will not block the matching request.\nThe response headers are going to be modified instead.",
          docs: "https://help.adblockplus.org/hc/en-us/articles/360062733293-How-to-write-filters#content-security-policies",
          versionAdded: null,
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          conflicts: ["domain", "subdocument"],
          inverseConflicts: true,
          assignable: true,
          negatable: false,
          blockOnly: false,
          exceptionOnly: false,
          valueOptional: true,
          valueFormat: "csp_value"
        }],
        map: {
          "1": 0,
          "2": 0,
          "4": 0,
          "8": 0,
          "16": 0,
          "32": 0,
          "64": 0,
          "1024": 1,
          "2048": 1,
          "4096": 1,
          "8192": 1,
          "16384": 2,
          "32768": 2,
          "65536": 2,
          "131072": 2
        }
      }, {
        shared: [{
          name: "denyallow",
          aliases: null,
          description: "The `$denyallow` modifier allows to avoid creating additional rules\nwhen it is needed to disable a certain rule for specific domains.\n`$denyallow` matches only target domains and not referrer domains.",
          docs: "https://adguard.app/kb/general/ad-filtering/create-own-filters/#denyallow-modifier",
          versionAdded: null,
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          conflicts: ["to"],
          inverseConflicts: false,
          assignable: true,
          negatable: false,
          blockOnly: false,
          exceptionOnly: false,
          valueOptional: false,
          valueFormat: "pipe_separated_denyallow_domains"
        }, {
          name: "denyallow",
          aliases: null,
          description: "The `$denyallow` modifier allows to avoid creating additional rules\nwhen it is needed to disable a certain rule for specific domains.\n`$denyallow` matches only target domains and not referrer domains.",
          docs: "https://github.com/gorhill/uBlock/wiki/Static-filter-syntax#denyallow",
          versionAdded: null,
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          conflicts: ["to"],
          inverseConflicts: false,
          assignable: true,
          negatable: false,
          blockOnly: false,
          exceptionOnly: false,
          valueOptional: false,
          valueFormat: "pipe_separated_denyallow_domains"
        }],
        map: {
          "1": 0,
          "2": 0,
          "4": 0,
          "8": 0,
          "16": 0,
          "32": 0,
          "64": 0,
          "256": 0,
          "512": 0,
          "1024": 1,
          "2048": 1,
          "4096": 1,
          "8192": 1
        }
      }, {
        shared: [{
          name: "document",
          aliases: null,
          description: "The rule corresponds to the main frame document requests,\ni.e. HTML documents that are loaded in the browser tab.",
          docs: "https://adguard.app/kb/general/ad-filtering/create-own-filters/#document-modifier",
          versionAdded: null,
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          conflicts: null,
          inverseConflicts: false,
          assignable: false,
          negatable: false,
          blockOnly: false,
          exceptionOnly: false,
          valueOptional: false,
          valueFormat: null
        }, {
          name: "document",
          aliases: null,
          description: "The rule corresponds to the main frame document requests,\ni.e. HTML documents that are loaded in the browser tab.",
          docs: "https://adguard.app/kb/general/ad-filtering/create-own-filters/#document-modifier",
          versionAdded: null,
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          conflicts: null,
          inverseConflicts: false,
          assignable: false,
          negatable: false,
          blockOnly: false,
          exceptionOnly: false,
          valueOptional: false,
          valueFormat: null
        }, {
          name: "document",
          aliases: null,
          description: "The rule corresponds to the main frame document requests,\ni.e. HTML documents that are loaded in the browser tab.",
          docs: "https://adguard.app/kb/general/ad-filtering/create-own-filters/#document-modifier",
          versionAdded: null,
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          conflicts: null,
          inverseConflicts: false,
          assignable: false,
          negatable: false,
          blockOnly: false,
          exceptionOnly: false,
          valueOptional: false,
          valueFormat: null
        }, {
          name: "document",
          aliases: null,
          description: "The rule corresponds to the main frame document requests,\ni.e. HTML documents that are loaded in the browser tab.",
          docs: "https://adguard.app/kb/general/ad-filtering/create-own-filters/#document-modifier",
          versionAdded: null,
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          conflicts: null,
          inverseConflicts: false,
          assignable: false,
          negatable: false,
          blockOnly: false,
          exceptionOnly: false,
          valueOptional: false,
          valueFormat: null
        }, {
          name: "document",
          aliases: ["doc"],
          description: "The rule corresponds to the main frame document requests,\ni.e. HTML documents that are loaded in the browser tab.",
          docs: "https://github.com/gorhill/uBlock/wiki/Static-filter-syntax#document",
          versionAdded: null,
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          conflicts: null,
          inverseConflicts: false,
          assignable: false,
          negatable: false,
          blockOnly: false,
          exceptionOnly: false,
          valueOptional: false,
          valueFormat: null
        }, {
          name: "document",
          aliases: null,
          description: "The rule corresponds to the main frame document requests,\ni.e. HTML documents that are loaded in the browser tab.",
          docs: "https://help.adblockplus.org/hc/en-us/articles/360062733293-How-to-write-filters#allowlist",
          versionAdded: null,
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          conflicts: null,
          inverseConflicts: false,
          assignable: false,
          negatable: false,
          blockOnly: false,
          exceptionOnly: false,
          valueOptional: false,
          valueFormat: null
        }],
        map: {
          "1": 0,
          "2": 0,
          "4": 0,
          "8": 1,
          "16": 1,
          "32": 1,
          "64": 1,
          "256": 2,
          "512": 3,
          "1024": 4,
          "2048": 4,
          "4096": 4,
          "8192": 4,
          "16384": 5,
          "32768": 5,
          "65536": 5,
          "131072": 5
        }
      }, {
        shared: [{
          name: "domain",
          aliases: ["from"],
          description: "The `$domain` modifier limits the rule application area to a list of domains and their subdomains.",
          docs: "https://adguard.app/kb/general/ad-filtering/create-own-filters/#domain-modifier",
          versionAdded: null,
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          conflicts: null,
          inverseConflicts: false,
          assignable: true,
          negatable: false,
          blockOnly: false,
          exceptionOnly: false,
          valueOptional: false,
          valueFormat: "pipe_separated_domains"
        }, {
          name: "domain",
          aliases: ["from"],
          description: "The `$domain` modifier limits the rule application area to a list of domains and their subdomains.",
          docs: "https://github.com/gorhill/uBlock/wiki/Static-filter-syntax#from",
          versionAdded: null,
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          conflicts: null,
          inverseConflicts: false,
          assignable: true,
          negatable: false,
          blockOnly: false,
          exceptionOnly: false,
          valueOptional: false,
          valueFormat: "pipe_separated_domains"
        }, {
          name: "domain",
          aliases: null,
          description: "The `$domain` modifier limits the rule application area to a list of domains and their subdomains.",
          docs: "https://help.adblockplus.org/hc/en-us/articles/360062733293-How-to-write-filters#domain-restrictions",
          versionAdded: null,
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          conflicts: null,
          inverseConflicts: false,
          assignable: true,
          negatable: false,
          blockOnly: false,
          exceptionOnly: false,
          valueOptional: false,
          valueFormat: "pipe_separated_domains"
        }],
        map: {
          "1": 0,
          "2": 0,
          "4": 0,
          "8": 0,
          "16": 0,
          "32": 0,
          "64": 0,
          "128": 0,
          "256": 0,
          "512": 0,
          "1024": 1,
          "2048": 1,
          "4096": 1,
          "8192": 1,
          "16384": 2,
          "32768": 2,
          "65536": 2,
          "131072": 2
        }
      }, {
        shared: [{
          name: "elemhide",
          aliases: ["ehide"],
          description: "Disables any cosmetic rules on the pages matching the rule.",
          docs: "https://adguard.app/kb/general/ad-filtering/create-own-filters/#elemhide-modifier",
          versionAdded: null,
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          conflicts: null,
          inverseConflicts: false,
          assignable: false,
          negatable: false,
          blockOnly: false,
          exceptionOnly: true,
          valueOptional: false,
          valueFormat: null
        }, {
          name: "elemhide",
          aliases: ["ehide"],
          description: "Disables any cosmetic rules on the pages matching the rule.",
          docs: "https://github.com/gorhill/uBlock/wiki/Static-filter-syntax#elemhide-1",
          versionAdded: null,
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          conflicts: null,
          inverseConflicts: false,
          assignable: false,
          negatable: false,
          blockOnly: false,
          exceptionOnly: true,
          valueOptional: false,
          valueFormat: null
        }, {
          name: "elemhide",
          aliases: ["ehide"],
          description: "Disables any cosmetic rules on the pages matching the rule.",
          docs: "https://help.adblockplus.org/hc/en-us/articles/360062733293-How-to-write-filters#type-options",
          versionAdded: null,
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          conflicts: null,
          inverseConflicts: false,
          assignable: false,
          negatable: false,
          blockOnly: false,
          exceptionOnly: true,
          valueOptional: false,
          valueFormat: null
        }],
        map: {
          "1": 0,
          "2": 0,
          "4": 0,
          "8": 0,
          "16": 0,
          "32": 0,
          "64": 0,
          "128": 0,
          "256": 0,
          "512": 0,
          "1024": 1,
          "2048": 1,
          "4096": 1,
          "8192": 1,
          "16384": 2,
          "32768": 2,
          "65536": 2,
          "131072": 2
        }
      }, {
        shared: [{
          name: "empty",
          aliases: null,
          description: "This modifier is deprecated in favor of the $redirect modifier.\nRules with `$empty` are still supported and being converted into `$redirect=nooptext` now\nbut the support shall be removed in the future.",
          docs: "https://adguard.app/kb/general/ad-filtering/create-own-filters/#empty-modifier",
          versionAdded: null,
          versionRemoved: null,
          deprecated: true,
          deprecationMessage: "Rules with `$empty` are still supported and being converted into `$redirect=nooptext` now\nbut the support shall be removed in the future.",
          removed: false,
          removalMessage: null,
          conflicts: null,
          inverseConflicts: false,
          assignable: false,
          negatable: false,
          blockOnly: false,
          exceptionOnly: false,
          valueOptional: false,
          valueFormat: null
        }, {
          name: "empty",
          aliases: null,
          description: "This modifier is deprecated in favor of the $redirect modifier.\nRules with `$empty` are still supported and being converted into `$redirect=nooptext` now\nbut the support shall be removed in the future.",
          docs: "https://adguard.app/kb/general/ad-filtering/create-own-filters/#empty-modifier",
          versionAdded: null,
          versionRemoved: null,
          deprecated: true,
          deprecationMessage: "Rules with `$empty` are still supported and being converted into `$redirect=nooptext` now\nbut the support shall be removed in the future.",
          removed: false,
          removalMessage: null,
          conflicts: null,
          inverseConflicts: false,
          assignable: false,
          negatable: false,
          blockOnly: false,
          exceptionOnly: false,
          valueOptional: false,
          valueFormat: null
        }, {
          name: "empty",
          aliases: null,
          description: "This modifier is deprecated in favor of the $redirect modifier.\nRules with `$empty` are supported and being converted into `$redirect=nooptext`.",
          docs: "https://github.com/gorhill/uBlock/wiki/Static-filter-syntax#empty",
          versionAdded: null,
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          conflicts: null,
          inverseConflicts: false,
          assignable: false,
          negatable: false,
          blockOnly: false,
          exceptionOnly: false,
          valueOptional: false,
          valueFormat: null
        }],
        map: {
          "1": 0,
          "2": 0,
          "4": 0,
          "8": 1,
          "16": 1,
          "32": 1,
          "64": 1,
          "1024": 2,
          "2048": 2,
          "4096": 2,
          "8192": 2
        }
      }, {
        shared: [{
          name: "extension",
          aliases: null,
          description: "Disables all userscripts on the pages matching this rule.",
          docs: "https://adguard.app/kb/general/ad-filtering/create-own-filters/#extension-modifier",
          versionAdded: null,
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          conflicts: ["domain", "specifichide", "generichide", "elemhide", "genericblock", "urlblock", "jsinject", "content", "xmlhttprequest", "badfilter"],
          inverseConflicts: true,
          assignable: false,
          negatable: true,
          blockOnly: false,
          exceptionOnly: true,
          valueOptional: false,
          valueFormat: null
        }],
        map: {
          "1": 0,
          "2": 0,
          "4": 0
        }
      }, {
        shared: [{
          name: "first-party",
          aliases: ["1p", "~third-party"],
          description: "A restriction of first-party requests. Equal to `~third-party`.",
          docs: "https://adguard.app/kb/general/ad-filtering/create-own-filters/#third-party-modifier",
          versionAdded: null,
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          conflicts: null,
          inverseConflicts: false,
          assignable: false,
          negatable: false,
          blockOnly: false,
          exceptionOnly: false,
          valueOptional: false,
          valueFormat: null
        }, {
          name: "first-party",
          aliases: ["1p", "~third-party"],
          description: "A restriction of first-party requests. Equal to `~third-party`.",
          docs: "https://github.com/gorhill/uBlock/wiki/Static-filter-syntax#1p",
          versionAdded: null,
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          conflicts: null,
          inverseConflicts: false,
          assignable: false,
          negatable: false,
          blockOnly: false,
          exceptionOnly: false,
          valueOptional: false,
          valueFormat: null
        }],
        map: {
          "1": 0,
          "2": 0,
          "4": 0,
          "8": 0,
          "16": 0,
          "32": 0,
          "64": 0,
          "128": 0,
          "256": 0,
          "512": 0,
          "1024": 1,
          "2048": 1,
          "4096": 1,
          "8192": 1
        }
      }, {
        shared: [{
          name: "font",
          aliases: null,
          description: "The rule corresponds to requests for fonts, e.g. `.woff` filename extension.",
          docs: "https://adguard.app/kb/general/ad-filtering/create-own-filters/#font-modifier",
          versionAdded: null,
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          conflicts: null,
          inverseConflicts: false,
          assignable: false,
          negatable: true,
          blockOnly: false,
          exceptionOnly: false,
          valueOptional: false,
          valueFormat: null
        }, {
          name: "font",
          aliases: null,
          description: "The rule corresponds to requests for fonts, e.g. `.woff` filename extension.",
          docs: "https://help.adblockplus.org/hc/en-us/articles/360062733293#options",
          versionAdded: null,
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          conflicts: null,
          inverseConflicts: false,
          assignable: false,
          negatable: true,
          blockOnly: false,
          exceptionOnly: false,
          valueOptional: false,
          valueFormat: null
        }, {
          name: "font",
          aliases: null,
          description: "The rule corresponds to requests for fonts, e.g. `.woff` filename extension.",
          docs: "https://help.adblockplus.org/hc/en-us/articles/360062733293#options",
          versionAdded: null,
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          conflicts: null,
          inverseConflicts: false,
          assignable: false,
          negatable: true,
          blockOnly: false,
          exceptionOnly: false,
          valueOptional: false,
          valueFormat: null
        }],
        map: {
          "1": 0,
          "2": 0,
          "4": 0,
          "8": 0,
          "16": 0,
          "32": 0,
          "64": 0,
          "128": 0,
          "256": 0,
          "512": 0,
          "1024": 1,
          "2048": 1,
          "4096": 1,
          "8192": 1,
          "16384": 2,
          "32768": 2,
          "65536": 2,
          "131072": 2
        }
      }, {
        shared: [{
          name: "genericblock",
          aliases: null,
          description: "Disables generic basic rules on pages that correspond to exception rule.",
          docs: "https://adguard.app/kb/general/ad-filtering/create-own-filters/#genericblock-modifier",
          versionAdded: null,
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          conflicts: ["domain", "specifichide", "generichide", "elemhide", "extension", "jsinject", "content", "badfilter"],
          inverseConflicts: true,
          assignable: false,
          negatable: false,
          blockOnly: false,
          exceptionOnly: true,
          valueOptional: false,
          valueFormat: null
        }, {
          name: "genericblock",
          aliases: null,
          description: "Disables generic basic rules on pages that correspond to exception rule.",
          docs: "https://adguard.app/kb/general/ad-filtering/create-own-filters/#genericblock-modifier",
          versionAdded: null,
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          conflicts: ["domain", "specifichide", "generichide", "elemhide", "jsinject", "badfilter"],
          inverseConflicts: true,
          assignable: false,
          negatable: false,
          blockOnly: false,
          exceptionOnly: true,
          valueOptional: false,
          valueFormat: null
        }, {
          name: "genericblock",
          aliases: null,
          description: "Disables generic basic rules on pages that correspond to exception rule.",
          docs: "https://adguard.app/kb/general/ad-filtering/create-own-filters/#genericblock-modifier",
          versionAdded: null,
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          conflicts: ["domain", "specifichide", "generichide", "elemhide", "jsinject", "badfilter"],
          inverseConflicts: true,
          assignable: false,
          negatable: false,
          blockOnly: false,
          exceptionOnly: true,
          valueOptional: false,
          valueFormat: null
        }, {
          name: "genericblock",
          aliases: null,
          description: "Disables generic basic rules on pages that correspond to exception rule.",
          docs: "https://adguard.app/kb/general/ad-filtering/create-own-filters/#genericblock-modifier",
          versionAdded: null,
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          conflicts: ["domain", "specifichide", "generichide", "elemhide", "jsinject", "badfilter"],
          inverseConflicts: true,
          assignable: false,
          negatable: false,
          blockOnly: false,
          exceptionOnly: true,
          valueOptional: false,
          valueFormat: null
        }, {
          name: "genericblock",
          aliases: null,
          description: "Disables generic basic rules on pages that correspond to exception rule.",
          docs: "https://help.adblockplus.org/hc/en-us/articles/360062733293-How-to-write-filters#type-options",
          versionAdded: null,
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          conflicts: null,
          inverseConflicts: false,
          assignable: false,
          negatable: false,
          blockOnly: false,
          exceptionOnly: true,
          valueOptional: false,
          valueFormat: null
        }],
        map: {
          "1": 0,
          "2": 0,
          "4": 0,
          "8": 1,
          "16": 1,
          "32": 1,
          "64": 1,
          "256": 2,
          "512": 3,
          "16384": 4,
          "32768": 4,
          "65536": 4,
          "131072": 4
        }
      }, {
        shared: [{
          name: "generichide",
          aliases: ["ghide"],
          description: "Disables all generic cosmetic rules.",
          docs: "https://adguard.app/kb/general/ad-filtering/create-own-filters/#generichide-modifier",
          versionAdded: null,
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          conflicts: ["domain", "genericblock", "urlblock", "extension", "jsinject", "content", "xmlhttprequest", "badfilter"],
          inverseConflicts: true,
          assignable: false,
          negatable: false,
          blockOnly: false,
          exceptionOnly: true,
          valueOptional: false,
          valueFormat: null
        }, {
          name: "generichide",
          aliases: ["ghide"],
          description: "Disables all generic cosmetic rules.",
          docs: "https://github.com/gorhill/uBlock/wiki/Static-filter-syntax#generichide",
          versionAdded: null,
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          conflicts: ["domain", "badfilter"],
          inverseConflicts: true,
          assignable: false,
          negatable: false,
          blockOnly: false,
          exceptionOnly: true,
          valueOptional: false,
          valueFormat: null
        }, {
          name: "generichide",
          aliases: null,
          description: "Disables all generic cosmetic rules.",
          docs: "https://help.adblockplus.org/hc/en-us/articles/360062733293-How-to-write-filters#type-options",
          versionAdded: null,
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          conflicts: ["domain"],
          inverseConflicts: true,
          assignable: false,
          negatable: false,
          blockOnly: false,
          exceptionOnly: true,
          valueOptional: false,
          valueFormat: null
        }],
        map: {
          "1": 0,
          "2": 0,
          "4": 0,
          "8": 0,
          "16": 0,
          "32": 0,
          "64": 0,
          "128": 0,
          "256": 0,
          "512": 0,
          "1024": 1,
          "2048": 1,
          "4096": 1,
          "8192": 1,
          "16384": 2,
          "32768": 2,
          "65536": 2,
          "131072": 2
        }
      }, {
        shared: [{
          name: "header",
          aliases: null,
          description: "The `$header` modifier allows matching the HTTP response\nhaving a specific header with (optionally) a specific value.",
          docs: "https://adguard.app/kb/general/ad-filtering/create-own-filters/#header-modifier",
          versionAdded: null,
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          conflicts: null,
          inverseConflicts: false,
          assignable: true,
          negatable: true,
          blockOnly: false,
          exceptionOnly: false,
          valueOptional: false,
          valueFormat: "(?xi)\n  ^\n    # header name\n    [\\w-]+\n    (\n      :\n      # header value: string or regexp\n      (\\w+|\\/.+\\/)\n    )?"
        }, {
          name: "header",
          aliases: null,
          description: "The `$header` modifier allows matching the HTTP response\nhaving a specific header with (optionally) a specific value.",
          docs: "https://adguard.app/kb/general/ad-filtering/create-own-filters/#header-modifier",
          versionAdded: null,
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          conflicts: null,
          inverseConflicts: false,
          assignable: true,
          negatable: true,
          blockOnly: false,
          exceptionOnly: false,
          valueOptional: false,
          valueFormat: "(?xi)\n  ^\n    # header name\n    [\\w-]+\n    (\n      :\n      # header value: string or regexp\n      (\\w+|\\/.+\\/)\n    )?"
        }, {
          name: "header",
          aliases: null,
          description: "The `$header` modifier allows matching the HTTP response\nhaving a specific header with (optionally) a specific value.",
          docs: "https://github.com/gorhill/uBlock/wiki/Static-filter-syntax#header",
          versionAdded: null,
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          conflicts: null,
          inverseConflicts: false,
          assignable: true,
          negatable: true,
          blockOnly: false,
          exceptionOnly: false,
          valueOptional: false,
          valueFormat: "(?xi)\n  ^\n    # header name\n    [\\w-]+\n    (\n      :\n      # header value: string or regexp\n      (\\w+|\\/.+\\/)\n    )?"
        }],
        map: {
          "1": 0,
          "2": 0,
          "4": 0,
          "8": 1,
          "16": 1,
          "32": 1,
          "64": 1,
          "1024": 2,
          "2048": 2,
          "4096": 2,
          "8192": 2
        }
      }, {
        shared: [{
          name: "hls",
          aliases: null,
          description: "The `$hls` rules modify the response of a matching request.\nThey are intended as a convenient way to remove segments from HLS playlists (RFC 8216).",
          docs: "https://adguard.app/kb/general/ad-filtering/create-own-filters/#hls-modifier",
          versionAdded: "CoreLibs 1.10",
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          conflicts: ["domain", "third-party", "app", "important", "match-case", "xmlhttprequest"],
          inverseConflicts: true,
          assignable: true,
          negatable: false,
          blockOnly: false,
          exceptionOnly: false,
          valueOptional: true,
          valueFormat: "(?xi)\n  (\n    # string pattern\n    \\w+\n    # or regexp pattern\n    |\n    # TODO: improve regexp pattern to invalidate unescaped `/`, `$`, and `,`\n    \\/.+\\/\n      # options\n      ([ti]*)?\n  )"
        }],
        map: {
          "1": 0,
          "2": 0,
          "4": 0
        }
      }, {
        shared: [{
          name: "image",
          aliases: null,
          description: "The rule corresponds to images requests.",
          docs: "https://adguard.app/kb/general/ad-filtering/create-own-filters/#image-modifier",
          versionAdded: null,
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          conflicts: null,
          inverseConflicts: false,
          assignable: false,
          negatable: true,
          blockOnly: false,
          exceptionOnly: false,
          valueOptional: false,
          valueFormat: null
        }, {
          name: "image",
          aliases: null,
          description: "The rule corresponds to images requests.",
          docs: "https://help.adblockplus.org/hc/en-us/articles/360062733293#options",
          versionAdded: null,
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          conflicts: null,
          inverseConflicts: false,
          assignable: false,
          negatable: true,
          blockOnly: false,
          exceptionOnly: false,
          valueOptional: false,
          valueFormat: null
        }, {
          name: "image",
          aliases: null,
          description: "The rule corresponds to images requests.",
          docs: "https://help.adblockplus.org/hc/en-us/articles/360062733293#options",
          versionAdded: null,
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          conflicts: null,
          inverseConflicts: false,
          assignable: false,
          negatable: true,
          blockOnly: false,
          exceptionOnly: false,
          valueOptional: false,
          valueFormat: null
        }],
        map: {
          "1": 0,
          "2": 0,
          "4": 0,
          "8": 0,
          "16": 0,
          "32": 0,
          "64": 0,
          "128": 0,
          "256": 0,
          "512": 0,
          "1024": 1,
          "2048": 1,
          "4096": 1,
          "8192": 1,
          "16384": 2,
          "32768": 2,
          "65536": 2,
          "131072": 2
        }
      }, {
        shared: [{
          name: "important",
          aliases: null,
          description: "The `$important` modifier applied to a rule increases its priority\nover any other rule without `$important` modifier. Even over basic exception rules.",
          docs: "https://adguard.app/kb/general/ad-filtering/create-own-filters/#important-modifier",
          versionAdded: null,
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          conflicts: null,
          inverseConflicts: false,
          assignable: false,
          negatable: false,
          blockOnly: false,
          exceptionOnly: false,
          valueOptional: false,
          valueFormat: null
        }, {
          name: "important",
          aliases: null,
          description: "The `$important` modifier applied to a rule increases its priority\nover any other rule without `$important` modifier. Even over basic exception rules.",
          docs: "https://github.com/gorhill/uBlock/wiki/Static-filter-syntax#important",
          versionAdded: null,
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          conflicts: null,
          inverseConflicts: false,
          assignable: false,
          negatable: false,
          blockOnly: false,
          exceptionOnly: false,
          valueOptional: false,
          valueFormat: null
        }],
        map: {
          "1": 0,
          "2": 0,
          "4": 0,
          "8": 0,
          "16": 0,
          "32": 0,
          "64": 0,
          "128": 0,
          "256": 0,
          "512": 0,
          "1024": 1,
          "2048": 1,
          "4096": 1,
          "8192": 1
        }
      }, {
        shared: [{
          name: "inline-font",
          aliases: null,
          description: "The `$inline-font` modifier is a sort of a shortcut for $csp modifier with specific value.\nE.g. `||example.org^$inline-font` is converting into:\n```adblock\n||example.org^$csp=font-src 'self' 'unsafe-eval' http: https: data: blob: mediastream: filesystem:\n```",
          docs: "https://adguard.app/kb/general/ad-filtering/create-own-filters/#inline-font-modifier",
          versionAdded: null,
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          conflicts: null,
          inverseConflicts: false,
          assignable: false,
          negatable: true,
          blockOnly: false,
          exceptionOnly: false,
          valueOptional: false,
          valueFormat: null
        }, {
          name: "inline-font",
          aliases: null,
          description: "The `$inline-font` modifier is a sort of a shortcut for $csp modifier with specific value.\nE.g. `||example.org^$inline-font` is converting into:\n```adblock\n||example.org^$csp=font-src 'self' 'unsafe-eval' http: https: data: blob: mediastream: filesystem:\n```",
          docs: "https://adguard.app/kb/general/ad-filtering/create-own-filters/#inline-font-modifier",
          versionAdded: null,
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          conflicts: null,
          inverseConflicts: false,
          assignable: false,
          negatable: true,
          blockOnly: false,
          exceptionOnly: false,
          valueOptional: false,
          valueFormat: null
        }, {
          name: "inline-font",
          aliases: null,
          description: "The `$inline-font` modifier is a sort of a shortcut for $csp modifier with specific value.\nE.g. `||example.org^$inline-font` is converting into:\n```adblock\n||example.org^$csp=font-src 'self' 'unsafe-eval' http: https: data: blob: mediastream: filesystem:\n```",
          docs: "https://github.com/gorhill/uBlock/wiki/Static-filter-syntax#inline-font",
          versionAdded: null,
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          conflicts: null,
          inverseConflicts: false,
          assignable: false,
          negatable: true,
          blockOnly: false,
          exceptionOnly: false,
          valueOptional: false,
          valueFormat: null
        }],
        map: {
          "1": 0,
          "2": 0,
          "4": 0,
          "8": 1,
          "16": 1,
          "32": 1,
          "64": 1,
          "1024": 2,
          "2048": 2,
          "4096": 2,
          "8192": 2
        }
      }, {
        shared: [{
          name: "inline-script",
          aliases: null,
          description: "The `$inline-script` modifier is a sort of a shortcut for $csp modifier with specific value.\nE.g. `||example.org^$inline-script` is converting into:\n```adblock\n||example.org^$csp=script-src 'self' 'unsafe-eval' http: https: data: blob: mediastream: filesystem:\n```",
          docs: "https://adguard.app/kb/general/ad-filtering/create-own-filters/#inline-script-modifier",
          versionAdded: null,
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          conflicts: null,
          inverseConflicts: false,
          assignable: false,
          negatable: true,
          blockOnly: false,
          exceptionOnly: false,
          valueOptional: false,
          valueFormat: null
        }, {
          name: "inline-script",
          aliases: null,
          description: "The `$inline-script` modifier is a sort of a shortcut for $csp modifier with specific value.\nE.g. `||example.org^$inline-script` is converting into:\n```adblock\n||example.org^$csp=script-src 'self' 'unsafe-eval' http: https: data: blob: mediastream: filesystem:\n```",
          docs: "https://adguard.app/kb/general/ad-filtering/create-own-filters/#inline-script-modifier",
          versionAdded: null,
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          conflicts: null,
          inverseConflicts: false,
          assignable: false,
          negatable: true,
          blockOnly: false,
          exceptionOnly: false,
          valueOptional: false,
          valueFormat: null
        }, {
          name: "inline-script",
          aliases: null,
          description: "The `$inline-script` modifier is a sort of a shortcut for $csp modifier with specific value.\nE.g. `||example.org^$inline-script` is converting into:\n```adblock\n||example.org^$csp=script-src 'self' 'unsafe-eval' http: https: data: blob: mediastream: filesystem:\n```",
          docs: "https://github.com/gorhill/uBlock/wiki/Static-filter-syntax#inline-script",
          versionAdded: null,
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          conflicts: null,
          inverseConflicts: false,
          assignable: false,
          negatable: true,
          blockOnly: false,
          exceptionOnly: false,
          valueOptional: false,
          valueFormat: null
        }],
        map: {
          "1": 0,
          "2": 0,
          "4": 0,
          "8": 1,
          "16": 1,
          "32": 1,
          "64": 1,
          "1024": 2,
          "2048": 2,
          "4096": 2,
          "8192": 2
        }
      }, {
        shared: [{
          name: "jsinject",
          aliases: null,
          description: "Forbids adding of javascript code to the page.",
          docs: "https://adguard.app/kb/general/ad-filtering/create-own-filters/#jsinject-modifier",
          versionAdded: null,
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          conflicts: ["domain", "specifichide", "generichide", "elemhide", "genericblock", "urlblock", "extension", "content", "xmlhttprequest", "badfilter"],
          inverseConflicts: true,
          assignable: false,
          negatable: false,
          blockOnly: false,
          exceptionOnly: true,
          valueOptional: false,
          valueFormat: null
        }, {
          name: "jsinject",
          aliases: null,
          description: "Forbids adding of javascript code to the page.",
          docs: "https://adguard.app/kb/general/ad-filtering/create-own-filters/#jsinject-modifier",
          versionAdded: null,
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          conflicts: ["domain", "specifichide", "generichide", "elemhide", "genericblock", "urlblock", "xmlhttprequest", "badfilter"],
          inverseConflicts: true,
          assignable: false,
          negatable: false,
          blockOnly: false,
          exceptionOnly: true,
          valueOptional: false,
          valueFormat: null
        }, {
          name: "jsinject",
          aliases: null,
          description: "Forbids adding of javascript code to the page.",
          docs: "https://adguard.app/kb/general/ad-filtering/create-own-filters/#jsinject-modifier",
          versionAdded: null,
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          conflicts: ["domain", "specifichide", "generichide", "elemhide", "genericblock", "urlblock", "xmlhttprequest", "badfilter"],
          inverseConflicts: true,
          assignable: false,
          negatable: false,
          blockOnly: false,
          exceptionOnly: true,
          valueOptional: false,
          valueFormat: null
        }, {
          name: "jsinject",
          aliases: null,
          description: "Forbids adding of javascript code to the page.",
          docs: "https://adguard.app/kb/general/ad-filtering/create-own-filters/#jsinject-modifier",
          versionAdded: null,
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          conflicts: ["domain", "specifichide", "generichide", "elemhide", "genericblock", "urlblock", "xmlhttprequest", "badfilter"],
          inverseConflicts: true,
          assignable: false,
          negatable: false,
          blockOnly: false,
          exceptionOnly: true,
          valueOptional: false,
          valueFormat: null
        }],
        map: {
          "1": 0,
          "2": 0,
          "4": 0,
          "8": 1,
          "16": 1,
          "32": 1,
          "64": 1,
          "256": 2,
          "512": 3
        }
      }, {
        shared: [{
          name: "jsonprune",
          aliases: null,
          description: "The `$jsonprune` rules modify the response to a matching request\nby removing JSON items that match a modified JSONPath expression.\nThey do not modify responses which are not valid JSON documents.",
          docs: "https://adguard.app/kb/general/ad-filtering/create-own-filters/#jsonprune-modifier",
          versionAdded: null,
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          conflicts: null,
          inverseConflicts: false,
          assignable: true,
          negatable: false,
          blockOnly: false,
          exceptionOnly: false,
          valueOptional: true,
          valueFormat: "(?xi)\n  ^\n    # the expression always starts with a dollar sign (for root)\n    # which should be escaped\n    \\\\\n    \\$\n    \\.?\n    # TODO: improve the expression to invalidate unescaped `$` and `,`\n    .+\n  $"
        }],
        map: {
          "1": 0,
          "2": 0,
          "4": 0
        }
      }, {
        shared: [{
          name: "match-case",
          aliases: null,
          description: "This modifier defines a rule which applies only to addresses that match the case.\nDefault rules are case-insensitive.",
          docs: "https://adguard.app/kb/general/ad-filtering/create-own-filters/#match-case-modifier",
          versionAdded: null,
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          conflicts: null,
          inverseConflicts: false,
          assignable: false,
          negatable: true,
          blockOnly: false,
          exceptionOnly: false,
          valueOptional: false,
          valueFormat: null
        }, {
          name: "match-case",
          aliases: null,
          description: "This modifier defines a rule which applies only to addresses that match the case.\nDefault rules are case-insensitive.",
          docs: "https://github.com/gorhill/uBlock/wiki/Static-filter-syntax#match-case",
          versionAdded: null,
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          conflicts: null,
          inverseConflicts: false,
          assignable: false,
          negatable: true,
          blockOnly: false,
          exceptionOnly: false,
          valueOptional: false,
          valueFormat: null
        }, {
          name: "match-case",
          aliases: null,
          description: "This modifier defines a rule which applies only to addresses that match the case.\nDefault rules are case-insensitive.",
          docs: "https://help.adblockplus.org/hc/en-us/articles/360062733293-How-to-write-filters#type-options",
          versionAdded: null,
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          conflicts: null,
          inverseConflicts: false,
          assignable: false,
          negatable: true,
          blockOnly: false,
          exceptionOnly: false,
          valueOptional: false,
          valueFormat: null
        }],
        map: {
          "1": 0,
          "2": 0,
          "4": 0,
          "8": 0,
          "16": 0,
          "32": 0,
          "64": 0,
          "128": 0,
          "256": 0,
          "512": 0,
          "1024": 1,
          "2048": 1,
          "4096": 1,
          "8192": 1,
          "16384": 2,
          "32768": 2,
          "65536": 2,
          "131072": 2
        }
      }, {
        shared: [{
          name: "media",
          aliases: null,
          description: "A restriction of third-party and own requests.\nA third-party request is a request from a different domain.\nFor example, a request to `example.org` from `domain.com` is a third-party request.",
          docs: "https://adguard.app/kb/general/ad-filtering/create-own-filters/#media-modifier",
          versionAdded: null,
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          conflicts: null,
          inverseConflicts: false,
          assignable: false,
          negatable: true,
          blockOnly: false,
          exceptionOnly: false,
          valueOptional: false,
          valueFormat: null
        }, {
          name: "media",
          aliases: null,
          description: "A restriction of third-party and own requests.\nA third-party request is a request from a different domain.\nFor example, a request to `example.org` from `domain.com` is a third-party request.",
          docs: "https://help.adblockplus.org/hc/en-us/articles/360062733293#options",
          versionAdded: null,
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          conflicts: null,
          inverseConflicts: false,
          assignable: false,
          negatable: true,
          blockOnly: false,
          exceptionOnly: false,
          valueOptional: false,
          valueFormat: null
        }, {
          name: "media",
          aliases: null,
          description: "A restriction of third-party and own requests.\nA third-party request is a request from a different domain.\nFor example, a request to `example.org` from `domain.com` is a third-party request.",
          docs: "https://help.adblockplus.org/hc/en-us/articles/360062733293#options",
          versionAdded: null,
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          conflicts: null,
          inverseConflicts: false,
          assignable: false,
          negatable: true,
          blockOnly: false,
          exceptionOnly: false,
          valueOptional: false,
          valueFormat: null
        }],
        map: {
          "1": 0,
          "2": 0,
          "4": 0,
          "8": 0,
          "16": 0,
          "32": 0,
          "64": 0,
          "128": 0,
          "256": 0,
          "512": 0,
          "1024": 1,
          "2048": 1,
          "4096": 1,
          "8192": 1,
          "16384": 2,
          "32768": 2,
          "65536": 2,
          "131072": 2
        }
      }, {
        shared: [{
          name: "method",
          aliases: null,
          description: "This modifier limits the rule scope to requests that use the specified set of HTTP methods.\nNegated methods are allowed.",
          docs: "https://adguard.app/kb/general/ad-filtering/create-own-filters/#method-modifier",
          versionAdded: null,
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          conflicts: null,
          inverseConflicts: false,
          assignable: true,
          negatable: false,
          blockOnly: false,
          exceptionOnly: false,
          valueOptional: false,
          valueFormat: "pipe_separated_methods"
        }, {
          name: "method",
          aliases: null,
          description: "This modifier limits the rule scope to requests that use the specified set of HTTP methods.\nNegated methods are allowed.",
          docs: "https://adguard.app/kb/general/ad-filtering/create-own-filters/#method-modifier",
          versionAdded: null,
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          conflicts: null,
          inverseConflicts: false,
          assignable: true,
          negatable: false,
          blockOnly: false,
          exceptionOnly: false,
          valueOptional: false,
          valueFormat: "pipe_separated_methods"
        }, {
          name: "method",
          aliases: null,
          description: "This modifier limits the rule scope to requests that use the specified set of HTTP methods.\nNegated methods are allowed.",
          docs: "https://github.com/gorhill/uBlock/wiki/Static-filter-syntax#method",
          versionAdded: null,
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          conflicts: null,
          inverseConflicts: false,
          assignable: true,
          negatable: false,
          blockOnly: false,
          exceptionOnly: false,
          valueOptional: false,
          valueFormat: "pipe_separated_methods"
        }],
        map: {
          "1": 0,
          "2": 0,
          "4": 0,
          "8": 1,
          "16": 1,
          "32": 1,
          "64": 1,
          "1024": 2,
          "2048": 2,
          "4096": 2,
          "8192": 2
        }
      }, {
        shared: [{
          name: "mp4",
          aliases: null,
          description: "As a response to blocked request AdGuard returns a short video placeholder.\nRules with `$mp4` are still supported and being converted into `$redirect=noopmp4-1s` now\nbut the support shall be removed in the future.",
          docs: "https://adguard.app/kb/general/ad-filtering/create-own-filters/#mp4-modifier",
          versionAdded: null,
          versionRemoved: null,
          deprecated: true,
          deprecationMessage: "Rules with `$mp4` are still supported and being converted into `$redirect=noopmp4-1s` now\nbut the support shall be removed in the future.",
          removed: false,
          removalMessage: null,
          conflicts: null,
          inverseConflicts: false,
          assignable: false,
          negatable: false,
          blockOnly: false,
          exceptionOnly: false,
          valueOptional: false,
          valueFormat: null
        }, {
          name: "mp4",
          aliases: null,
          description: "As a response to blocked request AdGuard returns a short video placeholder.\nRules with `$mp4` are still supported and being converted into `$redirect=noopmp4-1s` now\nbut the support shall be removed in the future.",
          docs: "https://adguard.app/kb/general/ad-filtering/create-own-filters/#mp4-modifier",
          versionAdded: null,
          versionRemoved: null,
          deprecated: true,
          deprecationMessage: "Rules with `$mp4` are still supported and being converted into `$redirect=noopmp4-1s` now\nbut the support shall be removed in the future.",
          removed: false,
          removalMessage: null,
          conflicts: null,
          inverseConflicts: false,
          assignable: false,
          negatable: false,
          blockOnly: false,
          exceptionOnly: false,
          valueOptional: false,
          valueFormat: null
        }, {
          name: "mp4",
          aliases: null,
          description: "As a response to blocked request a short video placeholder is returned.\nRules with `$mp4` are supported and being converted into `$redirect=noopmp4-1s`.",
          docs: "https://github.com/gorhill/uBlock/wiki/Static-filter-syntax#mp4",
          versionAdded: null,
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          conflicts: null,
          inverseConflicts: false,
          assignable: false,
          negatable: false,
          blockOnly: false,
          exceptionOnly: false,
          valueOptional: false,
          valueFormat: null
        }],
        map: {
          "1": 0,
          "2": 0,
          "4": 0,
          "8": 1,
          "16": 1,
          "32": 1,
          "64": 1,
          "1024": 2,
          "2048": 2,
          "4096": 2,
          "8192": 2
        }
      }, {
        shared: [{
          name: "network",
          aliases: null,
          description: "This is basically a Firewall-kind of rules allowing to fully block\nor unblock access to a specified remote address.",
          docs: "https://adguard.app/kb/general/ad-filtering/create-own-filters/#network-modifier",
          versionAdded: null,
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          conflicts: ["app", "important"],
          inverseConflicts: true,
          assignable: false,
          negatable: false,
          blockOnly: false,
          exceptionOnly: false,
          valueOptional: false,
          valueFormat: null
        }],
        map: {
          "1": 0,
          "2": 0,
          "4": 0
        }
      }, {
        shared: [{
          name: "_",
          aliases: null,
          description: "The noop modifier does nothing and can be used solely to increase rules' readability.\nIt consists of a sequence of underscore characters (_) of any length\nand can appear in a rule as many times as needed.",
          docs: "https://adguard.app/kb/general/ad-filtering/create-own-filters/#noop-modifier",
          versionAdded: null,
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          conflicts: null,
          inverseConflicts: false,
          assignable: false,
          negatable: false,
          blockOnly: false,
          exceptionOnly: false,
          valueOptional: false,
          valueFormat: null
        }, {
          name: "_",
          aliases: null,
          description: "The noop modifier does nothing and can be used solely to increase rules' readability.\nIt consists of a sequence of underscore characters (_) of any length\nand can appear in a rule as many times as needed.",
          docs: "https://adguard.app/kb/general/ad-filtering/create-own-filters/#noop-modifier",
          versionAdded: null,
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          conflicts: null,
          inverseConflicts: false,
          assignable: false,
          negatable: false,
          blockOnly: false,
          exceptionOnly: false,
          valueOptional: false,
          valueFormat: null
        }, {
          name: "_",
          aliases: null,
          description: "The noop modifier does nothing and can be used solely to increase rules' readability.\nIt consists of a sequence of underscore characters (_) of any length\nand can appear in a rule as many times as needed.",
          docs: "https://adguard.app/kb/general/ad-filtering/create-own-filters/#noop-modifier",
          versionAdded: null,
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          conflicts: null,
          inverseConflicts: false,
          assignable: false,
          negatable: false,
          blockOnly: false,
          exceptionOnly: false,
          valueOptional: false,
          valueFormat: null
        }, {
          name: "_",
          aliases: null,
          description: "The noop modifier does nothing and can be used solely to increase rules' readability.\nIt consists of a sequence of underscore characters (_) of any length\nand can appear in a rule as many times as needed.",
          docs: "https://adguard.app/kb/general/ad-filtering/create-own-filters/#noop-modifier",
          versionAdded: null,
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          conflicts: null,
          inverseConflicts: false,
          assignable: false,
          negatable: false,
          blockOnly: false,
          exceptionOnly: false,
          valueOptional: false,
          valueFormat: null
        }, {
          name: "_",
          aliases: null,
          description: "The noop modifier does nothing and can be used solely to increase rules' readability.\nIt consists of a sequence of underscore characters (_) of any length\nand can appear in a rule as many times as needed.",
          docs: "https://github.com/gorhill/uBlock/wiki/Static-filter-syntax#_-aka-noop",
          versionAdded: null,
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          conflicts: null,
          inverseConflicts: false,
          assignable: false,
          negatable: false,
          blockOnly: false,
          exceptionOnly: false,
          valueOptional: false,
          valueFormat: null
        }],
        map: {
          "1": 0,
          "2": 0,
          "4": 0,
          "8": 1,
          "16": 1,
          "32": 1,
          "64": 1,
          "256": 2,
          "512": 3,
          "1024": 4,
          "2048": 4,
          "4096": 4,
          "8192": 4
        }
      }, {
        shared: [{
          name: "object-subrequest",
          aliases: null,
          description: "The `$object-subrequest` modifier is removed and is no longer supported.\nRules with it are considered as invalid.\nThe rule corresponds to requests by browser plugins (it is usually Flash).",
          docs: "https://adguard.app/kb/general/ad-filtering/create-own-filters/#object-subrequest-modifier",
          versionAdded: null,
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: true,
          removalMessage: "The `$object-subrequest` modifier is removed and is no longer supported.\nRules with it are considered as invalid.",
          conflicts: null,
          inverseConflicts: false,
          assignable: false,
          negatable: true,
          blockOnly: false,
          exceptionOnly: false,
          valueOptional: false,
          valueFormat: null
        }],
        map: {
          "1": 0,
          "2": 0,
          "4": 0,
          "8": 0,
          "16": 0,
          "32": 0,
          "64": 0,
          "128": 0,
          "256": 0,
          "512": 0
        }
      }, {
        shared: [{
          name: "object",
          aliases: null,
          description: "The rule corresponds to browser plugins resources, e.g. Java or Flash",
          docs: "https://adguard.app/kb/general/ad-filtering/create-own-filters/#object-modifier",
          versionAdded: null,
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          conflicts: null,
          inverseConflicts: false,
          assignable: false,
          negatable: true,
          blockOnly: false,
          exceptionOnly: false,
          valueOptional: false,
          valueFormat: null
        }, {
          name: "object",
          aliases: null,
          description: "The rule corresponds to browser plugins resources, e.g. Java or Flash.",
          docs: "https://help.adblockplus.org/hc/en-us/articles/360062733293-How-to-write-filters#type-options",
          versionAdded: null,
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          conflicts: null,
          inverseConflicts: false,
          assignable: false,
          negatable: true,
          blockOnly: false,
          exceptionOnly: false,
          valueOptional: false,
          valueFormat: null
        }, {
          name: "object",
          aliases: null,
          description: "The rule corresponds to browser plugins resources, e.g. Java or Flash.",
          docs: "https://help.adblockplus.org/hc/en-us/articles/360062733293-How-to-write-filters#type-options",
          versionAdded: null,
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          conflicts: null,
          inverseConflicts: false,
          assignable: false,
          negatable: true,
          blockOnly: false,
          exceptionOnly: false,
          valueOptional: false,
          valueFormat: null
        }],
        map: {
          "1": 0,
          "2": 0,
          "4": 0,
          "8": 0,
          "16": 0,
          "32": 0,
          "64": 0,
          "128": 0,
          "256": 0,
          "512": 0,
          "1024": 1,
          "2048": 1,
          "4096": 1,
          "8192": 1,
          "16384": 2,
          "32768": 2,
          "65536": 2,
          "131072": 2
        }
      }, {
        shared: [{
          name: "other",
          aliases: null,
          description: "The rule applies to requests for which the type has not been determined\nor does not match the types listed above.",
          docs: "https://adguard.app/kb/general/ad-filtering/create-own-filters/#other-modifier",
          versionAdded: null,
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          conflicts: null,
          inverseConflicts: false,
          assignable: false,
          negatable: true,
          blockOnly: false,
          exceptionOnly: false,
          valueOptional: false,
          valueFormat: null
        }, {
          name: "other",
          aliases: null,
          description: "The rule applies to requests for which the type has not been determined\nor does not match the types listed above.",
          docs: "https://help.adblockplus.org/hc/en-us/articles/360062733293-How-to-write-filters#type-options",
          versionAdded: null,
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          conflicts: null,
          inverseConflicts: false,
          assignable: false,
          negatable: true,
          blockOnly: false,
          exceptionOnly: false,
          valueOptional: false,
          valueFormat: null
        }, {
          name: "other",
          aliases: null,
          description: "The rule applies to requests for which the type has not been determined\nor does not match the types listed above.",
          docs: "https://help.adblockplus.org/hc/en-us/articles/360062733293-How-to-write-filters#type-options",
          versionAdded: null,
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          conflicts: null,
          inverseConflicts: false,
          assignable: false,
          negatable: true,
          blockOnly: false,
          exceptionOnly: false,
          valueOptional: false,
          valueFormat: null
        }],
        map: {
          "1": 0,
          "2": 0,
          "4": 0,
          "8": 0,
          "16": 0,
          "32": 0,
          "64": 0,
          "128": 0,
          "256": 0,
          "512": 0,
          "1024": 1,
          "2048": 1,
          "4096": 1,
          "8192": 1,
          "16384": 2,
          "32768": 2,
          "65536": 2,
          "131072": 2
        }
      }, {
        shared: [{
          name: "permissions",
          aliases: null,
          description: "For the requests matching a `$permissions` rule, ad blocker strengthens response's feature policy\nby adding additional feature policy equal to the `$permissions` modifier contents.\n`$permissions` rules are applied independently from any other rule type.",
          docs: "https://adguard.app/kb/general/ad-filtering/create-own-filters/#permissions-modifier",
          versionAdded: "CoreLibs 1.11",
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          conflicts: ["domain", "important", "subdocument"],
          inverseConflicts: true,
          assignable: true,
          negatable: false,
          blockOnly: false,
          exceptionOnly: false,
          valueOptional: true,
          valueFormat: "permissions_value"
        }],
        map: {
          "1": 0,
          "2": 0,
          "4": 0
        }
      }, {
        shared: [{
          name: "ping",
          aliases: null,
          description: "The rule corresponds to requests caused by either navigator.sendBeacon() or the ping attribute on links.",
          docs: "https://adguard.app/kb/general/ad-filtering/create-own-filters/#ping-modifier",
          versionAdded: null,
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          conflicts: null,
          inverseConflicts: false,
          assignable: false,
          negatable: true,
          blockOnly: false,
          exceptionOnly: false,
          valueOptional: false,
          valueFormat: null
        }, {
          name: "ping",
          aliases: null,
          description: "The rule corresponds to requests caused by either navigator.sendBeacon() or the ping attribute on links.",
          docs: "https://help.adblockplus.org/hc/en-us/articles/360062733293-How-to-write-filters#type-options",
          versionAdded: null,
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          conflicts: null,
          inverseConflicts: false,
          assignable: false,
          negatable: true,
          blockOnly: false,
          exceptionOnly: false,
          valueOptional: false,
          valueFormat: null
        }, {
          name: "ping",
          aliases: null,
          description: "The rule corresponds to requests caused by either navigator.sendBeacon() or the ping attribute on links.",
          docs: "https://help.adblockplus.org/hc/en-us/articles/360062733293-How-to-write-filters#type-options",
          versionAdded: null,
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          conflicts: null,
          inverseConflicts: false,
          assignable: false,
          negatable: true,
          blockOnly: false,
          exceptionOnly: false,
          valueOptional: false,
          valueFormat: null
        }],
        map: {
          "1": 0,
          "2": 0,
          "4": 0,
          "8": 0,
          "16": 0,
          "32": 0,
          "64": 0,
          "128": 0,
          "256": 0,
          "512": 0,
          "1024": 1,
          "2048": 1,
          "4096": 1,
          "8192": 1,
          "16384": 2,
          "32768": 2,
          "65536": 2,
          "131072": 2
        }
      }, {
        shared: [{
          name: "popunder",
          aliases: null,
          description: "To block \"popunders\" windows/tabs where the original page redirects to an advertisement\nand the desired content loads in the newly created one.\nTo be used in the same manner as the popup filter option, except that it will block popunders.",
          docs: "https://github.com/gorhill/uBlock/wiki/Static-filter-syntax#popunder",
          versionAdded: null,
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          conflicts: null,
          inverseConflicts: false,
          assignable: false,
          negatable: false,
          blockOnly: true,
          exceptionOnly: false,
          valueOptional: false,
          valueFormat: null
        }],
        map: {
          "1024": 0,
          "2048": 0,
          "4096": 0,
          "8192": 0
        }
      }, {
        shared: [{
          name: "popup",
          aliases: null,
          description: "Pages opened in a new tab or window.\nNote: Filters will not block pop-ups by default, only if the `$popup`  type option is specified.",
          docs: "https://adguard.app/kb/general/ad-filtering/create-own-filters/#popup-modifier",
          versionAdded: null,
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          conflicts: null,
          inverseConflicts: false,
          assignable: false,
          negatable: false,
          blockOnly: false,
          exceptionOnly: false,
          valueOptional: false,
          valueFormat: null
        }, {
          name: "popup",
          aliases: null,
          description: "Pages opened in a new tab or window.\nNote: Filters will not block pop-ups by default, only if the `$popup`  type option is specified.",
          docs: "https://help.adblockplus.org/hc/en-us/articles/360062733293-How-to-write-filters#type-options",
          versionAdded: null,
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          conflicts: null,
          inverseConflicts: false,
          assignable: false,
          negatable: false,
          blockOnly: false,
          exceptionOnly: false,
          valueOptional: false,
          valueFormat: null
        }, {
          name: "popup",
          aliases: null,
          description: "Pages opened in a new tab or window.\nNote: Filters will not block pop-ups by default, only if the `$popup`  type option is specified.",
          docs: "https://help.adblockplus.org/hc/en-us/articles/360062733293-How-to-write-filters#type-options",
          versionAdded: null,
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          conflicts: null,
          inverseConflicts: false,
          assignable: false,
          negatable: false,
          blockOnly: false,
          exceptionOnly: false,
          valueOptional: false,
          valueFormat: null
        }],
        map: {
          "1": 0,
          "2": 0,
          "4": 0,
          "8": 0,
          "16": 0,
          "32": 0,
          "64": 0,
          "128": 0,
          "256": 0,
          "512": 0,
          "1024": 1,
          "2048": 1,
          "4096": 1,
          "8192": 1,
          "16384": 2,
          "32768": 2,
          "65536": 2,
          "131072": 2
        }
      }, {
        shared: [{
          name: "redirect-rule",
          aliases: null,
          description: "This is basically an alias to `$redirect`\nsince it has the same \"redirection\" values and the logic is almost similar.\nThe difference is that `$redirect-rule` is applied only in the case\nwhen the target request is blocked by a different basic rule.",
          docs: "https://adguard.app/kb/general/ad-filtering/create-own-filters/#redirect-rule-modifier",
          versionAdded: null,
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          conflicts: ["domain", "to", "third-party", "popup", "match-case", "header", "first-party", "document", "image", "stylesheet", "script", "object", "font", "media", "subdocument", "ping", "xmlhttprequest", "websocket", "other", "webrtc", "important", "badfilter", "app"],
          inverseConflicts: true,
          assignable: true,
          negatable: false,
          blockOnly: false,
          exceptionOnly: false,
          valueOptional: true,
          valueFormat: "(?x)\n  ^(\n    1x1-transparent\\.gif|\n    2x2-transparent\\.png|\n    3x2-transparent\\.png|\n    32x32-transparent\\.png|\n    noopframe|\n    noopcss|\n    noopjs|\n    noopjson|\n    nooptext|\n    empty|\n    noopvmap-1\\.0|\n    noopvast-2\\.0|\n    noopvast-3\\.0|\n    noopvast-4\\.0|\n    noopmp3-0\\.1s|\n    noopmp4-1s|\n    amazon-apstag|\n    ati-smarttag|\n    didomi-loader|\n    fingerprintjs2|\n    fingerprintjs3|\n    gemius|\n    google-analytics-ga|\n    google-analytics|\n    google-ima3|\n    googlesyndication-adsbygoogle|\n    googletagservices-gpt|\n    matomo|\n    metrika-yandex-tag|\n    metrika-yandex-watch|\n    naver-wcslog|\n    noeval|\n    pardot-1\\.0|\n    prebid-ads|\n    prebid|\n    prevent-bab|\n    prevent-bab2|\n    prevent-fab-3\\.2\\.0|\n    prevent-popads-net|\n    scorecardresearch-beacon|\n    set-popads-dummy|\n    click2load\\.html|\n  )?$"
        }, {
          name: "redirect-rule",
          aliases: null,
          description: "This is basically an alias to `$redirect`\nsince it has the same \"redirection\" values and the logic is almost similar.\nThe difference is that `$redirect-rule` is applied only in the case\nwhen the target request is blocked by a different basic rule.",
          docs: "https://adguard.app/kb/general/ad-filtering/create-own-filters/#redirect-rule-modifier",
          versionAdded: null,
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          conflicts: ["domain", "to", "third-party", "popup", "match-case", "header", "first-party", "document", "image", "stylesheet", "script", "object", "font", "media", "subdocument", "ping", "xmlhttprequest", "websocket", "other", "webrtc", "important", "badfilter"],
          inverseConflicts: true,
          assignable: true,
          negatable: false,
          blockOnly: false,
          exceptionOnly: false,
          valueOptional: true,
          valueFormat: "(?x)\n  ^(\n    1x1-transparent\\.gif|\n    2x2-transparent\\.png|\n    3x2-transparent\\.png|\n    32x32-transparent\\.png|\n    noopframe|\n    noopcss|\n    noopjs|\n    noopjson|\n    nooptext|\n    empty|\n    noopvmap-1\\.0|\n    noopvast-2\\.0|\n    noopvast-3\\.0|\n    noopvast-4\\.0|\n    noopmp3-0\\.1s|\n    noopmp4-1s|\n    amazon-apstag|\n    ati-smarttag|\n    didomi-loader|\n    fingerprintjs2|\n    fingerprintjs3|\n    gemius|\n    google-analytics-ga|\n    google-analytics|\n    google-ima3|\n    googlesyndication-adsbygoogle|\n    googletagservices-gpt|\n    matomo|\n    metrika-yandex-tag|\n    metrika-yandex-watch|\n    naver-wcslog|\n    noeval|\n    pardot-1\\.0|\n    prebid-ads|\n    prebid|\n    prevent-bab|\n    prevent-bab2|\n    prevent-fab-3\\.2\\.0|\n    prevent-popads-net|\n    scorecardresearch-beacon|\n    set-popads-dummy|\n    click2load\\.html|\n  )?$"
        }, {
          name: "redirect-rule",
          aliases: null,
          description: "This is basically an alias to `$redirect`\nsince it has the same \"redirection\" values and the logic is almost similar.\nThe difference is that `$redirect-rule` is applied only in the case\nwhen the target request is blocked by a different basic rule.",
          docs: "https://github.com/gorhill/uBlock/wiki/Static-filter-syntax#redirect-rule",
          versionAdded: null,
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          conflicts: ["domain", "to", "third-party", "popup", "match-case", "header", "first-party", "document", "image", "stylesheet", "script", "object", "font", "media", "subdocument", "ping", "xmlhttprequest", "websocket", "other", "webrtc", "important", "badfilter"],
          inverseConflicts: true,
          assignable: true,
          negatable: false,
          blockOnly: false,
          exceptionOnly: false,
          valueOptional: false,
          valueFormat: "(?x)\n  ^(\n    1x1\\.gif|\n    2x2\\.png|\n    3x2\\.png|\n    32x32\\.png|\n    noop\\.css|\n    noop\\.html|\n    noopframe|\n    noop\\.js|\n    noop\\.txt|\n    noop-0\\.1s\\.mp3|\n    noop-0\\.5s\\.mp3|\n    noop-1s\\.mp4|\n    none|\n    click2load\\.html|\n    addthis_widget\\.js|\n    amazon_ads\\.js|\n    amazon_apstag\\.js|\n    monkeybroker\\.js|\n    doubleclick_instream_ad_status|\n    google-analytics_ga\\.js|\n    google-analytics_analytics\\.js|\n    google-analytics_inpage_linkid\\.js|\n    google-analytics_cx_api\\.js|\n    google-ima\\.js|\n    googletagservices_gpt\\.js|\n    googletagmanager_gtm\\.js|\n    googlesyndication_adsbygoogle\\.js|\n    scorecardresearch_beacon\\.js|\n    outbrain-widget\\.js|\n    hd-main\\.js\n  )\n  (:[0-9]+)?$"
        }],
        map: {
          "1": 0,
          "2": 0,
          "4": 0,
          "8": 1,
          "16": 1,
          "32": 1,
          "64": 1,
          "1024": 2,
          "2048": 2,
          "4096": 2,
          "8192": 2
        }
      }, {
        shared: [{
          name: "redirect",
          aliases: null,
          description: "Used to redirect web requests to a local \"resource\".",
          docs: "https://adguard.app/kb/general/ad-filtering/create-own-filters/#redirect-modifier",
          versionAdded: null,
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          conflicts: null,
          inverseConflicts: false,
          assignable: true,
          negatable: false,
          blockOnly: false,
          exceptionOnly: false,
          valueOptional: true,
          valueFormat: "(?x)\n  ^(\n    1x1-transparent\\.gif|\n    2x2-transparent\\.png|\n    3x2-transparent\\.png|\n    32x32-transparent\\.png|\n    noopframe|\n    noopcss|\n    noopjs|\n    noopjson|\n    nooptext|\n    empty|\n    noopvmap-1\\.0|\n    noopvast-2\\.0|\n    noopvast-3\\.0|\n    noopvast-4\\.0|\n    noopmp3-0\\.1s|\n    noopmp4-1s|\n    amazon-apstag|\n    ati-smarttag|\n    didomi-loader|\n    fingerprintjs2|\n    fingerprintjs3|\n    gemius|\n    google-analytics-ga|\n    google-analytics|\n    googletagmanager-gtm|\n    google-ima3|\n    googlesyndication-adsbygoogle|\n    googletagservices-gpt|\n    matomo|\n    metrika-yandex-tag|\n    metrika-yandex-watch|\n    naver-wcslog|\n    noeval|\n    pardot-1\\.0|\n    prebid-ads|\n    prebid|\n    prevent-bab|\n    prevent-bab2|\n    prevent-fab-3\\.2\\.0|\n    prevent-popads-net|\n    scorecardresearch-beacon|\n    set-popads-dummy|\n    click2load\\.html\n  )?$"
        }, {
          name: "redirect",
          aliases: null,
          description: "Used to redirect web requests to a local \"resource\".",
          docs: "https://adguard.app/kb/general/ad-filtering/create-own-filters/#redirect-modifier",
          versionAdded: null,
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          conflicts: null,
          inverseConflicts: false,
          assignable: true,
          negatable: false,
          blockOnly: false,
          exceptionOnly: false,
          valueOptional: true,
          valueFormat: "(?x)\n  ^(\n    1x1-transparent\\.gif|\n    2x2-transparent\\.png|\n    3x2-transparent\\.png|\n    32x32-transparent\\.png|\n    noopframe|\n    noopcss|\n    noopjs|\n    noopjson|\n    nooptext|\n    empty|\n    noopvmap-1\\.0|\n    noopvast-2\\.0|\n    noopvast-3\\.0|\n    noopvast-4\\.0|\n    noopmp3-0\\.1s|\n    noopmp4-1s|\n    amazon-apstag|\n    ati-smarttag|\n    didomi-loader|\n    fingerprintjs2|\n    fingerprintjs3|\n    gemius|\n    google-analytics-ga|\n    google-analytics|\n    googletagmanager-gtm|\n    google-ima3|\n    googlesyndication-adsbygoogle|\n    googletagservices-gpt|\n    matomo|\n    metrika-yandex-tag|\n    metrika-yandex-watch|\n    naver-wcslog|\n    noeval|\n    pardot-1\\.0|\n    prebid-ads|\n    prebid|\n    prevent-bab|\n    prevent-bab2|\n    prevent-fab-3\\.2\\.0|\n    prevent-popads-net|\n    scorecardresearch-beacon|\n    set-popads-dummy|\n    click2load\\.html\n  )?$"
        }, {
          name: "redirect",
          aliases: null,
          description: "Used to redirect web requests to a local \"resource\".",
          docs: "https://github.com/gorhill/uBlock/wiki/Static-filter-syntax#redirect",
          versionAdded: null,
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          conflicts: null,
          inverseConflicts: false,
          assignable: true,
          negatable: false,
          blockOnly: false,
          exceptionOnly: false,
          valueOptional: true,
          valueFormat: "(?x)\n  ^(\n    1x1\\.gif|\n    2x2\\.png|\n    3x2\\.png|\n    32x32\\.png|\n    noop\\.css|\n    noop\\.html|\n    noopframe|\n    noop\\.js|\n    noop\\.txt|\n    noop-0\\.1s\\.mp3|\n    noop-0\\.5s\\.mp3|\n    noop-1s\\.mp4|\n    none|\n    click2load\\.html|\n    addthis_widget\\.js|\n    amazon_ads\\.js|\n    amazon_apstag\\.js|\n    monkeybroker\\.js|\n    doubleclick_instream_ad_status|\n    google-analytics_ga\\.js|\n    google-analytics_analytics\\.js|\n    google-analytics_inpage_linkid\\.js|\n    google-analytics_cx_api\\.js|\n    google-ima\\.js|\n    googletagservices_gpt\\.js|\n    googletagmanager_gtm\\.js|\n    googlesyndication_adsbygoogle\\.js|\n    scorecardresearch_beacon\\.js|\n    outbrain-widget\\.js|\n    hd-main\\.js\n  )\n  (:[0-9]+)?$"
        }, {
          name: "rewrite",
          aliases: null,
          description: "The `rewrite=` option allows the rewriting of URLs (or redirecting requests) to an internal\nresource in order to deactivate it without causing an error. Indicate the internal resource\nby name and prefix `abp-resource:` in order to be recognized. For example\n`$rewrite=abp-resource:blank-js` sends an empty JavaScript.",
          docs: "https://help.adblockplus.org/hc/en-us/articles/360062733293#rewrite",
          versionAdded: null,
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          conflicts: null,
          inverseConflicts: false,
          assignable: true,
          negatable: false,
          blockOnly: false,
          exceptionOnly: false,
          valueOptional: false,
          valueFormat: "(?x)\n  # ABP resources always starts with the `abp-resource:` prefix\n  ^abp-resource:\n  # Possible resource names\n  (\n    blank-text|\n    blank-css|\n    blank-js|\n    blank-html|\n    blank-mp3|\n    1x1-transparent-gif|\n    2x2-transparent-png|\n    3x2-transparent-png|\n    32x32-transparent-png\n  )$"
        }],
        map: {
          "1": 0,
          "2": 0,
          "4": 0,
          "8": 1,
          "16": 1,
          "32": 1,
          "64": 1,
          "1024": 2,
          "2048": 2,
          "4096": 2,
          "8192": 2,
          "16384": 3,
          "32768": 3,
          "65536": 3,
          "131072": 3
        }
      }, {
        shared: [{
          name: "referrerpolicy",
          aliases: null,
          description: "This modifier allows overriding of a page's referrer policy.",
          docs: "https://adguard.app/kb/general/ad-filtering/create-own-filters/#referrerpolicy-modifier",
          versionAdded: null,
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          conflicts: ["document", "subdocument"],
          inverseConflicts: true,
          assignable: true,
          negatable: false,
          blockOnly: false,
          exceptionOnly: false,
          valueOptional: true,
          valueFormat: "referrerpolicy_value"
        }],
        map: {
          "1": 0,
          "2": 0,
          "4": 0
        }
      }, {
        shared: [{
          name: "removeheader",
          aliases: null,
          description: "Rules with the `$removeheader` modifier are intended to remove headers from HTTP requests and responses.",
          docs: "https://adguard.app/kb/general/ad-filtering/create-own-filters/#removeheader-modifier",
          versionAdded: null,
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          conflicts: ["domain", "third-party", "first-party", "app", "important", "match-case", "document", "image", "stylesheet", "script", "object", "font", "media", "subdocument", "ping", "xmlhttpreqeust", "websocket", "other", "webrtc"],
          inverseConflicts: true,
          assignable: true,
          negatable: false,
          blockOnly: false,
          exceptionOnly: false,
          valueOptional: true,
          valueFormat: "(?xi)\n  ^\n    # Value may start with \"request:\"\n    (request:)?\n\n    # Forbidden header names\n    (?!\n      (\n        access-control-allow-origin|\n        access-control-allow-credentials|\n        access-control-allow-headers|\n        access-control-allow-methods|\n        access-control-expose-headers|\n        access-control-max-age|\n        access-control-request-headers|\n        access-control-request-method|\n        origin|\n        timing-allow-origin|\n        allow|\n        cross-origin-embedder-policy|\n        cross-origin-opener-policy|\n        cross-origin-resource-policy|\n        content-security-policy|\n        content-security-policy-report-only|\n        expect-ct|\n        feature-policy|\n        origin-isolation|\n        strict-transport-security|\n        upgrade-insecure-requests|\n        x-content-type-options|\n        x-download-options|\n        x-frame-options|\n        x-permitted-cross-domain-policies|\n        x-powered-by|\n        x-xss-protection|\n        public-key-pins|\n        public-key-pins-report-only|\n        sec-websocket-key|\n        sec-websocket-extensions|\n        sec-websocket-accept|\n        sec-websocket-protocol|\n        sec-websocket-version|\n        p3p|\n        sec-fetch-mode|\n        sec-fetch-dest|\n        sec-fetch-site|\n        sec-fetch-user|\n        referrer-policy|\n        content-type|\n        content-length|\n        accept|\n        accept-encoding|\n        host|\n        connection|\n        transfer-encoding|\n        upgrade\n      )\n    $)\n\n    # Any other header name is allowed, if it matches the following regex\n    [A-z0-9-]+\n  $"
        }, {
          name: "removeheader",
          aliases: null,
          description: "Rules with the `$removeheader` modifier are intended to remove headers from HTTP requests and responses.",
          docs: "https://adguard.app/kb/general/ad-filtering/create-own-filters/#removeheader-modifier",
          versionAdded: null,
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          conflicts: ["domain", "third-party", "first-party", "app", "important", "match-case", "document", "image", "stylesheet", "script", "object", "font", "media", "subdocument", "ping", "xmlhttpreqeust", "websocket", "other", "webrtc"],
          inverseConflicts: true,
          assignable: true,
          negatable: false,
          blockOnly: false,
          exceptionOnly: false,
          valueOptional: true,
          valueFormat: "(?xi)\n  ^\n    # Value may start with \"request:\"\n    (request:)?\n\n    # Forbidden header names\n    (?!\n      (\n        access-control-allow-origin|\n        access-control-allow-credentials|\n        access-control-allow-headers|\n        access-control-allow-methods|\n        access-control-expose-headers|\n        access-control-max-age|\n        access-control-request-headers|\n        access-control-request-method|\n        origin|\n        timing-allow-origin|\n        allow|\n        cross-origin-embedder-policy|\n        cross-origin-opener-policy|\n        cross-origin-resource-policy|\n        content-security-policy|\n        content-security-policy-report-only|\n        expect-ct|\n        feature-policy|\n        origin-isolation|\n        strict-transport-security|\n        upgrade-insecure-requests|\n        x-content-type-options|\n        x-download-options|\n        x-frame-options|\n        x-permitted-cross-domain-policies|\n        x-powered-by|\n        x-xss-protection|\n        public-key-pins|\n        public-key-pins-report-only|\n        sec-websocket-key|\n        sec-websocket-extensions|\n        sec-websocket-accept|\n        sec-websocket-protocol|\n        sec-websocket-version|\n        p3p|\n        sec-fetch-mode|\n        sec-fetch-dest|\n        sec-fetch-site|\n        sec-fetch-user|\n        referrer-policy|\n        content-type|\n        content-length|\n        accept|\n        accept-encoding|\n        host|\n        connection|\n        transfer-encoding|\n        upgrade\n      )\n    $)\n\n    # Any other header name is allowed, if it matches the following regex\n    [A-z0-9-]+\n  $"
        }],
        map: {
          "1": 0,
          "2": 0,
          "4": 0,
          "8": 1,
          "16": 1,
          "32": 1,
          "64": 1
        }
      }, {
        shared: [{
          name: "removeparam",
          aliases: null,
          description: "Rules with the `$removeparam` modifier are intended to strip query parameters from requests' URLs.",
          docs: "https://adguard.app/kb/general/ad-filtering/create-own-filters/#removeparam-modifier",
          versionAdded: null,
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          conflicts: null,
          inverseConflicts: false,
          assignable: true,
          negatable: false,
          blockOnly: false,
          exceptionOnly: false,
          valueOptional: true,
          valueFormat: "(?xi)\n  (\n    # string pattern\n    \\w+\n    # or regexp pattern\n    |\n    \\/.+\\/\n      # flags\n      ([gimuy]+)?\n  )"
        }, {
          name: "removeparam",
          aliases: null,
          description: "Rules with the `$removeparam` modifier are intended to strip query parameters from requests' URLs.",
          docs: "https://adguard.app/kb/general/ad-filtering/create-own-filters/#removeparam-modifier",
          versionAdded: null,
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          conflicts: null,
          inverseConflicts: false,
          assignable: true,
          negatable: false,
          blockOnly: false,
          exceptionOnly: false,
          valueOptional: true,
          valueFormat: "(?xi)\n  (\n    # string pattern\n    \\w+\n    # or regexp pattern\n    |\n    \\/.+\\/\n      # flags\n      ([gimuy]+)?\n  )"
        }, {
          name: "removeparam",
          aliases: null,
          description: "Rules with the `$removeparam` modifier are intended to strip query parameters from requests' URLs.",
          docs: "https://github.com/gorhill/uBlock/wiki/Static-filter-syntax#removeparam",
          versionAdded: null,
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          conflicts: null,
          inverseConflicts: false,
          assignable: true,
          negatable: false,
          blockOnly: false,
          exceptionOnly: false,
          valueOptional: false,
          valueFormat: "(?xi)\n  (\n    # string pattern\n    \\w+\n    # or regexp pattern\n    |\n    \\/.+\\/\n      # flags\n      ([gimuy]+)?\n  )"
        }],
        map: {
          "1": 0,
          "2": 0,
          "4": 0,
          "8": 1,
          "16": 1,
          "32": 1,
          "64": 1,
          "1024": 2,
          "2048": 2,
          "4096": 2,
          "8192": 2
        }
      }, {
        shared: [{
          name: "replace",
          aliases: null,
          description: "This modifier completely changes the rule behavior.\nIf it is applied, the rule will not block the request. The response is going to be modified instead.",
          docs: "https://adguard.app/kb/general/ad-filtering/create-own-filters/#replace-modifier",
          versionAdded: null,
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          conflicts: ["app", "domain", "document", "subdocument", "script", "stylesheet", "other", "xmlhttprequest", "first-party", "third-party", "important", "badfilter"],
          inverseConflicts: true,
          assignable: true,
          negatable: false,
          blockOnly: false,
          exceptionOnly: false,
          valueOptional: false,
          valueFormat: "(?xi)\n  ^\n    \\/\n      # the regexp to match by\n      (.+)\n    # separator\n    \\/\n      # replacement\n      (.+)?\n    \\/\n      # flags\n      ([gimuy]*)?\n  $"
        }, {
          name: "replace",
          aliases: null,
          description: "This modifier completely changes the rule behavior.\nIf it is applied, the rule will not block the request. The response is going to be modified instead.",
          docs: "https://adguard.app/kb/general/ad-filtering/create-own-filters/#replace-modifier",
          versionAdded: null,
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          conflicts: ["app", "domain", "document", "subdocument", "script", "stylesheet", "other", "xmlhttprequest", "first-party", "third-party", "important", "badfilter"],
          inverseConflicts: true,
          assignable: true,
          negatable: false,
          blockOnly: false,
          exceptionOnly: false,
          valueOptional: false,
          valueFormat: "(?xi)\n  ^\n    \\/\n      # the regexp to match by\n      (.+)\n    # separator\n    \\/\n      # replacement\n      (.+)?\n    \\/\n      # flags\n      ([gimuy]*)?\n  $"
        }, {
          name: "replace",
          aliases: null,
          description: "This modifier completely changes the rule behavior.\nIf it is applied, the rule will not block the request. The response is going to be modified instead.",
          docs: "https://github.com/gorhill/uBlock/wiki/Static-filter-syntax#replace",
          versionAdded: null,
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          conflicts: ["app", "domain", "document", "subdocument", "script", "stylesheet", "other", "xmlhttprequest", "first-party", "third-party", "important", "badfilter"],
          inverseConflicts: true,
          assignable: true,
          negatable: false,
          blockOnly: false,
          exceptionOnly: false,
          valueOptional: false,
          valueFormat: "(?xi)\n  ^\n    \\/\n      # the regexp to match by\n      (.+)\n    # separator\n    \\/\n      # replacement\n      (.+)?\n    \\/\n      # flags\n      ([gimuy]*)?\n  $"
        }],
        map: {
          "1": 0,
          "2": 0,
          "4": 0,
          "64": 1,
          "8192": 2
        }
      }, {
        shared: [{
          name: "script",
          aliases: null,
          description: "The rule corresponds to script requests, e.g. javascript, vbscript.",
          docs: "https://adguard.app/kb/general/ad-filtering/create-own-filters/#script-modifier",
          versionAdded: null,
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          conflicts: null,
          inverseConflicts: false,
          assignable: false,
          negatable: true,
          blockOnly: false,
          exceptionOnly: false,
          valueOptional: false,
          valueFormat: null
        }, {
          name: "script",
          aliases: null,
          description: "The rule corresponds to script requests, e.g. javascript, vbscript.",
          docs: "https://help.adblockplus.org/hc/en-us/articles/360062733293#options",
          versionAdded: null,
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          conflicts: null,
          inverseConflicts: false,
          assignable: false,
          negatable: true,
          blockOnly: false,
          exceptionOnly: false,
          valueOptional: false,
          valueFormat: null
        }, {
          name: "script",
          aliases: null,
          description: "The rule corresponds to script requests, e.g. javascript, vbscript.",
          docs: "https://help.adblockplus.org/hc/en-us/articles/360062733293-How-to-write-filters#type-options",
          versionAdded: null,
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          conflicts: null,
          inverseConflicts: false,
          assignable: false,
          negatable: true,
          blockOnly: false,
          exceptionOnly: false,
          valueOptional: false,
          valueFormat: null
        }],
        map: {
          "1": 0,
          "2": 0,
          "4": 0,
          "8": 0,
          "16": 0,
          "32": 0,
          "64": 0,
          "128": 0,
          "256": 0,
          "512": 0,
          "1024": 1,
          "2048": 1,
          "4096": 1,
          "8192": 1,
          "16384": 2,
          "32768": 2,
          "65536": 2,
          "131072": 2
        }
      }, {
        shared: [{
          name: "specifichide",
          aliases: ["shide"],
          description: "Disables all specific element hiding and CSS rules, but not general ones.\nHas an opposite effect to `$generichide`.",
          docs: "https://adguard.app/kb/general/ad-filtering/create-own-filters/#specifichide-modifier",
          versionAdded: null,
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          conflicts: ["domain", "genericblock", "urlblock", "extension", "jsinject", "content", "xmlhttprequest", "badfilter"],
          inverseConflicts: true,
          assignable: false,
          negatable: false,
          blockOnly: false,
          exceptionOnly: true,
          valueOptional: false,
          valueFormat: null
        }, {
          name: "specifichide",
          aliases: ["shide"],
          description: "Disables all specific element hiding and CSS rules, but not general ones.\nHas an opposite effect to `$generichide`.",
          docs: "https://github.com/gorhill/uBlock/wiki/Static-filter-syntax#specifichide",
          versionAdded: null,
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          conflicts: ["domain", "badfilter"],
          inverseConflicts: true,
          assignable: false,
          negatable: false,
          blockOnly: false,
          exceptionOnly: true,
          valueOptional: false,
          valueFormat: null
        }],
        map: {
          "1": 0,
          "2": 0,
          "4": 0,
          "8": 0,
          "16": 0,
          "32": 0,
          "64": 0,
          "128": 0,
          "256": 0,
          "512": 0,
          "1024": 1,
          "2048": 1,
          "4096": 1,
          "8192": 1
        }
      }, {
        shared: [{
          name: "stealth",
          aliases: null,
          description: "Disables the Stealth Mode module for all corresponding pages and requests.",
          docs: "https://adguard.app/kb/general/ad-filtering/create-own-filters/#stealth-modifier",
          versionAdded: null,
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          conflicts: null,
          inverseConflicts: false,
          assignable: true,
          negatable: false,
          blockOnly: false,
          exceptionOnly: true,
          valueOptional: true,
          valueFormat: "pipe_separated_stealth_options"
        }, {
          name: "stealth",
          aliases: null,
          description: "Disables the Stealth Mode module for all corresponding pages and requests.",
          docs: "https://adguard.app/kb/general/ad-filtering/create-own-filters/#stealth-modifier",
          versionAdded: null,
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          conflicts: null,
          inverseConflicts: false,
          assignable: true,
          negatable: false,
          blockOnly: false,
          exceptionOnly: true,
          valueOptional: true,
          valueFormat: "pipe_separated_stealth_options"
        }, {
          name: "stealth",
          aliases: null,
          description: "Disables the Stealth Mode module for all corresponding pages and requests.",
          docs: "https://adguard.app/kb/general/ad-filtering/create-own-filters/#stealth-modifier",
          versionAdded: null,
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          conflicts: null,
          inverseConflicts: false,
          assignable: true,
          negatable: false,
          blockOnly: false,
          exceptionOnly: true,
          valueOptional: true,
          valueFormat: "pipe_separated_stealth_options"
        }, {
          name: "stealth",
          aliases: null,
          description: "Disables the Stealth Mode module for all corresponding pages and requests.",
          docs: "https://adguard.app/kb/general/ad-filtering/create-own-filters/#stealth-modifier",
          versionAdded: null,
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          conflicts: null,
          inverseConflicts: false,
          assignable: true,
          negatable: false,
          blockOnly: false,
          exceptionOnly: true,
          valueOptional: true,
          valueFormat: "pipe_separated_stealth_options"
        }, {
          name: "stealth",
          aliases: null,
          description: "Disables the Stealth Mode module for all corresponding pages and requests.",
          docs: "https://adguard.app/kb/general/ad-filtering/create-own-filters/#stealth-modifier",
          versionAdded: null,
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          conflicts: null,
          inverseConflicts: false,
          assignable: true,
          negatable: false,
          blockOnly: false,
          exceptionOnly: true,
          valueOptional: true,
          valueFormat: "pipe_separated_stealth_options"
        }],
        map: {
          "1": 0,
          "2": 0,
          "4": 0,
          "8": 1,
          "16": 2,
          "32": 3,
          "64": 4
        }
      }, {
        shared: [{
          name: "strict1p",
          aliases: null,
          description: "This new `strict1p` option can check for strict partyness.\nFor example, a network request qualifies as 1st-party if both the context and the request share the same hostname.",
          docs: "https://github.com/gorhill/uBlock/wiki/Static-filter-syntax#strict1p",
          versionAdded: null,
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          conflicts: null,
          inverseConflicts: false,
          assignable: false,
          negatable: true,
          blockOnly: false,
          exceptionOnly: false,
          valueOptional: false,
          valueFormat: null
        }],
        map: {
          "1024": 0,
          "2048": 0,
          "4096": 0,
          "8192": 0
        }
      }, {
        shared: [{
          name: "strict3p",
          aliases: null,
          description: "This new `strict3p` option can check for strict partyness.\nFor example, a network request qualifies as 3rd-party if the context and the request hostnames are different.",
          docs: "https://github.com/gorhill/uBlock/wiki/Static-filter-syntax#strict3p",
          versionAdded: null,
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          conflicts: null,
          inverseConflicts: false,
          assignable: false,
          negatable: true,
          blockOnly: false,
          exceptionOnly: false,
          valueOptional: false,
          valueFormat: null
        }],
        map: {
          "1024": 0,
          "2048": 0,
          "4096": 0,
          "8192": 0
        }
      }, {
        shared: [{
          name: "stylesheet",
          aliases: null,
          description: "The rule corresponds to CSS files requests.",
          docs: "https://adguard.app/kb/general/ad-filtering/create-own-filters/#stylesheet-modifier",
          versionAdded: null,
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          conflicts: null,
          inverseConflicts: false,
          assignable: false,
          negatable: true,
          blockOnly: false,
          exceptionOnly: false,
          valueOptional: false,
          valueFormat: null
        }, {
          name: "stylesheet",
          aliases: ["css"],
          description: "The rule corresponds to CSS files requests.",
          docs: "https://github.com/gorhill/uBlock/wiki/Static-filter-syntax#css",
          versionAdded: null,
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          conflicts: null,
          inverseConflicts: false,
          assignable: false,
          negatable: true,
          blockOnly: false,
          exceptionOnly: false,
          valueOptional: false,
          valueFormat: null
        }, {
          name: "stylesheet",
          aliases: null,
          description: "The rule corresponds to CSS files requests.",
          docs: "https://help.adblockplus.org/hc/en-us/articles/360062733293-How-to-write-filters#type-options",
          versionAdded: null,
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          conflicts: null,
          inverseConflicts: false,
          assignable: false,
          negatable: true,
          blockOnly: false,
          exceptionOnly: false,
          valueOptional: false,
          valueFormat: null
        }],
        map: {
          "1": 0,
          "2": 0,
          "4": 0,
          "8": 0,
          "16": 0,
          "32": 0,
          "64": 0,
          "128": 0,
          "256": 0,
          "512": 0,
          "1024": 1,
          "2048": 1,
          "4096": 1,
          "8192": 1,
          "16384": 2,
          "32768": 2,
          "65536": 2,
          "131072": 2
        }
      }, {
        shared: [{
          name: "subdocument",
          aliases: null,
          description: "The rule corresponds to requests for built-in pages — HTML tags frame and iframe.",
          docs: "https://adguard.app/kb/general/ad-filtering/create-own-filters/#subdocument-modifier",
          versionAdded: null,
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          conflicts: null,
          inverseConflicts: false,
          assignable: false,
          negatable: true,
          blockOnly: false,
          exceptionOnly: false,
          valueOptional: false,
          valueFormat: null
        }, {
          name: "subdocument",
          aliases: ["frame"],
          description: "The rule corresponds to requests for built-in pages — HTML tags frame and iframe.",
          docs: "https://github.com/gorhill/uBlock/wiki/Static-filter-syntax#frame",
          versionAdded: null,
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          conflicts: null,
          inverseConflicts: false,
          assignable: false,
          negatable: true,
          blockOnly: false,
          exceptionOnly: false,
          valueOptional: false,
          valueFormat: null
        }, {
          name: "subdocument",
          aliases: null,
          description: "The rule corresponds to requests for built-in pages — HTML tags frame and iframe.",
          docs: "https://help.adblockplus.org/hc/en-us/articles/360062733293-How-to-write-filters#type-options",
          versionAdded: null,
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          conflicts: null,
          inverseConflicts: false,
          assignable: false,
          negatable: true,
          blockOnly: false,
          exceptionOnly: false,
          valueOptional: false,
          valueFormat: null
        }],
        map: {
          "1": 0,
          "2": 0,
          "4": 0,
          "8": 0,
          "16": 0,
          "32": 0,
          "64": 0,
          "128": 0,
          "256": 0,
          "512": 0,
          "1024": 1,
          "2048": 1,
          "4096": 1,
          "8192": 1,
          "16384": 2,
          "32768": 2,
          "65536": 2,
          "131072": 2
        }
      }, {
        shared: [{
          name: "third-party",
          aliases: ["3p"],
          description: "A restriction of third-party and own requests.\nA third-party request is a request from a different domain.\nFor example, a request to `example.org` from `domain.com` is a third-party request.",
          docs: "https://adguard.app/kb/general/ad-filtering/create-own-filters/#third-party-modifier",
          versionAdded: null,
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          conflicts: null,
          inverseConflicts: false,
          assignable: false,
          negatable: true,
          blockOnly: false,
          exceptionOnly: false,
          valueOptional: false,
          valueFormat: null
        }, {
          name: "3p",
          aliases: ["third-party"],
          description: "A restriction of third-party and own requests.\nA third-party request is a request from a different domain.\nFor example, a request to `example.org` from `domain.com` is a third-party request.",
          docs: "https://github.com/gorhill/uBlock/wiki/Static-filter-syntax#3p",
          versionAdded: null,
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          conflicts: null,
          inverseConflicts: false,
          assignable: false,
          negatable: true,
          blockOnly: false,
          exceptionOnly: false,
          valueOptional: false,
          valueFormat: null
        }, {
          name: "third-party",
          aliases: null,
          description: "A restriction of third-party and own requests.\nA third-party request is a request from a different domain.\nFor example, a request to `example.org` from `domain.com` is a third-party request.",
          docs: "https://help.adblockplus.org/hc/en-us/articles/360062733293#party-requests",
          versionAdded: null,
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          conflicts: null,
          inverseConflicts: false,
          assignable: false,
          negatable: true,
          blockOnly: false,
          exceptionOnly: false,
          valueOptional: false,
          valueFormat: null
        }],
        map: {
          "1": 0,
          "2": 0,
          "4": 0,
          "8": 0,
          "16": 0,
          "32": 0,
          "64": 0,
          "128": 0,
          "256": 0,
          "512": 0,
          "1024": 1,
          "2048": 1,
          "4096": 1,
          "8192": 1,
          "16384": 2,
          "32768": 2,
          "65536": 2,
          "131072": 2
        }
      }, {
        shared: [{
          name: "to",
          aliases: null,
          description: "`$to` limits the rule scope to requests made to the specified domains and their subdomains.\nTo add multiple domains to one rule, use the `|` character as a separator.",
          docs: "https://adguard.com/kb/general/ad-filtering/create-own-filters/#to-modifier",
          versionAdded: null,
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          conflicts: ["denyallow"],
          inverseConflicts: false,
          assignable: true,
          negatable: false,
          blockOnly: false,
          exceptionOnly: false,
          valueOptional: false,
          valueFormat: "pipe_separated_domains"
        }, {
          name: "to",
          aliases: null,
          description: "`$to` limits the rule scope to requests made to the specified domains and their subdomains.\nTo add multiple domains to one rule, use the `|` character as a separator.",
          docs: "https://adguard.com/kb/general/ad-filtering/create-own-filters/#to-modifier",
          versionAdded: null,
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          conflicts: ["denyallow"],
          inverseConflicts: false,
          assignable: true,
          negatable: false,
          blockOnly: false,
          exceptionOnly: false,
          valueOptional: false,
          valueFormat: "pipe_separated_domains"
        }, {
          name: "to",
          aliases: null,
          description: "The main motivation of this option is\nto give static network filtering engine an equivalent of DNR's `requestDomains` and `excludedRequestDomains`.",
          docs: "https://github.com/gorhill/uBlock/wiki/Static-filter-syntax#to",
          versionAdded: null,
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          conflicts: ["denyallow"],
          inverseConflicts: false,
          assignable: true,
          negatable: false,
          blockOnly: false,
          exceptionOnly: false,
          valueOptional: false,
          valueFormat: "pipe_separated_domains"
        }],
        map: {
          "1": 0,
          "2": 0,
          "4": 0,
          "8": 1,
          "16": 1,
          "32": 1,
          "64": 1,
          "1024": 2,
          "2048": 2,
          "4096": 2,
          "8192": 2
        }
      }, {
        shared: [{
          name: "urlblock",
          aliases: null,
          description: "Disables blocking of all requests sent from the pages matching the rule.",
          docs: "https://adguard.app/kb/general/ad-filtering/create-own-filters/#urlblock-modifier",
          versionAdded: null,
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          conflicts: ["domain", "specifichide", "generichide", "elemhide", "extension", "jsinject", "content", "badfilter"],
          inverseConflicts: true,
          assignable: false,
          negatable: false,
          blockOnly: false,
          exceptionOnly: true,
          valueOptional: false,
          valueFormat: null
        }],
        map: {
          "1": 0,
          "2": 0,
          "4": 0,
          "8": 0,
          "16": 0,
          "32": 0,
          "64": 0,
          "128": 0,
          "256": 0,
          "512": 0
        }
      }, {
        shared: [{
          name: "webrtc",
          aliases: null,
          description: "The rule applies only to WebRTC connections.",
          docs: "https://adguard.app/kb/general/ad-filtering/create-own-filters/#webrtc-modifier",
          versionAdded: null,
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: true,
          removalMessage: "This modifier is removed and is no longer supported.\nRules with it are considered as invalid. If you need to suppress WebRTC, consider using\nthe [nowebrtc scriptlet](https://github.com/AdguardTeam/Scriptlets/blob/master/wiki/about-scriptlets.md#nowebrtc).",
          conflicts: null,
          inverseConflicts: false,
          assignable: false,
          negatable: true,
          blockOnly: false,
          exceptionOnly: false,
          valueOptional: false,
          valueFormat: null
        }, {
          name: "webrtc",
          aliases: null,
          description: "The rule applies only to WebRTC connections.",
          docs: "https://github.com/gorhill/uBlock/wiki/Static-filter-syntax",
          versionAdded: null,
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: true,
          removalMessage: "This modifier is removed and is no longer supported.\nIf you need to suppress WebRTC, consider using\nthe [nowebrtc scriptlet](https://github.com/gorhill/uBlock/wiki/Resources-Library#nowebrtcjs-).",
          conflicts: null,
          inverseConflicts: false,
          assignable: false,
          negatable: true,
          blockOnly: false,
          exceptionOnly: false,
          valueOptional: false,
          valueFormat: null
        }, {
          name: "webrtc",
          aliases: null,
          description: "The rule applies only to WebRTC connections.",
          docs: "https://help.adblockplus.org/hc/en-us/articles/360062733293-How-to-write-filters#type-options",
          versionAdded: "1.13.3",
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          conflicts: null,
          inverseConflicts: false,
          assignable: false,
          negatable: true,
          blockOnly: false,
          exceptionOnly: false,
          valueOptional: false,
          valueFormat: null
        }],
        map: {
          "1": 0,
          "2": 0,
          "4": 0,
          "8": 0,
          "16": 0,
          "32": 0,
          "64": 0,
          "128": 0,
          "256": 0,
          "512": 0,
          "1024": 1,
          "2048": 1,
          "4096": 1,
          "8192": 1,
          "16384": 2,
          "32768": 2,
          "65536": 2,
          "131072": 2
        }
      }, {
        shared: [{
          name: "websocket",
          aliases: null,
          description: "The rule applies only to WebSocket connections.",
          docs: "https://adguard.app/kb/general/ad-filtering/create-own-filters/#websocket-modifier",
          versionAdded: null,
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          conflicts: null,
          inverseConflicts: false,
          assignable: false,
          negatable: true,
          blockOnly: false,
          exceptionOnly: false,
          valueOptional: false,
          valueFormat: null
        }, {
          name: "websocket",
          aliases: null,
          description: "The rule applies only to WebSocket connections.",
          docs: "https://adguard.app/kb/general/ad-filtering/create-own-filters/#websocket-modifier",
          versionAdded: null,
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          conflicts: null,
          inverseConflicts: false,
          assignable: false,
          negatable: true,
          blockOnly: false,
          exceptionOnly: false,
          valueOptional: false,
          valueFormat: null
        }, {
          name: "websocket",
          aliases: null,
          description: "The rule applies only to WebSocket connections.",
          docs: "https://adguard.app/kb/general/ad-filtering/create-own-filters/#websocket-modifier",
          versionAdded: null,
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          conflicts: null,
          inverseConflicts: false,
          assignable: false,
          negatable: true,
          blockOnly: false,
          exceptionOnly: false,
          valueOptional: false,
          valueFormat: null
        }, {
          name: "websocket",
          aliases: null,
          description: "The rule applies only to WebSocket connections.",
          docs: "https://adguard.app/kb/general/ad-filtering/create-own-filters/#websocket-modifier",
          versionAdded: null,
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          conflicts: null,
          inverseConflicts: false,
          assignable: false,
          negatable: true,
          blockOnly: false,
          exceptionOnly: false,
          valueOptional: false,
          valueFormat: null
        }, {
          name: "websocket",
          aliases: null,
          description: "The rule applies only to WebSocket connections.",
          docs: "https://help.adblockplus.org/hc/en-us/articles/360062733293-How-to-write-filters#type-options",
          versionAdded: null,
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          conflicts: null,
          inverseConflicts: false,
          assignable: false,
          negatable: true,
          blockOnly: false,
          exceptionOnly: false,
          valueOptional: false,
          valueFormat: null
        }, {
          name: "websocket",
          aliases: null,
          description: "The rule applies only to WebSocket connections.",
          docs: "https://help.adblockplus.org/hc/en-us/articles/360062733293-How-to-write-filters#type-options",
          versionAdded: null,
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          conflicts: null,
          inverseConflicts: false,
          assignable: false,
          negatable: true,
          blockOnly: false,
          exceptionOnly: false,
          valueOptional: false,
          valueFormat: null
        }],
        map: {
          "1": 0,
          "2": 0,
          "4": 0,
          "8": 1,
          "16": 1,
          "32": 1,
          "64": 1,
          "256": 2,
          "512": 3,
          "1024": 4,
          "2048": 4,
          "4096": 4,
          "8192": 4,
          "16384": 5,
          "32768": 5,
          "65536": 5,
          "131072": 5
        }
      }, {
        shared: [{
          name: "xmlhttprequest",
          aliases: ["xhr"],
          description: "The rule applies only to ajax requests (requests sent via javascript object XMLHttpRequest).",
          docs: "https://adguard.app/kb/general/ad-filtering/create-own-filters/#xmlhttprequest-modifier",
          versionAdded: null,
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          conflicts: null,
          inverseConflicts: false,
          assignable: false,
          negatable: true,
          blockOnly: false,
          exceptionOnly: false,
          valueOptional: false,
          valueFormat: null
        }, {
          name: "xhr",
          aliases: ["xmlhttprequest"],
          description: "The rule applies only to ajax requests (requests sent via javascript object XMLHttpRequest).",
          docs: "https://github.com/gorhill/uBlock/wiki/Static-filter-syntax#xhr",
          versionAdded: null,
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          conflicts: null,
          inverseConflicts: false,
          assignable: false,
          negatable: true,
          blockOnly: false,
          exceptionOnly: false,
          valueOptional: false,
          valueFormat: null
        }, {
          name: "xmlhttprequest",
          aliases: null,
          description: "The rule applies only to ajax requests (requests sent via javascript object XMLHttpRequest).",
          docs: "https://help.adblockplus.org/hc/en-us/articles/360062733293-How-to-write-filters#type-options",
          versionAdded: null,
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          conflicts: null,
          inverseConflicts: false,
          assignable: false,
          negatable: true,
          blockOnly: false,
          exceptionOnly: false,
          valueOptional: false,
          valueFormat: null
        }],
        map: {
          "1": 0,
          "2": 0,
          "4": 0,
          "8": 0,
          "16": 0,
          "32": 0,
          "64": 0,
          "128": 0,
          "256": 0,
          "512": 0,
          "1024": 1,
          "2048": 1,
          "4096": 1,
          "8192": 1,
          "16384": 2,
          "32768": 2,
          "65536": 2,
          "131072": 2
        }
      }],
      map: {
        all: 0,
        app: 1,
        badfilter: 2,
        cname: 3,
        content: 4,
        cookie: 5,
        csp: 6,
        denyallow: 7,
        document: 8,
        doc: 8,
        domain: 9,
        from: 9,
        elemhide: 10,
        ehide: 10,
        empty: 11,
        extension: 12,
        "first-party": 13,
        "1p": 13,
        "~third-party": 13,
        font: 14,
        genericblock: 15,
        generichide: 16,
        ghide: 16,
        header: 17,
        hls: 18,
        image: 19,
        important: 20,
        "inline-font": 21,
        "inline-script": 22,
        jsinject: 23,
        jsonprune: 24,
        "match-case": 25,
        media: 26,
        method: 27,
        mp4: 28,
        network: 29,
        _: 30,
        "object-subrequest": 31,
        object: 32,
        other: 33,
        permissions: 34,
        ping: 35,
        popunder: 36,
        popup: 37,
        "redirect-rule": 38,
        redirect: 39,
        rewrite: 39,
        referrerpolicy: 40,
        removeheader: 41,
        removeparam: 42,
        replace: 43,
        script: 44,
        specifichide: 45,
        shide: 45,
        stealth: 46,
        strict1p: 47,
        strict3p: 48,
        stylesheet: 49,
        css: 49,
        subdocument: 50,
        frame: 50,
        "third-party": 51,
        "3p": 51,
        to: 52,
        urlblock: 53,
        webrtc: 54,
        websocket: 55,
        xmlhttprequest: 56,
        xhr: 56
      }
    };
    var redirectsCompatibilityTableData = {
      shared: [{
        shared: [{
          name: "1x1-transparent.gif",
          aliases: ["1x1.gif", "1x1-transparent-gif"],
          description: "Redirects to a 1x1 transparent GIF.",
          docs: "https://github.com/AdguardTeam/Scriptlets/blob/master/wiki/about-redirects.md#1x1-transparent.gif",
          versionAdded: null,
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          isBlocking: false,
          resourceTypes: []
        }, {
          name: "1x1.gif",
          aliases: null,
          description: "Redirects to a 1x1 transparent GIF.",
          docs: "https://github.com/gorhill/uBlock/wiki/Resources-Library#available-empty-redirect-resources",
          versionAdded: null,
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          isBlocking: false,
          resourceTypes: ["image"]
        }, {
          name: "1x1-transparent-gif",
          aliases: null,
          description: "Redirects to a 1x1 transparent GIF.",
          docs: "https://help.adblockplus.org/hc/en-us/articles/360062733293#rewrite",
          versionAdded: null,
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          isBlocking: false,
          resourceTypes: []
        }],
        map: {
          "1": 0,
          "2": 0,
          "4": 0,
          "8": 0,
          "16": 0,
          "32": 0,
          "64": 0,
          "1024": 1,
          "2048": 1,
          "4096": 1,
          "8192": 1,
          "16384": 2,
          "32768": 2,
          "65536": 2,
          "131072": 2
        }
      }, {
        shared: [{
          name: "2x2-transparent.png",
          aliases: ["2x2.png", "2x2-transparent-png"],
          description: "Redirects to a 2x2 transparent PNG.",
          docs: "https://github.com/AdguardTeam/Scriptlets/blob/master/wiki/about-redirects.md#2x2-transparent.png",
          versionAdded: null,
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          isBlocking: false,
          resourceTypes: []
        }, {
          name: "2x2.png",
          aliases: null,
          description: "Redirects to a 2x2 transparent PNG.",
          docs: "https://github.com/gorhill/uBlock/wiki/Resources-Library#available-empty-redirect-resources",
          versionAdded: null,
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          isBlocking: false,
          resourceTypes: ["image"]
        }, {
          name: "2x2-transparent-png",
          aliases: null,
          description: "Redirects to a 2x2 transparent PNG.",
          docs: "https://help.adblockplus.org/hc/en-us/articles/360062733293#rewrite",
          versionAdded: null,
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          isBlocking: false,
          resourceTypes: []
        }],
        map: {
          "1": 0,
          "2": 0,
          "4": 0,
          "8": 0,
          "16": 0,
          "32": 0,
          "64": 0,
          "1024": 1,
          "2048": 1,
          "4096": 1,
          "8192": 1,
          "16384": 2,
          "32768": 2,
          "65536": 2,
          "131072": 2
        }
      }, {
        shared: [{
          name: "32x32-transparent.png",
          aliases: ["32x32.png", "32x32-transparent-png"],
          description: "Redirects to a 32x32 transparent PNG.",
          docs: "https://github.com/AdguardTeam/Scriptlets/blob/master/wiki/about-redirects.md#32x32-transparent.png",
          versionAdded: null,
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          isBlocking: false,
          resourceTypes: []
        }, {
          name: "32x32.png",
          aliases: null,
          description: "Redirects to a 32x32 transparent PNG.",
          docs: "https://github.com/gorhill/uBlock/wiki/Resources-Library#available-empty-redirect-resources",
          versionAdded: null,
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          isBlocking: false,
          resourceTypes: ["image"]
        }, {
          name: "32x32-transparent-png",
          aliases: null,
          description: "Redirects to a 32x32 transparent PNG.",
          docs: "https://help.adblockplus.org/hc/en-us/articles/360062733293#rewrite",
          versionAdded: null,
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          isBlocking: false,
          resourceTypes: []
        }],
        map: {
          "1": 0,
          "2": 0,
          "4": 0,
          "8": 0,
          "16": 0,
          "32": 0,
          "64": 0,
          "1024": 1,
          "2048": 1,
          "4096": 1,
          "8192": 1,
          "16384": 2,
          "32768": 2,
          "65536": 2,
          "131072": 2
        }
      }, {
        shared: [{
          name: "3x2-transparent.png",
          aliases: ["3x2.png", "3x2-transparent-png"],
          description: "Redirects to a 3x2 transparent PNG.",
          docs: "https://github.com/AdguardTeam/Scriptlets/blob/master/wiki/about-redirects.md#3x2-transparent.png",
          versionAdded: null,
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          isBlocking: false,
          resourceTypes: []
        }, {
          name: "3x2.png",
          aliases: null,
          description: "Redirects to a 3x2 transparent PNG.",
          docs: "https://github.com/gorhill/uBlock/wiki/Resources-Library#available-empty-redirect-resources",
          versionAdded: null,
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          isBlocking: false,
          resourceTypes: ["image"]
        }, {
          name: "3x2-transparent-png",
          aliases: null,
          description: "Redirects to a 3x2 transparent PNG.",
          docs: "https://help.adblockplus.org/hc/en-us/articles/360062733293#rewrite",
          versionAdded: null,
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          isBlocking: false,
          resourceTypes: []
        }],
        map: {
          "1": 0,
          "2": 0,
          "4": 0,
          "8": 0,
          "16": 0,
          "32": 0,
          "64": 0,
          "1024": 1,
          "2048": 1,
          "4096": 1,
          "8192": 1,
          "16384": 2,
          "32768": 2,
          "65536": 2,
          "131072": 2
        }
      }, {
        shared: [{
          name: "amazon-apstag",
          aliases: ["ubo-amazon_apstag.js", "amazon_apstag.js"],
          description: "Mocks Amazon's apstag.js",
          docs: "https://github.com/AdguardTeam/Scriptlets/blob/master/wiki/about-redirects.md#amazon-apstag",
          versionAdded: null,
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          isBlocking: false,
          resourceTypes: []
        }, {
          name: "amazon_apstag.js",
          aliases: null,
          description: "Mocks Amazon's apstag.js",
          docs: "https://github.com/gorhill/uBlock/wiki/Resources-Library#amazon_apstagjs-",
          versionAdded: null,
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          isBlocking: false,
          resourceTypes: ["script"]
        }],
        map: {
          "1": 0,
          "2": 0,
          "4": 0,
          "8": 0,
          "16": 0,
          "32": 0,
          "64": 0,
          "1024": 1,
          "2048": 1,
          "4096": 1,
          "8192": 1
        }
      }, {
        shared: [{
          name: "amazon_ads.js",
          aliases: null,
          description: null,
          docs: null,
          versionAdded: null,
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          isBlocking: false,
          resourceTypes: ["script"]
        }],
        map: {
          "1024": 0,
          "2048": 0,
          "4096": 0,
          "8192": 0
        }
      }, {
        shared: [{
          name: "ampproject_v0.js",
          aliases: null,
          description: null,
          docs: null,
          versionAdded: null,
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          isBlocking: false,
          resourceTypes: ["script"]
        }],
        map: {
          "1024": 0,
          "2048": 0,
          "4096": 0,
          "8192": 0
        }
      }, {
        shared: [{
          name: "ati-smarttag",
          aliases: null,
          description: null,
          docs: null,
          versionAdded: null,
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          isBlocking: false,
          resourceTypes: []
        }],
        map: {
          "1": 0,
          "2": 0,
          "4": 0,
          "8": 0,
          "16": 0,
          "32": 0,
          "64": 0
        }
      }, {
        shared: [{
          name: "chartbeat.js",
          aliases: null,
          description: null,
          docs: null,
          versionAdded: null,
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          isBlocking: false,
          resourceTypes: ["script"]
        }],
        map: {
          "1024": 0,
          "2048": 0,
          "4096": 0,
          "8192": 0
        }
      }, {
        shared: [{
          name: "click2load.html",
          aliases: ["click2load.html", "ubo-click2load.html"],
          description: "Redirects resource and replaces supposed content by decoy frame with button for original content recovering.",
          docs: null,
          versionAdded: null,
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          isBlocking: true,
          resourceTypes: []
        }, {
          name: "click2load.html",
          aliases: null,
          description: "Redirects resource and replaces supposed content by decoy frame with button for original content recovering.",
          docs: null,
          versionAdded: null,
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          isBlocking: true,
          resourceTypes: []
        }],
        map: {
          "1": 0,
          "2": 0,
          "4": 0,
          "8": 0,
          "16": 0,
          "32": 0,
          "64": 0,
          "1024": 1,
          "2048": 1,
          "4096": 1,
          "8192": 1
        }
      }, {
        shared: [{
          name: "didomi-loader",
          aliases: null,
          description: "Mocks Didomi's CMP loader script.",
          docs: null,
          versionAdded: null,
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          isBlocking: false,
          resourceTypes: []
        }],
        map: {
          "1": 0,
          "2": 0,
          "4": 0,
          "8": 0,
          "16": 0,
          "32": 0,
          "64": 0
        }
      }, {
        shared: [{
          name: "empty",
          aliases: null,
          description: "Redirects to an empty file.",
          docs: null,
          versionAdded: null,
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          isBlocking: false,
          resourceTypes: []
        }, {
          name: "empty",
          aliases: null,
          description: "Redirects to an empty file.",
          docs: null,
          versionAdded: null,
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          isBlocking: false,
          resourceTypes: []
        }],
        map: {
          "1": 0,
          "2": 0,
          "4": 0,
          "8": 0,
          "16": 0,
          "32": 0,
          "64": 0,
          "1024": 1,
          "2048": 1,
          "4096": 1,
          "8192": 1
        }
      }, {
        shared: [{
          name: "fingerprintjs2",
          aliases: ["fingerprint2.js"],
          description: "Mocks FingerprintJS2 script.",
          docs: null,
          versionAdded: null,
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          isBlocking: false,
          resourceTypes: []
        }, {
          name: "fingerprint2.js",
          aliases: null,
          description: "Mocks FingerprintJS2 script.",
          docs: null,
          versionAdded: null,
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          isBlocking: false,
          resourceTypes: ["script"]
        }],
        map: {
          "1": 0,
          "2": 0,
          "4": 0,
          "8": 0,
          "16": 0,
          "32": 0,
          "64": 0,
          "1024": 1,
          "2048": 1,
          "4096": 1,
          "8192": 1
        }
      }, {
        shared: [{
          name: "fingerprintjs3",
          aliases: ["fingerprint3.js"],
          description: "Mocks FingerprintJS v3.",
          docs: null,
          versionAdded: null,
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          isBlocking: false,
          resourceTypes: []
        }, {
          name: "fingerprint3.js",
          aliases: null,
          description: "Mocks FingerprintJS v3.",
          docs: null,
          versionAdded: null,
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          isBlocking: false,
          resourceTypes: ["script"]
        }],
        map: {
          "1": 0,
          "2": 0,
          "4": 0,
          "8": 0,
          "16": 0,
          "32": 0,
          "64": 0,
          "1024": 1,
          "2048": 1,
          "4096": 1,
          "8192": 1
        }
      }, {
        shared: [{
          name: "gemius",
          aliases: null,
          description: "Mocks Gemius Analytics.",
          docs: null,
          versionAdded: null,
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          isBlocking: false,
          resourceTypes: []
        }],
        map: {
          "1": 0,
          "2": 0,
          "4": 0,
          "8": 0,
          "16": 0,
          "32": 0,
          "64": 0
        }
      }, {
        shared: [{
          name: "google-analytics-ga",
          aliases: ["ubo-google-analytics_ga.js", "google-analytics_ga.js"],
          description: "Mocks old Google Analytics API.",
          docs: null,
          versionAdded: null,
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          isBlocking: false,
          resourceTypes: []
        }, {
          name: "google-analytics_ga.js",
          aliases: null,
          description: "Mocks old Google Analytics API.",
          docs: null,
          versionAdded: null,
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          isBlocking: false,
          resourceTypes: ["script"]
        }],
        map: {
          "1": 0,
          "2": 0,
          "4": 0,
          "8": 0,
          "16": 0,
          "32": 0,
          "64": 0,
          "1024": 1,
          "2048": 1,
          "4096": 1,
          "8192": 1
        }
      }, {
        shared: [{
          name: "google-analytics",
          aliases: ["ubo-google-analytics_analytics.js", "google-analytics_analytics.js", "googletagmanager-gtm", "ubo-googletagmanager_gtm.js", "googletagmanager_gtm.js"],
          description: "Mocks Google's Analytics and Tag Manager APIs.",
          docs: null,
          versionAdded: null,
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          isBlocking: false,
          resourceTypes: []
        }, {
          name: "google-analytics_analytics.js",
          aliases: null,
          description: "Mocks Google's Analytics and Tag Manager APIs.",
          docs: null,
          versionAdded: null,
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          isBlocking: false,
          resourceTypes: ["script"]
        }],
        map: {
          "1": 0,
          "2": 0,
          "4": 0,
          "8": 0,
          "16": 0,
          "32": 0,
          "64": 0,
          "1024": 1,
          "2048": 1,
          "4096": 1,
          "8192": 1
        }
      }, {
        shared: [{
          name: "google-analytics_cx_api.js",
          aliases: null,
          description: null,
          docs: null,
          versionAdded: null,
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          isBlocking: false,
          resourceTypes: ["script"]
        }],
        map: {
          "1024": 0,
          "2048": 0,
          "4096": 0,
          "8192": 0
        }
      }, {
        shared: [{
          name: "google-analytics_inpage_linkid.js",
          aliases: null,
          description: null,
          docs: null,
          versionAdded: null,
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          isBlocking: false,
          resourceTypes: ["script"]
        }],
        map: {
          "1024": 0,
          "2048": 0,
          "4096": 0,
          "8192": 0
        }
      }, {
        shared: [{
          name: "google-ima3",
          aliases: ["ubo-google-ima.js", "google-ima.js"],
          description: "Mocks the IMA SDK of Google.",
          docs: null,
          versionAdded: null,
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          isBlocking: false,
          resourceTypes: []
        }, {
          name: "google-ima.js",
          aliases: null,
          description: "Mocks the IMA SDK of Google.",
          docs: null,
          versionAdded: null,
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          isBlocking: false,
          resourceTypes: ["script"]
        }],
        map: {
          "1": 0,
          "2": 0,
          "4": 0,
          "8": 0,
          "16": 0,
          "32": 0,
          "64": 0,
          "1024": 1,
          "2048": 1,
          "4096": 1,
          "8192": 1
        }
      }, {
        shared: [{
          name: "googlesyndication-adsbygoogle",
          aliases: ["ubo-googlesyndication_adsbygoogle.js", "ubo-googlesyndication.com/adsbygoogle.js", "googlesyndication_adsbygoogle.js"],
          description: "Mocks Google AdSense API.",
          docs: null,
          versionAdded: null,
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          isBlocking: false,
          resourceTypes: []
        }, {
          name: "googlesyndication_adsbygoogle.js",
          aliases: ["googlesyndication.com/adsbygoogle.js"],
          description: "Mocks Google AdSense API.",
          docs: null,
          versionAdded: null,
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          isBlocking: false,
          resourceTypes: ["script"]
        }],
        map: {
          "1": 0,
          "2": 0,
          "4": 0,
          "8": 0,
          "16": 0,
          "32": 0,
          "64": 0,
          "1024": 1,
          "2048": 1,
          "4096": 1,
          "8192": 1
        }
      }, {
        shared: [{
          name: "googletagservices-gpt",
          aliases: ["ubo-googletagservices_gpt.js", "googletagservices_gpt.js"],
          description: "Mocks Google Publisher Tag API.",
          docs: null,
          versionAdded: null,
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          isBlocking: false,
          resourceTypes: []
        }, {
          name: "googletagservices_gpt.js",
          aliases: null,
          description: "Mocks Google Publisher Tag API.",
          docs: null,
          versionAdded: null,
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          isBlocking: false,
          resourceTypes: ["script"]
        }],
        map: {
          "1": 0,
          "2": 0,
          "4": 0,
          "8": 0,
          "16": 0,
          "32": 0,
          "64": 0,
          "1024": 1,
          "2048": 1,
          "4096": 1,
          "8192": 1
        }
      }, {
        shared: [{
          name: "hd-main.js",
          aliases: null,
          description: null,
          docs: null,
          versionAdded: null,
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          isBlocking: false,
          resourceTypes: ["script"]
        }],
        map: {
          "1024": 0,
          "2048": 0,
          "4096": 0,
          "8192": 0
        }
      }, {
        shared: [{
          name: "matomo",
          aliases: null,
          description: "Mocks the piwik.js file of Matomo (formerly Piwik).",
          docs: null,
          versionAdded: null,
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          isBlocking: false,
          resourceTypes: []
        }],
        map: {
          "1": 0,
          "2": 0,
          "4": 0,
          "8": 0,
          "16": 0,
          "32": 0,
          "64": 0
        }
      }, {
        shared: [{
          name: "metrika-yandex-tag",
          aliases: null,
          description: "Mocks Yandex Metrika API.",
          docs: null,
          versionAdded: null,
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          isBlocking: false,
          resourceTypes: []
        }],
        map: {
          "1": 0,
          "2": 0,
          "4": 0,
          "8": 0,
          "16": 0,
          "32": 0,
          "64": 0
        }
      }, {
        shared: [{
          name: "metrika-yandex-watch",
          aliases: null,
          description: "Mocks the old Yandex Metrika API.",
          docs: null,
          versionAdded: null,
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          isBlocking: false,
          resourceTypes: []
        }],
        map: {
          "1": 0,
          "2": 0,
          "4": 0,
          "8": 0,
          "16": 0,
          "32": 0,
          "64": 0
        }
      }, {
        shared: [{
          name: "naver-wcslog",
          aliases: null,
          description: "Mocks wcslog.js of Naver Analytics.",
          docs: null,
          versionAdded: null,
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          isBlocking: false,
          resourceTypes: []
        }],
        map: {
          "1": 0,
          "2": 0,
          "4": 0,
          "8": 0,
          "16": 0,
          "32": 0,
          "64": 0
        }
      }, {
        shared: [{
          name: "no-protected-audience",
          aliases: null,
          description: "Prevents using the Protected Audience API.",
          docs: null,
          versionAdded: null,
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          isBlocking: false,
          resourceTypes: []
        }],
        map: {
          "1": 0,
          "2": 0,
          "4": 0,
          "8": 0,
          "16": 0,
          "32": 0,
          "64": 0
        }
      }, {
        shared: [{
          name: "no-topics",
          aliases: null,
          description: "Prevents using the Topics API.",
          docs: null,
          versionAdded: null,
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          isBlocking: false,
          resourceTypes: []
        }],
        map: {
          "1": 0,
          "2": 0,
          "4": 0,
          "8": 0,
          "16": 0,
          "32": 0,
          "64": 0
        }
      }, {
        shared: [{
          name: "noeval",
          aliases: ["noeval.js", "silent-noeval.js", "ubo-noeval.js", "ubo-silent-noeval.js", "ubo-noeval", "ubo-silent-noeval"],
          description: "Prevents page to use eval.",
          docs: null,
          versionAdded: null,
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          isBlocking: false,
          resourceTypes: []
        }, {
          name: "noeval.js",
          aliases: null,
          description: "Prevents page to use eval.",
          docs: null,
          versionAdded: null,
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          isBlocking: false,
          resourceTypes: ["script"]
        }],
        map: {
          "1": 0,
          "2": 0,
          "4": 0,
          "8": 0,
          "16": 0,
          "32": 0,
          "64": 0,
          "1024": 1,
          "2048": 1,
          "4096": 1,
          "8192": 1
        }
      }, {
        shared: [{
          name: "noop-0.5s.mp3",
          aliases: null,
          description: "Redirects to an empty MP3 file with a duration of 0.5 seconds.",
          docs: null,
          versionAdded: null,
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          isBlocking: false,
          resourceTypes: ["media"]
        }],
        map: {
          "1024": 0,
          "2048": 0,
          "4096": 0,
          "8192": 0
        }
      }, {
        shared: [{
          name: "noopcss",
          aliases: ["noop.css", "blank-css"],
          description: "Redirects to an empty CSS file.",
          docs: null,
          versionAdded: null,
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          isBlocking: false,
          resourceTypes: []
        }, {
          name: "noop.css",
          aliases: null,
          description: "Redirects to an empty CSS file.",
          docs: null,
          versionAdded: null,
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          isBlocking: false,
          resourceTypes: ["stylesheet"]
        }, {
          name: "blank-css",
          aliases: null,
          description: "Redirects to an empty CSS file.",
          docs: null,
          versionAdded: null,
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          isBlocking: false,
          resourceTypes: []
        }],
        map: {
          "1": 0,
          "2": 0,
          "4": 0,
          "8": 0,
          "16": 0,
          "32": 0,
          "64": 0,
          "1024": 1,
          "2048": 1,
          "4096": 1,
          "8192": 1,
          "16384": 2,
          "32768": 2,
          "65536": 2,
          "131072": 2
        }
      }, {
        shared: [{
          name: "noopframe",
          aliases: ["noop.html", "blank-html"],
          description: "Redirects to an empty HTML file.",
          docs: null,
          versionAdded: null,
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          isBlocking: false,
          resourceTypes: []
        }, {
          name: "noop.html",
          aliases: null,
          description: "Redirects to an empty HTML file.",
          docs: null,
          versionAdded: null,
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          isBlocking: false,
          resourceTypes: ["sub_frame"]
        }, {
          name: "blank-html",
          aliases: null,
          description: "Redirects to an empty HTML file.",
          docs: null,
          versionAdded: null,
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          isBlocking: false,
          resourceTypes: []
        }],
        map: {
          "1": 0,
          "2": 0,
          "4": 0,
          "8": 0,
          "16": 0,
          "32": 0,
          "64": 0,
          "1024": 1,
          "2048": 1,
          "4096": 1,
          "8192": 1,
          "16384": 2,
          "32768": 2,
          "65536": 2,
          "131072": 2
        }
      }, {
        shared: [{
          name: "noopjs",
          aliases: ["noop.js", "blank-js"],
          description: "Redirects to an empty JavaScript file.",
          docs: null,
          versionAdded: null,
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          isBlocking: false,
          resourceTypes: []
        }, {
          name: "noop.js",
          aliases: null,
          description: "Redirects to an empty JavaScript file.",
          docs: null,
          versionAdded: null,
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          isBlocking: false,
          resourceTypes: ["script"]
        }, {
          name: "blank-js",
          aliases: null,
          description: "Redirects to an empty JavaScript file.",
          docs: null,
          versionAdded: null,
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          isBlocking: false,
          resourceTypes: []
        }],
        map: {
          "1": 0,
          "2": 0,
          "4": 0,
          "8": 0,
          "16": 0,
          "32": 0,
          "64": 0,
          "1024": 1,
          "2048": 1,
          "4096": 1,
          "8192": 1,
          "16384": 2,
          "32768": 2,
          "65536": 2,
          "131072": 2
        }
      }, {
        shared: [{
          name: "noopjson",
          aliases: ["noop.json"],
          description: "Redirects to an empty JSON file.",
          docs: null,
          versionAdded: null,
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          isBlocking: false,
          resourceTypes: []
        }, {
          name: "noop.json",
          aliases: null,
          description: "Redirects to an empty JSON file.",
          docs: null,
          versionAdded: null,
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          isBlocking: false,
          resourceTypes: []
        }],
        map: {
          "1": 0,
          "2": 0,
          "4": 0,
          "8": 0,
          "16": 0,
          "32": 0,
          "64": 0,
          "1024": 1,
          "2048": 1,
          "4096": 1,
          "8192": 1
        }
      }, {
        shared: [{
          name: "noopmp3-0.1s",
          aliases: ["noop-0.1s.mp3", "blank-mp3"],
          description: "Redirects to an empty MP3 file with a duration of 0.1 seconds.",
          docs: null,
          versionAdded: null,
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          isBlocking: false,
          resourceTypes: []
        }, {
          name: "noop-0.1s.mp3",
          aliases: null,
          description: "Redirects to an empty MP3 file with a duration of 0.1 seconds.",
          docs: null,
          versionAdded: null,
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          isBlocking: false,
          resourceTypes: ["media"]
        }, {
          name: "blank-mp3",
          aliases: null,
          description: "Redirects to an empty MP3 file with a duration of 0.1 seconds.",
          docs: null,
          versionAdded: null,
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          isBlocking: false,
          resourceTypes: []
        }],
        map: {
          "1": 0,
          "2": 0,
          "4": 0,
          "8": 0,
          "16": 0,
          "32": 0,
          "64": 0,
          "1024": 1,
          "2048": 1,
          "4096": 1,
          "8192": 1,
          "16384": 2,
          "32768": 2,
          "65536": 2,
          "131072": 2
        }
      }, {
        shared: [{
          name: "noopmp4-1s",
          aliases: ["noop-1s.mp4", "blank-mp4"],
          description: "Redirects to an empty MP4 file with a duration of 1 second.",
          docs: null,
          versionAdded: null,
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          isBlocking: false,
          resourceTypes: []
        }, {
          name: "noop-1s.mp4",
          aliases: null,
          description: "Redirects to an empty MP4 file with a duration of 1 second.",
          docs: null,
          versionAdded: null,
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          isBlocking: false,
          resourceTypes: ["media"]
        }, {
          name: "blank-mp4",
          aliases: null,
          description: "Redirects to an empty MP4 file with a duration of 1 second.",
          docs: null,
          versionAdded: null,
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          isBlocking: false,
          resourceTypes: []
        }],
        map: {
          "1": 0,
          "2": 0,
          "4": 0,
          "8": 0,
          "16": 0,
          "32": 0,
          "64": 0,
          "1024": 1,
          "2048": 1,
          "4096": 1,
          "8192": 1,
          "16384": 2,
          "32768": 2,
          "65536": 2,
          "131072": 2
        }
      }, {
        shared: [{
          name: "nooptext",
          aliases: ["noop.txt", "blank-text"],
          description: "Redirects to an empty text file.",
          docs: null,
          versionAdded: null,
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          isBlocking: false,
          resourceTypes: []
        }, {
          name: "noop.txt",
          aliases: null,
          description: "Redirects to an empty text file.",
          docs: null,
          versionAdded: null,
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          isBlocking: false,
          resourceTypes: ["image", "media", "sub_frame", "stylesheet", "script", "xmlhttprequest", "other"]
        }, {
          name: "blank-text",
          aliases: null,
          description: "Redirects to an empty text file.",
          docs: null,
          versionAdded: null,
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          isBlocking: false,
          resourceTypes: []
        }],
        map: {
          "1": 0,
          "2": 0,
          "4": 0,
          "8": 0,
          "16": 0,
          "32": 0,
          "64": 0,
          "1024": 1,
          "2048": 1,
          "4096": 1,
          "8192": 1,
          "16384": 2,
          "32768": 2,
          "65536": 2,
          "131072": 2
        }
      }, {
        shared: [{
          name: "noopvast-2.0",
          aliases: null,
          description: "Redirects to an empty VAST 2.0 XML file.",
          docs: null,
          versionAdded: null,
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          isBlocking: false,
          resourceTypes: []
        }],
        map: {
          "1": 0,
          "2": 0,
          "4": 0,
          "8": 0,
          "16": 0,
          "32": 0,
          "64": 0
        }
      }, {
        shared: [{
          name: "noopvast-3.0",
          aliases: null,
          description: "Redirects to an empty VAST 3.0 XML file.",
          docs: null,
          versionAdded: null,
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          isBlocking: false,
          resourceTypes: []
        }],
        map: {
          "1": 0,
          "2": 0,
          "4": 0,
          "8": 0,
          "16": 0,
          "32": 0,
          "64": 0
        }
      }, {
        shared: [{
          name: "noopvast-4.0",
          aliases: null,
          description: "Redirects to an empty VAST 4.0 XML file.",
          docs: null,
          versionAdded: null,
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          isBlocking: false,
          resourceTypes: []
        }],
        map: {
          "1": 0,
          "2": 0,
          "4": 0,
          "8": 0,
          "16": 0,
          "32": 0,
          "64": 0
        }
      }, {
        shared: [{
          name: "noopvmap-1.0",
          aliases: ["noop-vmap1.0.xml"],
          description: "Redirects to an empty VMAP 1.0 XML file.",
          docs: null,
          versionAdded: null,
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          isBlocking: false,
          resourceTypes: []
        }, {
          name: "noop-vmap1.0.xml",
          aliases: null,
          description: "Redirects to an empty VMAP 1.0 XML file.",
          docs: null,
          versionAdded: null,
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          isBlocking: false,
          resourceTypes: ["media"]
        }],
        map: {
          "1": 0,
          "2": 0,
          "4": 0,
          "8": 0,
          "16": 0,
          "32": 0,
          "64": 0,
          "1024": 1,
          "2048": 1,
          "4096": 1,
          "8192": 1
        }
      }, {
        shared: [{
          name: "nowebrtc",
          aliases: ["nowebrtc.js", "ubo-nowebrtc.js", "ubo-nowebrtc"],
          description: "Disables WebRTC by overriding `RTCPeerConnection`.",
          docs: null,
          versionAdded: null,
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          isBlocking: false,
          resourceTypes: []
        }, {
          name: "nowebrtc.js",
          aliases: null,
          description: "Disables WebRTC by overriding `RTCPeerConnection`.",
          docs: null,
          versionAdded: null,
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          isBlocking: false,
          resourceTypes: ["other"]
        }],
        map: {
          "1": 0,
          "2": 0,
          "4": 0,
          "8": 0,
          "16": 0,
          "32": 0,
          "64": 0,
          "1024": 1,
          "2048": 1,
          "4096": 1,
          "8192": 1
        }
      }, {
        shared: [{
          name: "outbrain-widget.js",
          aliases: null,
          description: null,
          docs: null,
          versionAdded: null,
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          isBlocking: false,
          resourceTypes: ["script"]
        }],
        map: {
          "1024": 0,
          "2048": 0,
          "4096": 0,
          "8192": 0
        }
      }, {
        shared: [{
          name: "pardot-1.0",
          aliases: null,
          description: "Mocks the pd.js file of Salesforce.",
          docs: null,
          versionAdded: null,
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          isBlocking: false,
          resourceTypes: []
        }],
        map: {
          "1": 0,
          "2": 0,
          "4": 0,
          "8": 0,
          "16": 0,
          "32": 0,
          "64": 0
        }
      }, {
        shared: [{
          name: "prebid-ads",
          aliases: ["prebid-ads.js"],
          description: "Mocks prebid-ads.js script.",
          docs: null,
          versionAdded: null,
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          isBlocking: false,
          resourceTypes: []
        }, {
          name: "prebid-ads.js",
          aliases: null,
          description: "Mocks prebid-ads.js script.",
          docs: null,
          versionAdded: null,
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          isBlocking: false,
          resourceTypes: ["script"]
        }],
        map: {
          "1": 0,
          "2": 0,
          "4": 0,
          "8": 0,
          "16": 0,
          "32": 0,
          "64": 0,
          "1024": 1,
          "2048": 1,
          "4096": 1,
          "8192": 1
        }
      }, {
        shared: [{
          name: "prebid",
          aliases: null,
          description: "Mocks the prebid.js header bidding suit.",
          docs: null,
          versionAdded: null,
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          isBlocking: false,
          resourceTypes: []
        }],
        map: {
          "1": 0,
          "2": 0,
          "4": 0,
          "8": 0,
          "16": 0,
          "32": 0,
          "64": 0
        }
      }, {
        shared: [{
          name: "prevent-bab",
          aliases: ["nobab.js"],
          description: "Prevents BlockAdblock script from detecting an ad blocker.",
          docs: null,
          versionAdded: null,
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          isBlocking: false,
          resourceTypes: []
        }, {
          name: "nobab.js",
          aliases: null,
          description: "Prevents BlockAdblock script from detecting an ad blocker.",
          docs: null,
          versionAdded: null,
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          isBlocking: false,
          resourceTypes: ["script"]
        }],
        map: {
          "1": 0,
          "2": 0,
          "4": 0,
          "8": 0,
          "16": 0,
          "32": 0,
          "64": 0,
          "1024": 1,
          "2048": 1,
          "4096": 1,
          "8192": 1
        }
      }, {
        shared: [{
          name: "prevent-bab2",
          aliases: ["nobab2.js"],
          description: "Prevents BlockAdblock script from detecting an ad blocker.",
          docs: null,
          versionAdded: null,
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          isBlocking: false,
          resourceTypes: []
        }, {
          name: "nobab2.js",
          aliases: null,
          description: "Prevents BlockAdblock script from detecting an ad blocker.",
          docs: null,
          versionAdded: null,
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          isBlocking: false,
          resourceTypes: ["script"]
        }],
        map: {
          "1": 0,
          "2": 0,
          "4": 0,
          "8": 0,
          "16": 0,
          "32": 0,
          "64": 0,
          "1024": 1,
          "2048": 1,
          "4096": 1,
          "8192": 1
        }
      }, {
        shared: [{
          name: "prevent-fab-3.2.0",
          aliases: ["nofab.js"],
          description: "Mocks FAB script v3.2.0.",
          docs: null,
          versionAdded: null,
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          isBlocking: false,
          resourceTypes: []
        }, {
          name: "nofab.js",
          aliases: ["fuckadblock.js-3.2.0", "fuckadblock.js-3.2.0.js"],
          description: "Mocks FAB script v3.2.0.",
          docs: null,
          versionAdded: null,
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          isBlocking: false,
          resourceTypes: ["script"]
        }],
        map: {
          "1": 0,
          "2": 0,
          "4": 0,
          "8": 0,
          "16": 0,
          "32": 0,
          "64": 0,
          "1024": 1,
          "2048": 1,
          "4096": 1,
          "8192": 1
        }
      }, {
        shared: [{
          name: "prevent-popads-net",
          aliases: ["popads.js"],
          description: "Aborts on property write (PopAds, popns), throws reference error with random id.",
          docs: null,
          versionAdded: null,
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          isBlocking: false,
          resourceTypes: []
        }, {
          name: "popads.js",
          aliases: null,
          description: "Aborts on property write (PopAds, popns), throws reference error with random id.",
          docs: null,
          versionAdded: null,
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          isBlocking: false,
          resourceTypes: ["script"]
        }],
        map: {
          "1": 0,
          "2": 0,
          "4": 0,
          "8": 0,
          "16": 0,
          "32": 0,
          "64": 0,
          "1024": 1,
          "2048": 1,
          "4096": 1,
          "8192": 1
        }
      }, {
        shared: [{
          name: "scorecardresearch-beacon",
          aliases: ["scorecardresearch_beacon.js"],
          description: "Mocks Scorecard Research API.",
          docs: null,
          versionAdded: null,
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          isBlocking: false,
          resourceTypes: []
        }, {
          name: "scorecardresearch_beacon.js",
          aliases: null,
          description: "Mocks Scorecard Research API.",
          docs: null,
          versionAdded: null,
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          isBlocking: false,
          resourceTypes: ["script"]
        }],
        map: {
          "1": 0,
          "2": 0,
          "4": 0,
          "8": 0,
          "16": 0,
          "32": 0,
          "64": 0,
          "1024": 1,
          "2048": 1,
          "4096": 1,
          "8192": 1
        }
      }, {
        shared: [{
          name: "set-popads-dummy",
          aliases: ["popads-dummy.js"],
          description: "Sets static properties PopAds and popns.",
          docs: null,
          versionAdded: null,
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          isBlocking: false,
          resourceTypes: []
        }, {
          name: "popads-dummy.js",
          aliases: null,
          description: "Sets static properties PopAds and popns.",
          docs: null,
          versionAdded: null,
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          isBlocking: false,
          resourceTypes: ["script"]
        }],
        map: {
          "1": 0,
          "2": 0,
          "4": 0,
          "8": 0,
          "16": 0,
          "32": 0,
          "64": 0,
          "1024": 1,
          "2048": 1,
          "4096": 1,
          "8192": 1
        }
      }],
      map: {
        "1x1-transparent.gif": 0,
        "1x1.gif": 0,
        "1x1-transparent-gif": 0,
        "2x2-transparent.png": 1,
        "2x2.png": 1,
        "2x2-transparent-png": 1,
        "32x32-transparent.png": 2,
        "32x32.png": 2,
        "32x32-transparent-png": 2,
        "3x2-transparent.png": 3,
        "3x2.png": 3,
        "3x2-transparent-png": 3,
        "amazon-apstag": 4,
        "ubo-amazon_apstag.js": 4,
        "amazon_apstag.js": 4,
        "amazon_ads.js": 5,
        "ampproject_v0.js": 6,
        "ati-smarttag": 7,
        "chartbeat.js": 8,
        "click2load.html": 9,
        "ubo-click2load.html": 9,
        "didomi-loader": 10,
        empty: 11,
        fingerprintjs2: 12,
        "fingerprint2.js": 12,
        fingerprintjs3: 13,
        "fingerprint3.js": 13,
        gemius: 14,
        "google-analytics-ga": 15,
        "ubo-google-analytics_ga.js": 15,
        "google-analytics_ga.js": 15,
        "google-analytics": 16,
        "ubo-google-analytics_analytics.js": 16,
        "google-analytics_analytics.js": 16,
        "googletagmanager-gtm": 16,
        "ubo-googletagmanager_gtm.js": 16,
        "googletagmanager_gtm.js": 16,
        "google-analytics_cx_api.js": 17,
        "google-analytics_inpage_linkid.js": 18,
        "google-ima3": 19,
        "ubo-google-ima.js": 19,
        "google-ima.js": 19,
        "googlesyndication-adsbygoogle": 20,
        "ubo-googlesyndication_adsbygoogle.js": 20,
        "ubo-googlesyndication.com/adsbygoogle.js": 20,
        "googlesyndication_adsbygoogle.js": 20,
        "googlesyndication.com/adsbygoogle.js": 20,
        "googletagservices-gpt": 21,
        "ubo-googletagservices_gpt.js": 21,
        "googletagservices_gpt.js": 21,
        "hd-main.js": 22,
        matomo: 23,
        "metrika-yandex-tag": 24,
        "metrika-yandex-watch": 25,
        "naver-wcslog": 26,
        "no-protected-audience": 27,
        "no-topics": 28,
        noeval: 29,
        "noeval.js": 29,
        "silent-noeval.js": 29,
        "ubo-noeval.js": 29,
        "ubo-silent-noeval.js": 29,
        "ubo-noeval": 29,
        "ubo-silent-noeval": 29,
        "noop-0.5s.mp3": 30,
        noopcss: 31,
        "noop.css": 31,
        "blank-css": 31,
        noopframe: 32,
        "noop.html": 32,
        "blank-html": 32,
        noopjs: 33,
        "noop.js": 33,
        "blank-js": 33,
        noopjson: 34,
        "noop.json": 34,
        "noopmp3-0.1s": 35,
        "noop-0.1s.mp3": 35,
        "blank-mp3": 35,
        "noopmp4-1s": 36,
        "noop-1s.mp4": 36,
        "blank-mp4": 36,
        nooptext: 37,
        "noop.txt": 37,
        "blank-text": 37,
        "noopvast-2.0": 38,
        "noopvast-3.0": 39,
        "noopvast-4.0": 40,
        "noopvmap-1.0": 41,
        "noop-vmap1.0.xml": 41,
        nowebrtc: 42,
        "nowebrtc.js": 42,
        "ubo-nowebrtc.js": 42,
        "ubo-nowebrtc": 42,
        "outbrain-widget.js": 43,
        "pardot-1.0": 44,
        "prebid-ads": 45,
        "prebid-ads.js": 45,
        prebid: 46,
        "prevent-bab": 47,
        "nobab.js": 47,
        "prevent-bab2": 48,
        "nobab2.js": 48,
        "prevent-fab-3.2.0": 49,
        "nofab.js": 49,
        "fuckadblock.js-3.2.0": 49,
        "fuckadblock.js-3.2.0.js": 49,
        "prevent-popads-net": 50,
        "popads.js": 50,
        "scorecardresearch-beacon": 51,
        "scorecardresearch_beacon.js": 51,
        "set-popads-dummy": 52,
        "popads-dummy.js": 52
      }
    };
    var scriptletsCompatibilityTableData = {
      shared: [{
        shared: [{
          name: "abort-current-inline-script",
          aliases: ["abort-current-script.js", "ubo-abort-current-script.js", "acs.js", "ubo-acs.js", "ubo-abort-current-script", "ubo-acs", "abort-current-inline-script.js", "ubo-abort-current-inline-script.js", "acis.js", "ubo-acis.js", "ubo-abort-current-inline-script", "ubo-acis", "abp-abort-current-inline-script"],
          description: null,
          docs: "https://github.com/AdguardTeam/Scriptlets/blob/master/wiki/about-scriptlets.md#abort-current-inline-script",
          versionAdded: "1.0.4",
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          parameters: [{
            name: "property",
            required: true,
            description: null,
            pattern: null,
            "default": null,
            debug: false
          }, {
            name: "search",
            required: false,
            description: null,
            pattern: null,
            "default": null,
            debug: false
          }]
        }, {
          name: "abort-current-script.js",
          aliases: ["acs.js", "abort-current-inline-script.js", "acis.js"],
          description: null,
          docs: "https://github.com/gorhill/uBlock/wiki/Resources-Library#abort-current-scriptjs-",
          versionAdded: "1.37.0",
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          parameters: [{
            name: "property",
            required: true,
            description: null,
            pattern: null,
            "default": null,
            debug: false
          }, {
            name: "search",
            required: false,
            description: null,
            pattern: null,
            "default": null,
            debug: false
          }]
        }, {
          name: "abort-current-inline-script",
          aliases: null,
          description: null,
          docs: "https://help.adblockplus.org/hc/en-us/articles/1500002338501-Snippet-filters-tutorial#snippets-ref",
          versionAdded: "3.4.3",
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          parameters: [{
            name: "api",
            required: true,
            description: null,
            pattern: null,
            "default": null,
            debug: false
          }, {
            name: "search",
            required: false,
            description: null,
            pattern: null,
            "default": null,
            debug: false
          }]
        }],
        map: {
          "1": 0,
          "2": 0,
          "4": 0,
          "8": 0,
          "16": 0,
          "32": 0,
          "64": 0,
          "1024": 1,
          "2048": 1,
          "4096": 1,
          "8192": 1,
          "16384": 2,
          "32768": 2,
          "65536": 2,
          "131072": 2
        }
      }, {
        shared: [{
          name: "abort-on-property-read",
          aliases: ["abort-on-property-read.js", "ubo-abort-on-property-read.js", "aopr.js", "ubo-aopr.js", "ubo-abort-on-property-read", "ubo-aopr", "abp-abort-on-property-read"],
          description: null,
          docs: "https://github.com/AdguardTeam/Scriptlets/blob/master/wiki/about-scriptlets.md#abort-on-property-read",
          versionAdded: "1.0.4",
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          parameters: [{
            name: "property",
            required: true,
            description: null,
            pattern: null,
            "default": null,
            debug: false
          }]
        }, {
          name: "abort-on-property-read.js",
          aliases: ["aopr.js"],
          description: null,
          docs: "https://github.com/gorhill/uBlock/wiki/Resources-Library#abort-on-property-readjs-",
          versionAdded: null,
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          parameters: [{
            name: "property",
            required: true,
            description: null,
            pattern: null,
            "default": null,
            debug: false
          }]
        }, {
          name: "abort-on-property-read",
          aliases: null,
          description: null,
          docs: "https://help.adblockplus.org/hc/en-us/articles/1500002338501-Snippet-filters-tutorial#snippets-ref",
          versionAdded: "3.4.1",
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          parameters: [{
            name: "property",
            required: true,
            description: null,
            pattern: null,
            "default": null,
            debug: false
          }, {
            name: "setConfigurable",
            required: false,
            description: null,
            pattern: null,
            "default": null,
            debug: false
          }]
        }],
        map: {
          "1": 0,
          "2": 0,
          "4": 0,
          "8": 0,
          "16": 0,
          "32": 0,
          "64": 0,
          "1024": 1,
          "2048": 1,
          "4096": 1,
          "8192": 1,
          "16384": 2,
          "32768": 2,
          "65536": 2,
          "131072": 2
        }
      }, {
        shared: [{
          name: "abort-on-property-write",
          aliases: ["abort-on-property-write.js", "ubo-abort-on-property-write.js", "aopw.js", "ubo-aopw.js", "ubo-abort-on-property-write", "ubo-aopw", "abp-abort-on-property-write"],
          description: null,
          docs: "https://github.com/AdguardTeam/Scriptlets/blob/master/wiki/about-scriptlets.md#abort-on-property-write",
          versionAdded: "1.0.4",
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          parameters: [{
            name: "property",
            required: true,
            description: null,
            pattern: null,
            "default": null,
            debug: false
          }]
        }, {
          name: "abort-on-property-write.js",
          aliases: ["aopw.js"],
          description: null,
          docs: "https://github.com/gorhill/uBlock/wiki/Resources-Library#abort-on-property-writejs-",
          versionAdded: null,
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          parameters: [{
            name: "property",
            required: true,
            description: null,
            pattern: null,
            "default": null,
            debug: false
          }]
        }, {
          name: "abort-on-property-write",
          aliases: null,
          description: null,
          docs: "https://help.adblockplus.org/hc/en-us/articles/1500002338501-Snippet-filters-tutorial#snippets-ref",
          versionAdded: "3.4.3",
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          parameters: [{
            name: "property",
            required: true,
            description: null,
            pattern: null,
            "default": null,
            debug: false
          }, {
            name: "setConfigurable",
            required: false,
            description: null,
            pattern: null,
            "default": null,
            debug: false
          }]
        }],
        map: {
          "1": 0,
          "2": 0,
          "4": 0,
          "8": 0,
          "16": 0,
          "32": 0,
          "64": 0,
          "1024": 1,
          "2048": 1,
          "4096": 1,
          "8192": 1,
          "16384": 2,
          "32768": 2,
          "65536": 2,
          "131072": 2
        }
      }, {
        shared: [{
          name: "abort-on-stack-trace",
          aliases: ["abort-on-stack-trace.js", "ubo-abort-on-stack-trace.js", "aost.js", "ubo-aost.js", "ubo-abort-on-stack-trace", "ubo-aost", "abp-abort-on-stack-trace"],
          description: null,
          docs: "https://github.com/AdguardTeam/Scriptlets/blob/master/wiki/about-scriptlets.md#abort-on-stack-trace",
          versionAdded: "1.5.0",
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          parameters: [{
            name: "property",
            required: true,
            description: null,
            pattern: null,
            "default": null,
            debug: false
          }, {
            name: "stack",
            required: true,
            description: null,
            pattern: null,
            "default": null,
            debug: false
          }]
        }, {
          name: "abort-on-stack-trace.js",
          aliases: ["aost.js"],
          description: null,
          docs: "https://github.com/gorhill/uBlock/wiki/Resources-Library#abort-on-stack-tracejs-",
          versionAdded: "1.29.3rc9",
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          parameters: [{
            name: "property",
            required: true,
            description: null,
            pattern: null,
            "default": null,
            debug: false
          }, {
            name: "stack",
            required: true,
            description: null,
            pattern: null,
            "default": null,
            debug: false
          }]
        }],
        map: {
          "1": 0,
          "2": 0,
          "4": 0,
          "8": 0,
          "16": 0,
          "32": 0,
          "64": 0,
          "1024": 1,
          "2048": 1,
          "4096": 1,
          "8192": 1
        }
      }, {
        shared: [{
          name: "adjust-setInterval",
          aliases: ["nano-setInterval-booster.js", "ubo-nano-setInterval-booster.js", "nano-sib.js", "ubo-nano-sib.js", "adjust-setInterval.js", "ubo-adjust-setInterval.js", "ubo-nano-setInterval-booster", "ubo-nano-sib", "ubo-adjust-setInterval"],
          description: null,
          docs: "https://github.com/AdguardTeam/Scriptlets/blob/master/wiki/about-scriptlets.md#adjust-setInterval",
          versionAdded: "1.0.4",
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          parameters: [{
            name: "matchCallback",
            required: false,
            description: null,
            pattern: null,
            "default": null,
            debug: false
          }, {
            name: "matchDelay",
            required: false,
            description: null,
            pattern: null,
            "default": null,
            debug: false
          }, {
            name: "boost",
            required: false,
            description: null,
            pattern: null,
            "default": null,
            debug: false
          }]
        }, {
          name: "adjust-setInterval.js",
          aliases: ["nano-setInterval-booster.js", "nano-sib.js"],
          description: null,
          docs: "https://github.com/gorhill/uBlock/wiki/Resources-Library#adjust-setIntervaljs-",
          versionAdded: null,
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          parameters: [{
            name: "matchCallback",
            required: false,
            description: null,
            pattern: null,
            "default": null,
            debug: false
          }, {
            name: "matchDelay",
            required: false,
            description: null,
            pattern: null,
            "default": null,
            debug: false
          }, {
            name: "boost",
            required: false,
            description: null,
            pattern: null,
            "default": null,
            debug: false
          }]
        }],
        map: {
          "1": 0,
          "2": 0,
          "4": 0,
          "8": 0,
          "16": 0,
          "32": 0,
          "64": 0,
          "1024": 1,
          "2048": 1,
          "4096": 1,
          "8192": 1
        }
      }, {
        shared: [{
          name: "adjust-setTimeout",
          aliases: ["adjust-setTimeout.js", "ubo-adjust-setTimeout.js", "nano-setTimeout-booster.js", "ubo-nano-setTimeout-booster.js", "nano-stb.js", "ubo-nano-stb.js", "ubo-adjust-setTimeout", "ubo-nano-setTimeout-booster", "ubo-nano-stb"],
          description: null,
          docs: "https://github.com/AdguardTeam/Scriptlets/blob/master/wiki/about-scriptlets.md#adjust-setTimeout",
          versionAdded: "1.0.4",
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          parameters: [{
            name: "matchCallback",
            required: false,
            description: null,
            pattern: null,
            "default": null,
            debug: false
          }, {
            name: "matchDelay",
            required: false,
            description: null,
            pattern: null,
            "default": null,
            debug: false
          }, {
            name: "boost",
            required: false,
            description: null,
            pattern: null,
            "default": null,
            debug: false
          }]
        }, {
          name: "adjust-setTimeout.js",
          aliases: ["nano-setTimeout-booster.js", "nano-stb.js"],
          description: null,
          docs: "https://github.com/gorhill/uBlock/wiki/Resources-Library#adjust-setTimeoutjs-",
          versionAdded: null,
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          parameters: [{
            name: "matchCallback",
            required: false,
            description: null,
            pattern: null,
            "default": null,
            debug: false
          }, {
            name: "matchDelay",
            required: false,
            description: null,
            pattern: null,
            "default": null,
            debug: false
          }, {
            name: "boost",
            required: false,
            description: null,
            pattern: null,
            "default": null,
            debug: false
          }]
        }],
        map: {
          "1": 0,
          "2": 0,
          "4": 0,
          "8": 0,
          "16": 0,
          "32": 0,
          "64": 0,
          "1024": 1,
          "2048": 1,
          "4096": 1,
          "8192": 1
        }
      }, {
        shared: [{
          name: "amazon-apstag",
          aliases: ["ubo-amazon_apstag.js", "amazon_apstag.js"],
          description: null,
          docs: "https://github.com/AdguardTeam/Scriptlets/blob/master/wiki/about-scriptlets.md#amazon-apstag",
          versionAdded: "1.10.25",
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null
        }],
        map: {
          "1": 0,
          "2": 0,
          "4": 0,
          "8": 0,
          "16": 0,
          "32": 0,
          "64": 0
        }
      }, {
        shared: [{
          name: "call-nothrow",
          aliases: ["call-nothrow.js", "ubo-call-nothrow.js", "ubo-call-nothrow"],
          description: null,
          docs: "https://github.com/AdguardTeam/Scriptlets/blob/master/wiki/about-scriptlets.md#call-nothrow",
          versionAdded: "1.10.1",
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          parameters: [{
            name: "functionName",
            required: true,
            description: null,
            pattern: null,
            "default": null,
            debug: false
          }]
        }, {
          name: "call-nothrow.js",
          aliases: null,
          description: null,
          docs: "https://github.com/gorhill/uBlock/wiki/Resources-Library#call-nothrowjs-",
          versionAdded: "1.48.1b0",
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          parameters: [{
            name: "functionName",
            required: true,
            description: null,
            pattern: null,
            "default": null,
            debug: false
          }]
        }],
        map: {
          "1": 0,
          "2": 0,
          "4": 0,
          "8": 0,
          "16": 0,
          "32": 0,
          "64": 0,
          "1024": 1,
          "2048": 1,
          "4096": 1,
          "8192": 1
        }
      }, {
        shared: [{
          name: "close-window",
          aliases: ["window-close-if.js", "ubo-window-close-if.js", "ubo-window-close-if", "close-window.js", "ubo-close-window.js", "ubo-close-window"],
          description: null,
          docs: "https://github.com/AdguardTeam/Scriptlets/blob/master/wiki/about-scriptlets.md#close-window",
          versionAdded: "1.5.0",
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          parameters: [{
            name: "path",
            required: false,
            description: null,
            pattern: null,
            "default": null,
            debug: false
          }]
        }, {
          name: "close-window.js",
          aliases: ["window-close-if.js"],
          description: null,
          docs: "https://github.com/gorhill/uBlock/wiki/Resources-Library#close-windowjs-",
          versionAdded: "1.39.3b10",
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          parameters: [{
            name: "path",
            required: false,
            description: null,
            pattern: null,
            "default": null,
            debug: false
          }]
        }],
        map: {
          "1": 0,
          "2": 0,
          "4": 0,
          "8": 0,
          "16": 0,
          "32": 0,
          "64": 0,
          "1024": 1,
          "2048": 1,
          "4096": 1,
          "8192": 1
        }
      }, {
        shared: [{
          name: "debug-current-inline-script",
          aliases: null,
          description: null,
          docs: "https://github.com/AdguardTeam/Scriptlets/blob/master/wiki/about-scriptlets.md#debug-current-inline-script",
          versionAdded: "1.0.4",
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          parameters: [{
            name: "property",
            required: true,
            description: null,
            pattern: null,
            "default": null,
            debug: false
          }, {
            name: "search",
            required: false,
            description: null,
            pattern: null,
            "default": null,
            debug: false
          }]
        }],
        map: {
          "1": 0,
          "2": 0,
          "4": 0,
          "8": 0,
          "16": 0,
          "32": 0,
          "64": 0
        }
      }, {
        shared: [{
          name: "debug-on-property-read",
          aliases: null,
          description: null,
          docs: "https://github.com/AdguardTeam/Scriptlets/blob/master/wiki/about-scriptlets.md#debug-on-property-read",
          versionAdded: "1.0.4",
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          parameters: [{
            name: "property",
            required: true,
            description: null,
            pattern: null,
            "default": null,
            debug: false
          }]
        }],
        map: {
          "1": 0,
          "2": 0,
          "4": 0,
          "8": 0,
          "16": 0,
          "32": 0,
          "64": 0
        }
      }, {
        shared: [{
          name: "debug-on-property-write",
          aliases: null,
          description: null,
          docs: "https://github.com/AdguardTeam/Scriptlets/blob/master/wiki/about-scriptlets.md#debug-on-property-write",
          versionAdded: "1.0.4",
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          parameters: [{
            name: "property",
            required: true,
            description: null,
            pattern: null,
            "default": null,
            debug: false
          }]
        }],
        map: {
          "1": 0,
          "2": 0,
          "4": 0,
          "8": 0,
          "16": 0,
          "32": 0,
          "64": 0
        }
      }, {
        shared: [{
          name: "didomi-loader",
          aliases: null,
          description: null,
          docs: "https://github.com/AdguardTeam/Scriptlets/blob/master/wiki/about-scriptlets.md#didomi-loader",
          versionAdded: "1.10.25",
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null
        }],
        map: {
          "1": 0,
          "2": 0,
          "4": 0,
          "8": 0,
          "16": 0,
          "32": 0,
          "64": 0
        }
      }, {
        shared: [{
          name: "dir-string",
          aliases: null,
          description: null,
          docs: "https://github.com/AdguardTeam/Scriptlets/blob/master/wiki/about-scriptlets.md#dir-string",
          versionAdded: "1.0.4",
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          parameters: [{
            name: "times",
            required: false,
            description: null,
            pattern: null,
            "default": null,
            debug: false
          }]
        }],
        map: {
          "1": 0,
          "2": 0,
          "4": 0,
          "8": 0,
          "16": 0,
          "32": 0,
          "64": 0
        }
      }, {
        shared: [{
          name: "disable-newtab-links",
          aliases: ["disable-newtab-links.js", "ubo-disable-newtab-links.js", "ubo-disable-newtab-links"],
          description: null,
          docs: "https://github.com/AdguardTeam/Scriptlets/blob/master/wiki/about-scriptlets.md#disable-newtab-links",
          versionAdded: "1.0.4",
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null
        }, {
          name: "disable-newtab-links.js",
          aliases: null,
          description: null,
          docs: "https://github.com/gorhill/uBlock/wiki/Resources-Library#disable-newtab-linksjs-",
          versionAdded: null,
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null
        }],
        map: {
          "1": 0,
          "2": 0,
          "4": 0,
          "8": 0,
          "16": 0,
          "32": 0,
          "64": 0,
          "1024": 1,
          "2048": 1,
          "4096": 1,
          "8192": 1
        }
      }, {
        shared: [{
          name: "evaldata-prune",
          aliases: ["evaldata-prune.js", "ubo-evaldata-prune.js", "ubo-evaldata-prune"],
          description: null,
          docs: "https://github.com/AdguardTeam/Scriptlets/blob/master/wiki/about-scriptlets.md#evaldata-prune",
          versionAdded: "1.9.37",
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          parameters: [{
            name: "propsToRemove",
            required: false,
            description: null,
            pattern: null,
            "default": null,
            debug: false
          }, {
            name: "obligatoryProps",
            required: false,
            description: null,
            pattern: null,
            "default": null,
            debug: false
          }, {
            name: "stack",
            required: false,
            description: null,
            pattern: null,
            "default": null,
            debug: false
          }]
        }, {
          name: "evaldata-prune.js",
          aliases: null,
          description: null,
          docs: "https://github.com/gorhill/uBlock/wiki/Resources-Library#evaldata-prunejs-",
          versionAdded: "1.49.3rc15",
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          parameters: [{
            name: "propsToRemove",
            required: false,
            description: null,
            pattern: null,
            "default": null,
            debug: false
          }, {
            name: "obligatoryProps",
            required: false,
            description: null,
            pattern: null,
            "default": null,
            debug: false
          }, {
            name: "stack",
            required: false,
            description: null,
            pattern: null,
            "default": null,
            debug: false
          }]
        }],
        map: {
          "1": 0,
          "2": 0,
          "4": 0,
          "8": 0,
          "16": 0,
          "32": 0,
          "64": 0,
          "1024": 1,
          "2048": 1,
          "4096": 1,
          "8192": 1
        }
      }, {
        shared: [{
          name: "fingerprintjs2",
          aliases: ["ubo-fingerprint2.js", "fingerprint2.js"],
          description: null,
          docs: "https://github.com/AdguardTeam/Scriptlets/blob/master/wiki/about-scriptlets.md#fingerprintjs2",
          versionAdded: "1.10.25",
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null
        }],
        map: {
          "1": 0,
          "2": 0,
          "4": 0,
          "8": 0,
          "16": 0,
          "32": 0,
          "64": 0
        }
      }, {
        shared: [{
          name: "fingerprintjs3",
          aliases: ["ubo-fingerprint3.js", "fingerprint3.js"],
          description: null,
          docs: "https://github.com/AdguardTeam/Scriptlets/blob/master/wiki/about-scriptlets.md#fingerprintjs3",
          versionAdded: "1.10.25",
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null
        }],
        map: {
          "1": 0,
          "2": 0,
          "4": 0,
          "8": 0,
          "16": 0,
          "32": 0,
          "64": 0
        }
      }, {
        shared: [{
          name: "gemius",
          aliases: null,
          description: null,
          docs: "https://github.com/AdguardTeam/Scriptlets/blob/master/wiki/about-scriptlets.md#gemius",
          versionAdded: "1.10.25",
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null
        }],
        map: {
          "1": 0,
          "2": 0,
          "4": 0,
          "8": 0,
          "16": 0,
          "32": 0,
          "64": 0
        }
      }, {
        shared: [{
          name: "google-analytics-ga",
          aliases: ["ubo-google-analytics_ga.js", "google-analytics_ga.js"],
          description: null,
          docs: "https://github.com/AdguardTeam/Scriptlets/blob/master/wiki/about-scriptlets.md#google-analytics-ga",
          versionAdded: "1.10.25",
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null
        }],
        map: {
          "1": 0,
          "2": 0,
          "4": 0,
          "8": 0,
          "16": 0,
          "32": 0,
          "64": 0
        }
      }, {
        shared: [{
          name: "google-analytics",
          aliases: ["ubo-google-analytics_analytics.js", "google-analytics_analytics.js", "googletagmanager-gtm", "ubo-googletagmanager_gtm.js", "googletagmanager_gtm.js"],
          description: null,
          docs: "https://github.com/AdguardTeam/Scriptlets/blob/master/wiki/about-scriptlets.md#google-analytics",
          versionAdded: "1.10.25",
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null
        }],
        map: {
          "1": 0,
          "2": 0,
          "4": 0,
          "8": 0,
          "16": 0,
          "32": 0,
          "64": 0
        }
      }, {
        shared: [{
          name: "google-ima3",
          aliases: ["ubo-google-ima.js", "google-ima.js"],
          description: null,
          docs: "https://github.com/AdguardTeam/Scriptlets/blob/master/wiki/about-scriptlets.md#google-ima3",
          versionAdded: "1.10.25",
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null
        }],
        map: {
          "1": 0,
          "2": 0,
          "4": 0,
          "8": 0,
          "16": 0,
          "32": 0,
          "64": 0
        }
      }, {
        shared: [{
          name: "googlesyndication-adsbygoogle",
          aliases: ["ubo-googlesyndication_adsbygoogle.js", "googlesyndication_adsbygoogle.js"],
          description: null,
          docs: "https://github.com/AdguardTeam/Scriptlets/blob/master/wiki/about-scriptlets.md#googlesyndication-adsbygoogle",
          versionAdded: "1.10.25",
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null
        }],
        map: {
          "1": 0,
          "2": 0,
          "4": 0,
          "8": 0,
          "16": 0,
          "32": 0,
          "64": 0
        }
      }, {
        shared: [{
          name: "googletagservices-gpt",
          aliases: ["ubo-googletagservices_gpt.js", "googletagservices_gpt.js"],
          description: null,
          docs: "https://github.com/AdguardTeam/Scriptlets/blob/master/wiki/about-scriptlets.md#googletagservices-gpt",
          versionAdded: "1.10.25",
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null
        }],
        map: {
          "1": 0,
          "2": 0,
          "4": 0,
          "8": 0,
          "16": 0,
          "32": 0,
          "64": 0
        }
      }, {
        shared: [{
          name: "hide-in-shadow-dom",
          aliases: null,
          description: null,
          docs: "https://github.com/AdguardTeam/Scriptlets/blob/master/wiki/about-scriptlets.md#hide-in-shadow-dom",
          versionAdded: "1.3.0",
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          parameters: [{
            name: "selector",
            required: true,
            description: null,
            pattern: null,
            "default": null,
            debug: false
          }, {
            name: "baseSelector",
            required: false,
            description: null,
            pattern: null,
            "default": null,
            debug: false
          }]
        }],
        map: {
          "1": 0,
          "2": 0,
          "4": 0,
          "8": 0,
          "16": 0,
          "32": 0,
          "64": 0
        }
      }, {
        shared: [{
          name: "href-sanitizer",
          aliases: ["href-sanitizer.js", "ubo-href-sanitizer.js", "ubo-href-sanitizer"],
          description: null,
          docs: "https://github.com/AdguardTeam/Scriptlets/blob/master/wiki/about-scriptlets.md#href-sanitizer",
          versionAdded: "1.10.25",
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          parameters: [{
            name: "selector",
            required: true,
            description: null,
            pattern: null,
            "default": null,
            debug: false
          }, {
            name: "attribute",
            required: false,
            description: null,
            pattern: null,
            "default": null,
            debug: false
          }]
        }, {
          name: "href-sanitizer.js",
          aliases: null,
          description: null,
          docs: "https://github.com/gorhill/uBlock/wiki/Resources-Library#href-sanitizerjs-",
          versionAdded: "1.47.5b4",
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          parameters: [{
            name: "selector",
            required: true,
            description: null,
            pattern: null,
            "default": null,
            debug: false
          }, {
            name: "attribute",
            required: false,
            description: null,
            pattern: null,
            "default": null,
            debug: false
          }]
        }],
        map: {
          "1": 0,
          "2": 0,
          "4": 0,
          "8": 0,
          "16": 0,
          "32": 0,
          "64": 0,
          "1024": 1,
          "2048": 1,
          "4096": 1,
          "8192": 1
        }
      }, {
        shared: [{
          name: "inject-css-in-shadow-dom",
          aliases: null,
          description: null,
          docs: "https://github.com/AdguardTeam/Scriptlets/blob/master/wiki/about-scriptlets.md#inject-css-in-shadow-dom",
          versionAdded: "1.8.2",
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          parameters: [{
            name: "cssRule",
            required: true,
            description: null,
            pattern: null,
            "default": null,
            debug: false
          }, {
            name: "hostSelector",
            required: false,
            description: null,
            pattern: null,
            "default": null,
            debug: false
          }]
        }],
        map: {
          "1": 0,
          "2": 0,
          "4": 0,
          "8": 0,
          "16": 0,
          "32": 0,
          "64": 0
        }
      }, {
        shared: [{
          name: "json-prune-fetch-response",
          aliases: ["json-prune-fetch-response.js", "ubo-json-prune-fetch-response.js", "ubo-json-prune-fetch-response"],
          description: null,
          docs: "https://github.com/AdguardTeam/Scriptlets/blob/master/wiki/about-scriptlets.md#json-prune-fetch-response",
          versionAdded: "1.10.25",
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          parameters: [{
            name: "propsToRemove",
            required: false,
            description: null,
            pattern: null,
            "default": null,
            debug: false
          }, {
            name: "obligatoryProps",
            required: false,
            description: null,
            pattern: null,
            "default": null,
            debug: false
          }, {
            name: "propsToMatch",
            required: false,
            description: null,
            pattern: null,
            "default": null,
            debug: false
          }, {
            name: "stack",
            required: false,
            description: null,
            pattern: null,
            "default": null,
            debug: false
          }]
        }, {
          name: "json-prune-fetch-response.js",
          aliases: null,
          description: null,
          docs: "https://github.com/gorhill/uBlock/wiki/Resources-Library#json-prune-fetch-responsejs-",
          versionAdded: null,
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          parameters: [{
            name: "propsToRemove",
            required: false,
            description: null,
            pattern: null,
            "default": null,
            debug: false
          }, {
            name: "obligatoryProps",
            required: false,
            description: null,
            pattern: null,
            "default": null,
            debug: false
          }, {
            name: "propsToMatch",
            required: false,
            description: null,
            pattern: null,
            "default": null,
            debug: false
          }, {
            name: "stack",
            required: false,
            description: null,
            pattern: null,
            "default": null,
            debug: false
          }]
        }],
        map: {
          "1": 0,
          "2": 0,
          "4": 0,
          "8": 0,
          "16": 0,
          "32": 0,
          "64": 0,
          "1024": 1,
          "2048": 1,
          "4096": 1,
          "8192": 1
        }
      }, {
        shared: [{
          name: "json-prune-xhr-response",
          aliases: ["json-prune-xhr-response.js", "ubo-json-prune-xhr-response.js", "ubo-json-prune-xhr-response"],
          description: null,
          docs: "https://github.com/AdguardTeam/Scriptlets/blob/master/wiki/about-scriptlets.md#json-prune-xhr-response",
          versionAdded: "1.10.25",
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          parameters: [{
            name: "propsToRemove",
            required: false,
            description: null,
            pattern: null,
            "default": null,
            debug: false
          }, {
            name: "obligatoryProps",
            required: false,
            description: null,
            pattern: null,
            "default": null,
            debug: false
          }, {
            name: "propsToMatch",
            required: false,
            description: null,
            pattern: null,
            "default": null,
            debug: false
          }, {
            name: "stack",
            required: false,
            description: null,
            pattern: null,
            "default": null,
            debug: false
          }]
        }, {
          name: "json-prune-xhr-response.js",
          aliases: null,
          description: null,
          docs: "https://github.com/gorhill/uBlock/wiki/Resources-Library#json-prune-xhr-responsejs-",
          versionAdded: null,
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          parameters: [{
            name: "propsToRemove",
            required: false,
            description: null,
            pattern: null,
            "default": null,
            debug: false
          }, {
            name: "obligatoryProps",
            required: false,
            description: null,
            pattern: null,
            "default": null,
            debug: false
          }, {
            name: "propsToMatch",
            required: false,
            description: null,
            pattern: null,
            "default": null,
            debug: false
          }, {
            name: "stack",
            required: false,
            description: null,
            pattern: null,
            "default": null,
            debug: false
          }]
        }],
        map: {
          "1": 0,
          "2": 0,
          "4": 0,
          "8": 0,
          "16": 0,
          "32": 0,
          "64": 0,
          "1024": 1,
          "2048": 1,
          "4096": 1,
          "8192": 1
        }
      }, {
        shared: [{
          name: "json-prune",
          aliases: ["json-prune.js", "ubo-json-prune.js", "ubo-json-prune", "abp-json-prune"],
          description: null,
          docs: "https://github.com/AdguardTeam/Scriptlets/blob/master/wiki/about-scriptlets.md#json-prune",
          versionAdded: "1.1.0",
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          parameters: [{
            name: "propsToRemove",
            required: false,
            description: null,
            pattern: null,
            "default": null,
            debug: false
          }, {
            name: "obligatoryProps",
            required: false,
            description: null,
            pattern: null,
            "default": null,
            debug: false
          }, {
            name: "stack",
            required: false,
            description: null,
            pattern: null,
            "default": null,
            debug: false
          }]
        }, {
          name: "json-prune.js",
          aliases: null,
          description: null,
          docs: "https://github.com/gorhill/uBlock/wiki/Resources-Library#json-prunejs-",
          versionAdded: "1.23.0",
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          parameters: [{
            name: "propsToRemove",
            required: false,
            description: null,
            pattern: null,
            "default": null,
            debug: false
          }, {
            name: "obligatoryProps",
            required: false,
            description: null,
            pattern: null,
            "default": null,
            debug: false
          }, {
            name: "stack",
            required: false,
            description: null,
            pattern: null,
            "default": null,
            debug: false
          }]
        }, {
          name: "json-prune",
          aliases: null,
          description: null,
          docs: "https://help.adblockplus.org/hc/en-us/articles/1500002338501-Snippet-filters-tutorial#snippets-ref",
          versionAdded: "3.9.0",
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          parameters: [{
            name: "rawPrunePaths",
            required: true,
            description: null,
            pattern: null,
            "default": null,
            debug: false
          }, {
            name: "rawNeedlePaths",
            required: false,
            description: null,
            pattern: null,
            "default": null,
            debug: false
          }]
        }],
        map: {
          "1": 0,
          "2": 0,
          "4": 0,
          "8": 0,
          "16": 0,
          "32": 0,
          "64": 0,
          "1024": 1,
          "2048": 1,
          "4096": 1,
          "8192": 1,
          "16384": 2,
          "32768": 2,
          "65536": 2,
          "131072": 2
        }
      }, {
        shared: [{
          name: "log-addEventListener",
          aliases: ["addEventListener-logger.js", "ubo-addEventListener-logger.js", "aell.js", "ubo-aell.js", "ubo-addEventListener-logger", "ubo-aell"],
          description: null,
          docs: "https://github.com/AdguardTeam/Scriptlets/blob/master/wiki/about-scriptlets.md#log-addEventListener",
          versionAdded: "1.0.4",
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null
        }],
        map: {
          "1": 0,
          "2": 0,
          "4": 0,
          "8": 0,
          "16": 0,
          "32": 0,
          "64": 0
        }
      }, {
        shared: [{
          name: "log-eval",
          aliases: null,
          description: null,
          docs: "https://github.com/AdguardTeam/Scriptlets/blob/master/wiki/about-scriptlets.md#log-eval",
          versionAdded: "1.0.4",
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null
        }],
        map: {
          "1": 0,
          "2": 0,
          "4": 0,
          "8": 0,
          "16": 0,
          "32": 0,
          "64": 0
        }
      }, {
        shared: [{
          name: "log-on-stack-trace",
          aliases: null,
          description: null,
          docs: "https://github.com/AdguardTeam/Scriptlets/blob/master/wiki/about-scriptlets.md#log-on-stack-trace",
          versionAdded: "1.5.0",
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          parameters: [{
            name: "property",
            required: true,
            description: null,
            pattern: null,
            "default": null,
            debug: false
          }]
        }],
        map: {
          "1": 0,
          "2": 0,
          "4": 0,
          "8": 0,
          "16": 0,
          "32": 0,
          "64": 0
        }
      }, {
        shared: [{
          name: "log",
          aliases: ["abp-log"],
          description: null,
          docs: "https://github.com/AdguardTeam/Scriptlets/blob/master/wiki/about-scriptlets.md#log",
          versionAdded: "1.0.4",
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          parameters: [{
            name: "arguments",
            required: false,
            description: null,
            pattern: null,
            "default": null,
            debug: false
          }]
        }],
        map: {
          "1": 0,
          "2": 0,
          "4": 0,
          "8": 0,
          "16": 0,
          "32": 0,
          "64": 0
        }
      }, {
        shared: [{
          name: "m3u-prune",
          aliases: ["m3u-prune.js", "ubo-m3u-prune.js", "ubo-m3u-prune"],
          description: null,
          docs: "https://github.com/AdguardTeam/Scriptlets/blob/master/wiki/about-scriptlets.md#m3u-prune",
          versionAdded: "1.9.1",
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          parameters: [{
            name: "propsToRemove",
            required: false,
            description: null,
            pattern: null,
            "default": null,
            debug: false
          }, {
            name: "urlToMatch",
            required: false,
            description: null,
            pattern: null,
            "default": null,
            debug: false
          }]
        }, {
          name: "m3u-prune.js",
          aliases: null,
          description: null,
          docs: "https://github.com/gorhill/uBlock/wiki/Resources-Library#m3u-prunejs-",
          versionAdded: "1.44.5b6",
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          parameters: [{
            name: "propsToRemove",
            required: false,
            description: null,
            pattern: null,
            "default": null,
            debug: false
          }, {
            name: "urlToMatch",
            required: false,
            description: null,
            pattern: null,
            "default": null,
            debug: false
          }]
        }],
        map: {
          "1": 0,
          "2": 0,
          "4": 0,
          "8": 0,
          "16": 0,
          "32": 0,
          "64": 0,
          "1024": 1,
          "2048": 1,
          "4096": 1,
          "8192": 1
        }
      }, {
        shared: [{
          name: "matomo",
          aliases: null,
          description: null,
          docs: "https://github.com/AdguardTeam/Scriptlets/blob/master/wiki/about-scriptlets.md#matomo",
          versionAdded: "1.10.25",
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null
        }],
        map: {
          "1": 0,
          "2": 0,
          "4": 0,
          "8": 0,
          "16": 0,
          "32": 0,
          "64": 0
        }
      }, {
        shared: [{
          name: "metrika-yandex-tag",
          aliases: null,
          description: null,
          docs: "https://github.com/AdguardTeam/Scriptlets/blob/master/wiki/about-scriptlets.md#metrika-yandex-tag",
          versionAdded: "1.10.25",
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null
        }],
        map: {
          "1": 0,
          "2": 0,
          "4": 0,
          "8": 0,
          "16": 0,
          "32": 0,
          "64": 0
        }
      }, {
        shared: [{
          name: "metrika-yandex-watch",
          aliases: null,
          description: null,
          docs: "https://github.com/AdguardTeam/Scriptlets/blob/master/wiki/about-scriptlets.md#metrika-yandex-watch",
          versionAdded: "1.10.25",
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null
        }],
        map: {
          "1": 0,
          "2": 0,
          "4": 0,
          "8": 0,
          "16": 0,
          "32": 0,
          "64": 0
        }
      }, {
        shared: [{
          name: "naver-wcslog",
          aliases: null,
          description: null,
          docs: "https://github.com/AdguardTeam/Scriptlets/blob/master/wiki/about-scriptlets.md#naver-wcslog",
          versionAdded: "1.10.25",
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null
        }],
        map: {
          "1": 0,
          "2": 0,
          "4": 0,
          "8": 0,
          "16": 0,
          "32": 0,
          "64": 0
        }
      }, {
        shared: [{
          name: "no-protected-audience",
          aliases: null,
          description: null,
          docs: "https://github.com/AdguardTeam/Scriptlets/blob/master/wiki/about-scriptlets.md#no-protected-audience",
          versionAdded: "1.10.25",
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null
        }],
        map: {
          "1": 0,
          "2": 0,
          "4": 0,
          "8": 0,
          "16": 0,
          "32": 0,
          "64": 0
        }
      }, {
        shared: [{
          name: "no-topics",
          aliases: null,
          description: null,
          docs: "https://github.com/AdguardTeam/Scriptlets/blob/master/wiki/about-scriptlets.md#no-topics",
          versionAdded: "1.6.18",
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null
        }],
        map: {
          "1": 0,
          "2": 0,
          "4": 0,
          "8": 0,
          "16": 0,
          "32": 0,
          "64": 0
        }
      }, {
        shared: [{
          name: "noeval",
          aliases: ["noeval.js", "silent-noeval.js", "ubo-noeval.js", "ubo-silent-noeval.js", "ubo-noeval", "ubo-silent-noeval"],
          description: null,
          docs: "https://github.com/AdguardTeam/Scriptlets/blob/master/wiki/about-scriptlets.md#noeval",
          versionAdded: "1.0.4",
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null
        }],
        map: {
          "1": 0,
          "2": 0,
          "4": 0,
          "8": 0,
          "16": 0,
          "32": 0,
          "64": 0
        }
      }, {
        shared: [{
          name: "nowebrtc",
          aliases: ["nowebrtc.js", "ubo-nowebrtc.js", "ubo-nowebrtc"],
          description: null,
          docs: "https://github.com/AdguardTeam/Scriptlets/blob/master/wiki/about-scriptlets.md#nowebrtc",
          versionAdded: "1.0.4",
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null
        }, {
          name: "nowebrtc.js",
          aliases: null,
          description: null,
          docs: "https://github.com/gorhill/uBlock/wiki/Resources-Library#nowebrtcjs-",
          versionAdded: null,
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null
        }],
        map: {
          "1": 0,
          "2": 0,
          "4": 0,
          "8": 0,
          "16": 0,
          "32": 0,
          "64": 0,
          "1024": 1,
          "2048": 1,
          "4096": 1,
          "8192": 1
        }
      }, {
        shared: [{
          name: "pardot-1.0",
          aliases: null,
          description: null,
          docs: "https://github.com/AdguardTeam/Scriptlets/blob/master/wiki/about-scriptlets.md#pardot-1.0",
          versionAdded: "1.10.25",
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null
        }],
        map: {
          "1": 0,
          "2": 0,
          "4": 0,
          "8": 0,
          "16": 0,
          "32": 0,
          "64": 0
        }
      }, {
        shared: [{
          name: "prebid",
          aliases: null,
          description: null,
          docs: "https://github.com/AdguardTeam/Scriptlets/blob/master/wiki/about-scriptlets.md#prebid",
          versionAdded: "1.10.25",
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null
        }],
        map: {
          "1": 0,
          "2": 0,
          "4": 0,
          "8": 0,
          "16": 0,
          "32": 0,
          "64": 0
        }
      }, {
        shared: [{
          name: "prevent-addEventListener",
          aliases: ["addEventListener-defuser.js", "ubo-addEventListener-defuser.js", "aeld.js", "ubo-aeld.js", "ubo-addEventListener-defuser", "ubo-aeld", "abp-prevent-listener"],
          description: null,
          docs: "https://github.com/AdguardTeam/Scriptlets/blob/master/wiki/about-scriptlets.md#prevent-addEventListener",
          versionAdded: "1.0.4",
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          parameters: [{
            name: "typeSearch",
            required: false,
            description: null,
            pattern: null,
            "default": null,
            debug: false
          }, {
            name: "listenerSearch",
            required: false,
            description: null,
            pattern: null,
            "default": null,
            debug: false
          }]
        }, {
          name: "addEventListener-defuser.js",
          aliases: ["aeld.js", "prevent-addEventListener.js"],
          description: null,
          docs: "https://github.com/gorhill/uBlock/wiki/Resources-Library#addEventListener-defuserjs-",
          versionAdded: null,
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          parameters: [{
            name: "typeSearch",
            required: false,
            description: null,
            pattern: null,
            "default": null,
            debug: false
          }, {
            name: "listenerSearch",
            required: false,
            description: null,
            pattern: null,
            "default": null,
            debug: false
          }]
        }, {
          name: "prevent-listener",
          aliases: null,
          description: null,
          docs: "https://help.adblockplus.org/hc/en-us/articles/1500002338501-Snippet-filters-tutorial#snippets-ref",
          versionAdded: "3.11.2",
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          parameters: [{
            name: "type",
            required: true,
            description: null,
            pattern: null,
            "default": null,
            debug: false
          }, {
            name: "handler",
            required: false,
            description: null,
            pattern: null,
            "default": null,
            debug: false
          }, {
            name: "selector",
            required: false,
            description: null,
            pattern: null,
            "default": null,
            debug: false
          }]
        }],
        map: {
          "1": 0,
          "2": 0,
          "4": 0,
          "8": 0,
          "16": 0,
          "32": 0,
          "64": 0,
          "1024": 1,
          "2048": 1,
          "4096": 1,
          "8192": 1,
          "16384": 2,
          "32768": 2,
          "65536": 2,
          "131072": 2
        }
      }, {
        shared: [{
          name: "prevent-adfly",
          aliases: ["adfly-defuser.js", "ubo-adfly-defuser.js", "ubo-adfly-defuser"],
          description: null,
          docs: "https://github.com/AdguardTeam/Scriptlets/blob/master/wiki/about-scriptlets.md#prevent-adfly",
          versionAdded: "1.0.4",
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null
        }],
        map: {
          "1": 0,
          "2": 0,
          "4": 0,
          "8": 0,
          "16": 0,
          "32": 0,
          "64": 0
        }
      }, {
        shared: [{
          name: "prevent-bab",
          aliases: null,
          description: null,
          docs: "https://github.com/AdguardTeam/Scriptlets/blob/master/wiki/about-scriptlets.md#prevent-bab",
          versionAdded: "1.0.4",
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null
        }],
        map: {
          "1": 0,
          "2": 0,
          "4": 0,
          "8": 0,
          "16": 0,
          "32": 0,
          "64": 0
        }
      }, {
        shared: [{
          name: "prevent-element-src-loading",
          aliases: null,
          description: null,
          docs: "https://github.com/AdguardTeam/Scriptlets/blob/master/wiki/about-scriptlets.md#prevent-element-src-loading",
          versionAdded: "1.6.2",
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          parameters: [{
            name: "tagName",
            required: true,
            description: null,
            pattern: null,
            "default": null,
            debug: false
          }, {
            name: "match",
            required: true,
            description: null,
            pattern: null,
            "default": null,
            debug: false
          }]
        }],
        map: {
          "1": 0,
          "2": 0,
          "4": 0,
          "8": 0,
          "16": 0,
          "32": 0,
          "64": 0
        }
      }, {
        shared: [{
          name: "prevent-eval-if",
          aliases: ["noeval-if.js", "ubo-noeval-if.js", "ubo-noeval-if"],
          description: null,
          docs: "https://github.com/AdguardTeam/Scriptlets/blob/master/wiki/about-scriptlets.md#prevent-eval-if",
          versionAdded: "1.0.4",
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          parameters: [{
            name: "search",
            required: false,
            description: null,
            pattern: null,
            "default": null,
            debug: false
          }]
        }, {
          name: "noeval-if.js",
          aliases: ["prevent-eval-if.js"],
          description: null,
          docs: "https://github.com/gorhill/uBlock/wiki/Resources-Library#noeval-ifjs-",
          versionAdded: null,
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          parameters: [{
            name: "search",
            required: false,
            description: null,
            pattern: null,
            "default": null,
            debug: false
          }]
        }],
        map: {
          "1": 0,
          "2": 0,
          "4": 0,
          "8": 0,
          "16": 0,
          "32": 0,
          "64": 0,
          "1024": 1,
          "2048": 1,
          "4096": 1,
          "8192": 1
        }
      }, {
        shared: [{
          name: "prevent-fab-3.2.0",
          aliases: ["nofab.js", "ubo-nofab.js", "fuckadblock.js-3.2.0", "ubo-fuckadblock.js-3.2.0", "ubo-nofab"],
          description: null,
          docs: "https://github.com/AdguardTeam/Scriptlets/blob/master/wiki/about-scriptlets.md#prevent-fab-3.2.0",
          versionAdded: "1.0.4",
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null
        }],
        map: {
          "1": 0,
          "2": 0,
          "4": 0,
          "8": 0,
          "16": 0,
          "32": 0,
          "64": 0
        }
      }, {
        shared: [{
          name: "prevent-fetch",
          aliases: ["prevent-fetch.js", "no-fetch-if.js", "ubo-no-fetch-if.js", "ubo-no-fetch-if"],
          description: null,
          docs: "https://github.com/AdguardTeam/Scriptlets/blob/master/wiki/about-scriptlets.md#prevent-fetch",
          versionAdded: "1.3.18",
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          parameters: [{
            name: "propsToMatch",
            required: false,
            description: null,
            pattern: null,
            "default": null,
            debug: false
          }, {
            name: "responseBody",
            required: false,
            description: null,
            pattern: null,
            "default": null,
            debug: false
          }, {
            name: "responseType",
            required: false,
            description: null,
            pattern: null,
            "default": null,
            debug: false
          }]
        }, {
          name: "prevent-fetch.js",
          aliases: ["no-fetch-if.js"],
          description: null,
          docs: "https://github.com/gorhill/uBlock/wiki/Resources-Library#prevent-fetchjs-",
          versionAdded: "1.31.3b9",
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          parameters: [{
            name: "propsToMatch",
            required: false,
            description: null,
            pattern: null,
            "default": null,
            debug: false
          }, {
            name: "responseBody",
            required: false,
            description: null,
            pattern: null,
            "default": null,
            debug: false
          }, {
            name: "responseType",
            required: false,
            description: null,
            pattern: null,
            "default": null,
            debug: false
          }]
        }],
        map: {
          "1": 0,
          "2": 0,
          "4": 0,
          "8": 0,
          "16": 0,
          "32": 0,
          "64": 0,
          "1024": 1,
          "2048": 1,
          "4096": 1,
          "8192": 1
        }
      }, {
        shared: [{
          name: "prevent-popads-net",
          aliases: ["popads.net.js", "ubo-popads.net.js", "ubo-popads.net"],
          description: null,
          docs: "https://github.com/AdguardTeam/Scriptlets/blob/master/wiki/about-scriptlets.md#prevent-popads-net",
          versionAdded: "1.0.4",
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null
        }],
        map: {
          "1": 0,
          "2": 0,
          "4": 0,
          "8": 0,
          "16": 0,
          "32": 0,
          "64": 0
        }
      }, {
        shared: [{
          name: "prevent-refresh",
          aliases: ["prevent-refresh.js", "refresh-defuser.js", "refresh-defuser", "ubo-prevent-refresh.js", "ubo-prevent-refresh", "ubo-refresh-defuser.js", "ubo-refresh-defuser"],
          description: null,
          docs: "https://github.com/AdguardTeam/Scriptlets/blob/master/wiki/about-scriptlets.md#prevent-refresh",
          versionAdded: "1.6.2",
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          parameters: [{
            name: "delay",
            required: false,
            description: null,
            pattern: null,
            "default": null,
            debug: false
          }]
        }, {
          name: "prevent-refresh.js",
          aliases: ["refresh-defuser.js"],
          description: null,
          docs: "https://github.com/gorhill/uBlock/wiki/Resources-Library#prevent-refreshjs-",
          versionAdded: "1.38.7b3",
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          parameters: [{
            name: "delay",
            required: false,
            description: null,
            pattern: null,
            "default": null,
            debug: false
          }]
        }],
        map: {
          "1": 0,
          "2": 0,
          "4": 0,
          "8": 0,
          "16": 0,
          "32": 0,
          "64": 0,
          "1024": 1,
          "2048": 1,
          "4096": 1,
          "8192": 1
        }
      }, {
        shared: [{
          name: "prevent-requestAnimationFrame",
          aliases: ["no-requestAnimationFrame-if.js", "ubo-no-requestAnimationFrame-if.js", "norafif.js", "ubo-norafif.js", "ubo-no-requestAnimationFrame-if", "ubo-norafif"],
          description: null,
          docs: "https://github.com/AdguardTeam/Scriptlets/blob/master/wiki/about-scriptlets.md#prevent-requestAnimationFrame",
          versionAdded: "1.1.15",
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          parameters: [{
            name: "search",
            required: false,
            description: null,
            pattern: null,
            "default": null,
            debug: false
          }]
        }, {
          name: "no-requestAnimationFrame-if.js",
          aliases: ["norafif.js", "prevent-requestAnimationFrame.js"],
          description: null,
          docs: "https://github.com/gorhill/uBlock/wiki/Resources-Library#no-requestAnimationFrame-ifjs-",
          versionAdded: "1.27.0",
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          parameters: [{
            name: "search",
            required: false,
            description: null,
            pattern: null,
            "default": null,
            debug: false
          }]
        }],
        map: {
          "1": 0,
          "2": 0,
          "4": 0,
          "8": 0,
          "16": 0,
          "32": 0,
          "64": 0,
          "1024": 1,
          "2048": 1,
          "4096": 1,
          "8192": 1
        }
      }, {
        shared: [{
          name: "prevent-setInterval",
          aliases: ["no-setInterval-if.js", "ubo-no-setInterval-if.js", "setInterval-defuser.js", "ubo-setInterval-defuser.js", "nosiif.js", "ubo-nosiif.js", "sid.js", "ubo-sid.js", "ubo-no-setInterval-if", "ubo-setInterval-defuser", "ubo-nosiif", "ubo-sid"],
          description: null,
          docs: "https://github.com/AdguardTeam/Scriptlets/blob/master/wiki/about-scriptlets.md#prevent-setInterval",
          versionAdded: "1.0.4",
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          parameters: [{
            name: "matchCallback",
            required: false,
            description: null,
            pattern: null,
            "default": null,
            debug: false
          }, {
            name: "matchDelay",
            required: false,
            description: null,
            pattern: null,
            "default": null,
            debug: false
          }]
        }, {
          name: "no-setInterval-if.js",
          aliases: ["nosiif.js", "prevent-setInterval.js", "setInterval-defuser.js"],
          description: null,
          docs: "https://github.com/gorhill/uBlock/wiki/Resources-Library#no-setInterval-ifjs-",
          versionAdded: "1.23.0",
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          parameters: [{
            name: "matchCallback",
            required: false,
            description: null,
            pattern: null,
            "default": null,
            debug: false
          }, {
            name: "matchDelay",
            required: false,
            description: null,
            pattern: null,
            "default": null,
            debug: false
          }]
        }],
        map: {
          "1": 0,
          "2": 0,
          "4": 0,
          "8": 0,
          "16": 0,
          "32": 0,
          "64": 0,
          "1024": 1,
          "2048": 1,
          "4096": 1,
          "8192": 1
        }
      }, {
        shared: [{
          name: "prevent-setTimeout",
          aliases: ["no-setTimeout-if.js", "ubo-no-setTimeout-if.js", "nostif.js", "ubo-nostif.js", "ubo-no-setTimeout-if", "ubo-nostif", "setTimeout-defuser.js", "ubo-setTimeout-defuser.js", "ubo-setTimeout-defuser", "std.js", "ubo-std.js", "ubo-std"],
          description: null,
          docs: "https://github.com/AdguardTeam/Scriptlets/blob/master/wiki/about-scriptlets.md#prevent-setTimeout",
          versionAdded: "1.0.4",
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          parameters: [{
            name: "matchCallback",
            required: false,
            description: null,
            pattern: null,
            "default": null,
            debug: false
          }, {
            name: "matchDelay",
            required: false,
            description: null,
            pattern: null,
            "default": null,
            debug: false
          }]
        }, {
          name: "no-setTimeout-if.js",
          aliases: ["nostif.js", "prevent-setTimeout.js", "setTimeout-defuser.js"],
          description: null,
          docs: "https://github.com/gorhill/uBlock/wiki/Resources-Library#no-setTimeout-ifjs-",
          versionAdded: "1.23.0",
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          parameters: [{
            name: "matchCallback",
            required: false,
            description: null,
            pattern: null,
            "default": null,
            debug: false
          }, {
            name: "matchDelay",
            required: false,
            description: null,
            pattern: null,
            "default": null,
            debug: false
          }]
        }],
        map: {
          "1": 0,
          "2": 0,
          "4": 0,
          "8": 0,
          "16": 0,
          "32": 0,
          "64": 0,
          "1024": 1,
          "2048": 1,
          "4096": 1,
          "8192": 1
        }
      }, {
        shared: [{
          name: "prevent-window-open",
          aliases: ["window.open-defuser.js", "ubo-window.open-defuser.js", "ubo-window.open-defuser", "nowoif.js", "ubo-nowoif.js", "ubo-nowoif", "no-window-open-if.js", "ubo-no-window-open-if.js", "ubo-no-window-open-if"],
          description: null,
          docs: "https://github.com/AdguardTeam/Scriptlets/blob/master/wiki/about-scriptlets.md#prevent-window-open",
          versionAdded: "1.0.4",
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          parameters: [{
            name: "match",
            required: false,
            description: null,
            pattern: null,
            "default": null,
            debug: false
          }, {
            name: "delay",
            required: false,
            description: null,
            pattern: null,
            "default": null,
            debug: false
          }, {
            name: "replacement",
            required: false,
            description: null,
            pattern: null,
            "default": null,
            debug: false
          }]
        }, {
          name: "no-window-open-if.js",
          aliases: ["nowoif.js", "prevent-window-open.js", "window.open-defuser.js"],
          description: null,
          docs: "https://github.com/gorhill/uBlock/wiki/Resources-Library#no-window-open-ifjs-",
          versionAdded: null,
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          parameters: [{
            name: "match",
            required: false,
            description: null,
            pattern: null,
            "default": null,
            debug: false
          }, {
            name: "delay",
            required: false,
            description: null,
            pattern: null,
            "default": null,
            debug: false
          }, {
            name: "replacement",
            required: false,
            description: null,
            pattern: null,
            "default": null,
            debug: false
          }]
        }],
        map: {
          "1": 0,
          "2": 0,
          "4": 0,
          "8": 0,
          "16": 0,
          "32": 0,
          "64": 0,
          "1024": 1,
          "2048": 1,
          "4096": 1,
          "8192": 1
        }
      }, {
        shared: [{
          name: "prevent-xhr",
          aliases: ["no-xhr-if.js", "ubo-no-xhr-if.js", "ubo-no-xhr-if"],
          description: null,
          docs: "https://github.com/AdguardTeam/Scriptlets/blob/master/wiki/about-scriptlets.md#prevent-xhr",
          versionAdded: "1.5.0",
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          parameters: [{
            name: "propsToMatch",
            required: false,
            description: null,
            pattern: null,
            "default": null,
            debug: false
          }, {
            name: "randomize",
            required: false,
            description: null,
            pattern: null,
            "default": null,
            debug: false
          }]
        }, {
          name: "no-xhr-if.js",
          aliases: ["prevent-xhr.js"],
          description: null,
          docs: "https://github.com/gorhill/uBlock/wiki/Resources-Library#no-xhr-ifjs-",
          versionAdded: "1.38.0",
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          parameters: [{
            name: "propsToMatch",
            required: false,
            description: null,
            pattern: null,
            "default": null,
            debug: false
          }, {
            name: "randomize",
            required: false,
            description: null,
            pattern: null,
            "default": null,
            debug: false
          }]
        }],
        map: {
          "1": 0,
          "2": 0,
          "4": 0,
          "8": 0,
          "16": 0,
          "32": 0,
          "64": 0,
          "1024": 1,
          "2048": 1,
          "4096": 1,
          "8192": 1
        }
      }, {
        shared: [{
          name: "remove-attr",
          aliases: ["remove-attr.js", "ubo-remove-attr.js", "ra.js", "ubo-ra.js", "ubo-remove-attr", "ubo-ra"],
          description: null,
          docs: "https://github.com/AdguardTeam/Scriptlets/blob/master/wiki/about-scriptlets.md#remove-attr",
          versionAdded: "1.0.4",
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          parameters: [{
            name: "attrs",
            required: true,
            description: null,
            pattern: null,
            "default": null,
            debug: false
          }, {
            name: "selector",
            required: false,
            description: null,
            pattern: null,
            "default": null,
            debug: false
          }, {
            name: "applying",
            required: false,
            description: null,
            pattern: null,
            "default": null,
            debug: false
          }]
        }, {
          name: "remove-attr.js",
          aliases: ["ra.js", "ra", "remove-attr"],
          description: null,
          docs: "https://github.com/gorhill/uBlock/wiki/Resources-Library#remove-attrjs-",
          versionAdded: null,
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          parameters: [{
            name: "attrs",
            required: true,
            description: null,
            pattern: null,
            "default": null,
            debug: false
          }, {
            name: "selector",
            required: false,
            description: null,
            pattern: null,
            "default": null,
            debug: false
          }, {
            name: "applying",
            required: false,
            description: null,
            pattern: null,
            "default": null,
            debug: false
          }]
        }],
        map: {
          "1": 0,
          "2": 0,
          "4": 0,
          "8": 0,
          "16": 0,
          "32": 0,
          "64": 0,
          "1024": 1,
          "2048": 1,
          "4096": 1,
          "8192": 1
        }
      }, {
        shared: [{
          name: "remove-class",
          aliases: ["remove-class.js", "ubo-remove-class.js", "rc.js", "ubo-rc.js", "ubo-remove-class", "ubo-rc"],
          description: null,
          docs: "https://github.com/AdguardTeam/Scriptlets/blob/master/wiki/about-scriptlets.md#remove-class",
          versionAdded: "1.1.1",
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          parameters: [{
            name: "classes",
            required: true,
            description: null,
            pattern: null,
            "default": null,
            debug: false
          }, {
            name: "selector",
            required: false,
            description: null,
            pattern: null,
            "default": null,
            debug: false
          }, {
            name: "applying",
            required: false,
            description: null,
            pattern: null,
            "default": null,
            debug: false
          }]
        }, {
          name: "remove-class.js",
          aliases: ["rc.js", "rc", "remove-class"],
          description: null,
          docs: "https://github.com/gorhill/uBlock/wiki/Resources-Library#remove-classjs-",
          versionAdded: null,
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          parameters: [{
            name: "classes",
            required: true,
            description: null,
            pattern: null,
            "default": null,
            debug: false
          }, {
            name: "selector",
            required: false,
            description: null,
            pattern: null,
            "default": null,
            debug: false
          }, {
            name: "applying",
            required: false,
            description: null,
            pattern: null,
            "default": null,
            debug: false
          }]
        }],
        map: {
          "1": 0,
          "2": 0,
          "4": 0,
          "8": 0,
          "16": 0,
          "32": 0,
          "64": 0,
          "1024": 1,
          "2048": 1,
          "4096": 1,
          "8192": 1
        }
      }, {
        shared: [{
          name: "remove-cookie",
          aliases: ["cookie-remover.js", "ubo-cookie-remover.js", "ubo-cookie-remover", "remove-cookie.js", "ubo-remove-cookie.js", "ubo-remove-cookie", "abp-cookie-remover"],
          description: null,
          docs: "https://github.com/AdguardTeam/Scriptlets/blob/master/wiki/about-scriptlets.md#remove-cookie",
          versionAdded: "1.0.4",
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          parameters: [{
            name: "match",
            required: false,
            description: null,
            pattern: null,
            "default": null,
            debug: false
          }]
        }, {
          name: "remove-cookie.js",
          aliases: ["cookie-remover.js"],
          description: null,
          docs: "https://github.com/gorhill/uBlock/wiki/Resources-Library#remove-cookiejs-",
          versionAdded: "1.28.0",
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          parameters: [{
            name: "match",
            required: false,
            description: null,
            pattern: null,
            "default": null,
            debug: false
          }]
        }, {
          name: "cookie-remover",
          aliases: null,
          description: null,
          docs: "https://help.adblockplus.org/hc/en-us/articles/1500002338501-Snippet-filters-tutorial#snippets-ref",
          versionAdded: "3.11.2",
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          parameters: [{
            name: "cookie",
            required: true,
            description: null,
            pattern: null,
            "default": null,
            debug: false
          }, {
            name: "autoRemoveCookie",
            required: false,
            description: null,
            pattern: null,
            "default": null,
            debug: false
          }]
        }],
        map: {
          "1": 0,
          "2": 0,
          "4": 0,
          "8": 0,
          "16": 0,
          "32": 0,
          "64": 0,
          "1024": 1,
          "2048": 1,
          "4096": 1,
          "8192": 1,
          "16384": 2,
          "32768": 2,
          "65536": 2,
          "131072": 2
        }
      }, {
        shared: [{
          name: "remove-in-shadow-dom",
          aliases: null,
          description: null,
          docs: "https://github.com/AdguardTeam/Scriptlets/blob/master/wiki/about-scriptlets.md#remove-in-shadow-dom",
          versionAdded: "1.3.14",
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          parameters: [{
            name: "selector",
            required: true,
            description: null,
            pattern: null,
            "default": null,
            debug: false
          }, {
            name: "baseSelector",
            required: false,
            description: null,
            pattern: null,
            "default": null,
            debug: false
          }]
        }],
        map: {
          "1": 0,
          "2": 0,
          "4": 0,
          "8": 0,
          "16": 0,
          "32": 0,
          "64": 0
        }
      }, {
        shared: [{
          name: "remove-node-text",
          aliases: ["remove-node-text.js", "ubo-remove-node-text.js", "rmnt.js", "ubo-rmnt.js", "ubo-remove-node-text", "ubo-rmnt"],
          description: null,
          docs: "https://github.com/AdguardTeam/Scriptlets/blob/master/wiki/about-scriptlets.md#remove-node-text",
          versionAdded: "1.9.37",
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          parameters: [{
            name: "nodeName",
            required: true,
            description: null,
            pattern: null,
            "default": null,
            debug: false
          }, {
            name: "textMatch",
            required: true,
            description: null,
            pattern: null,
            "default": null,
            debug: false
          }]
        }, {
          name: "remove-node-text.js",
          aliases: ["rmnt.js"],
          description: null,
          docs: "https://github.com/gorhill/uBlock/wiki/Resources-Library#remove-node-textjs-",
          versionAdded: "1.49.3rc15",
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          parameters: [{
            name: "nodeName",
            required: true,
            description: null,
            pattern: null,
            "default": null,
            debug: false
          }, {
            name: "textMatch",
            required: true,
            description: null,
            pattern: null,
            "default": null,
            debug: false
          }]
        }],
        map: {
          "1": 0,
          "2": 0,
          "4": 0,
          "8": 0,
          "16": 0,
          "32": 0,
          "64": 0,
          "1024": 1,
          "2048": 1,
          "4096": 1,
          "8192": 1
        }
      }, {
        shared: [{
          name: "scorecardresearch-beacon",
          aliases: ["ubo-scorecardresearch_beacon.js", "scorecardresearch_beacon.js"],
          description: null,
          docs: "https://github.com/AdguardTeam/Scriptlets/blob/master/wiki/about-scriptlets.md#scorecardresearch-beacon",
          versionAdded: "1.10.25",
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null
        }],
        map: {
          "1": 0,
          "2": 0,
          "4": 0,
          "8": 0,
          "16": 0,
          "32": 0,
          "64": 0
        }
      }, {
        shared: [{
          name: "set-attr",
          aliases: ["set-attr.js", "ubo-set-attr.js", "ubo-set-attr"],
          description: null,
          docs: "https://github.com/AdguardTeam/Scriptlets/blob/master/wiki/about-scriptlets.md#set-attr",
          versionAdded: "1.5.0",
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          parameters: [{
            name: "selector",
            required: true,
            description: null,
            pattern: null,
            "default": null,
            debug: false
          }, {
            name: "attr",
            required: true,
            description: null,
            pattern: null,
            "default": null,
            debug: false
          }, {
            name: "value",
            required: false,
            description: null,
            pattern: null,
            "default": null,
            debug: false
          }]
        }, {
          name: "set-attr.js",
          aliases: null,
          description: null,
          docs: "https://github.com/gorhill/uBlock/wiki/Resources-Library#set-attrjs-",
          versionAdded: "1.50.1b16",
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          parameters: [{
            name: "selector",
            required: true,
            description: null,
            pattern: null,
            "default": null,
            debug: false
          }, {
            name: "attr",
            required: true,
            description: null,
            pattern: null,
            "default": null,
            debug: false
          }, {
            name: "value",
            required: false,
            description: null,
            pattern: null,
            "default": null,
            debug: false
          }]
        }],
        map: {
          "1": 0,
          "2": 0,
          "4": 0,
          "8": 0,
          "16": 0,
          "32": 0,
          "64": 0,
          "1024": 1,
          "2048": 1,
          "4096": 1,
          "8192": 1
        }
      }, {
        shared: [{
          name: "set-constant",
          aliases: ["set-constant.js", "ubo-set-constant.js", "set.js", "ubo-set.js", "ubo-set-constant", "ubo-set"],
          description: null,
          docs: "https://github.com/AdguardTeam/Scriptlets/blob/master/wiki/about-scriptlets.md#set-constant",
          versionAdded: "1.0.4",
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          parameters: [{
            name: "property",
            required: true,
            description: null,
            pattern: null,
            "default": null,
            debug: false
          }, {
            name: "value",
            required: true,
            description: null,
            pattern: null,
            "default": null,
            debug: false
          }, {
            name: "stack",
            required: false,
            description: null,
            pattern: null,
            "default": null,
            debug: false
          }, {
            name: "valueWrapper",
            required: false,
            description: null,
            pattern: null,
            "default": null,
            debug: false
          }, {
            name: "setProxyTrap",
            required: false,
            description: null,
            pattern: null,
            "default": null,
            debug: false
          }]
        }, {
          name: "set-constant.js",
          aliases: ["set.js"],
          description: null,
          docs: "https://github.com/gorhill/uBlock/wiki/Resources-Library#set-constantjs-",
          versionAdded: null,
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          parameters: [{
            name: "chain",
            required: true,
            description: null,
            pattern: null,
            "default": null,
            debug: false
          }, {
            name: "rawValue",
            required: true,
            description: null,
            pattern: null,
            "default": null,
            debug: false
          }, {
            name: "runAt",
            required: false,
            description: null,
            pattern: null,
            "default": null,
            debug: false
          }]
        }, {
          name: "override-property-read",
          aliases: null,
          description: null,
          docs: "https://help.adblockplus.org/hc/en-us/articles/1500002338501-Snippet-filters-tutorial#snippets-ref",
          versionAdded: "3.9.4",
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          parameters: [{
            name: "property",
            required: true,
            description: null,
            pattern: null,
            "default": null,
            debug: false
          }, {
            name: "value",
            required: true,
            description: null,
            pattern: null,
            "default": null,
            debug: false
          }, {
            name: "setConfigurable",
            required: false,
            description: null,
            pattern: null,
            "default": null,
            debug: false
          }]
        }],
        map: {
          "1": 0,
          "2": 0,
          "4": 0,
          "8": 0,
          "16": 0,
          "32": 0,
          "64": 0,
          "1024": 1,
          "2048": 1,
          "4096": 1,
          "8192": 1,
          "16384": 2,
          "32768": 2,
          "65536": 2,
          "131072": 2
        }
      }, {
        shared: [{
          name: "set-cookie-reload",
          aliases: ["set-cookie-reload.js", "ubo-set-cookie-reload.js", "ubo-set-cookie-reload"],
          description: null,
          docs: "https://github.com/AdguardTeam/Scriptlets/blob/master/wiki/about-scriptlets.md#set-cookie-reload",
          versionAdded: "1.3.14",
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          parameters: [{
            name: "name",
            required: true,
            description: null,
            pattern: null,
            "default": null,
            debug: false
          }, {
            name: "value",
            required: true,
            description: null,
            pattern: null,
            "default": null,
            debug: false
          }, {
            name: "path",
            required: false,
            description: null,
            pattern: null,
            "default": null,
            debug: false
          }, {
            name: "domain",
            required: false,
            description: null,
            pattern: null,
            "default": null,
            debug: false
          }]
        }, {
          name: "set-cookie-reload.js",
          aliases: null,
          description: null,
          docs: "https://github.com/gorhill/uBlock/wiki/Resources-Library#set-cookie-reloadjs-",
          versionAdded: null,
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          parameters: [{
            name: "name",
            required: true,
            description: null,
            pattern: null,
            "default": null,
            debug: false
          }, {
            name: "value",
            required: true,
            description: null,
            pattern: null,
            "default": null,
            debug: false
          }, {
            name: "path",
            required: false,
            description: null,
            pattern: null,
            "default": null,
            debug: false
          }, {
            name: "domain",
            required: false,
            description: null,
            pattern: null,
            "default": null,
            debug: false
          }]
        }],
        map: {
          "1": 0,
          "2": 0,
          "4": 0,
          "8": 0,
          "16": 0,
          "32": 0,
          "64": 0,
          "1024": 1,
          "2048": 1,
          "4096": 1,
          "8192": 1
        }
      }, {
        shared: [{
          name: "set-cookie",
          aliases: ["set-cookie.js", "ubo-set-cookie.js", "ubo-set-cookie"],
          description: null,
          docs: "https://github.com/AdguardTeam/Scriptlets/blob/master/wiki/about-scriptlets.md#set-cookie",
          versionAdded: "1.2.3",
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          parameters: [{
            name: "name",
            required: true,
            description: null,
            pattern: null,
            "default": null,
            debug: false
          }, {
            name: "value",
            required: true,
            description: null,
            pattern: null,
            "default": null,
            debug: false
          }, {
            name: "path",
            required: false,
            description: null,
            pattern: null,
            "default": null,
            debug: false
          }]
        }, {
          name: "set-cookie.js",
          aliases: null,
          description: null,
          docs: "https://github.com/gorhill/uBlock/wiki/Resources-Library#set-cookiejs-",
          versionAdded: "1.50.1b0",
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          parameters: [{
            name: "name",
            required: true,
            description: null,
            pattern: null,
            "default": null,
            debug: false
          }, {
            name: "value",
            required: true,
            description: null,
            pattern: null,
            "default": null,
            debug: false
          }, {
            name: "path",
            required: false,
            description: null,
            pattern: null,
            "default": null,
            debug: false
          }]
        }],
        map: {
          "1": 0,
          "2": 0,
          "4": 0,
          "8": 0,
          "16": 0,
          "32": 0,
          "64": 0,
          "1024": 1,
          "2048": 1,
          "4096": 1,
          "8192": 1
        }
      }, {
        shared: [{
          name: "set-local-storage-item",
          aliases: ["set-local-storage-item.js", "ubo-set-local-storage-item.js", "ubo-set-local-storage-item"],
          description: null,
          docs: "https://github.com/AdguardTeam/Scriptlets/blob/master/wiki/about-scriptlets.md#set-local-storage-item",
          versionAdded: "1.4.3",
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          parameters: [{
            name: "key",
            required: true,
            description: null,
            pattern: null,
            "default": null,
            debug: false
          }, {
            name: "value",
            required: true,
            description: null,
            pattern: null,
            "default": null,
            debug: false
          }]
        }, {
          name: "set-local-storage-item.js",
          aliases: null,
          description: null,
          docs: "https://github.com/gorhill/uBlock/wiki/Resources-Library#set-local-storage-itemjs-",
          versionAdded: "1.50.1b4",
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          parameters: [{
            name: "key",
            required: true,
            description: null,
            pattern: null,
            "default": null,
            debug: false
          }, {
            name: "value",
            required: true,
            description: null,
            pattern: null,
            "default": null,
            debug: false
          }]
        }],
        map: {
          "1": 0,
          "2": 0,
          "4": 0,
          "8": 0,
          "16": 0,
          "32": 0,
          "64": 0,
          "1024": 1,
          "2048": 1,
          "4096": 1,
          "8192": 1
        }
      }, {
        shared: [{
          name: "set-popads-dummy",
          aliases: ["popads-dummy.js", "ubo-popads-dummy.js", "ubo-popads-dummy"],
          description: null,
          docs: "https://github.com/AdguardTeam/Scriptlets/blob/master/wiki/about-scriptlets.md#set-popads-dummy",
          versionAdded: "1.0.4",
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null
        }],
        map: {
          "1": 0,
          "2": 0,
          "4": 0,
          "8": 0,
          "16": 0,
          "32": 0,
          "64": 0
        }
      }, {
        shared: [{
          name: "set-session-storage-item",
          aliases: ["set-session-storage-item.js", "ubo-set-session-storage-item.js", "ubo-set-session-storage-item"],
          description: null,
          docs: "https://github.com/AdguardTeam/Scriptlets/blob/master/wiki/about-scriptlets.md#set-session-storage-item",
          versionAdded: "1.4.3",
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          parameters: [{
            name: "key",
            required: true,
            description: null,
            pattern: null,
            "default": null,
            debug: false
          }, {
            name: "value",
            required: true,
            description: null,
            pattern: null,
            "default": null,
            debug: false
          }]
        }, {
          name: "set-session-storage-item.js",
          aliases: null,
          description: null,
          docs: "https://github.com/gorhill/uBlock/wiki/Resources-Library#set-session-storage-itemjs-",
          versionAdded: "1.50.1b4",
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          parameters: [{
            name: "key",
            required: true,
            description: null,
            pattern: null,
            "default": null,
            debug: false
          }, {
            name: "value",
            required: true,
            description: null,
            pattern: null,
            "default": null,
            debug: false
          }]
        }],
        map: {
          "1": 0,
          "2": 0,
          "4": 0,
          "8": 0,
          "16": 0,
          "32": 0,
          "64": 0,
          "1024": 1,
          "2048": 1,
          "4096": 1,
          "8192": 1
        }
      }, {
        shared: [{
          name: "spoof-css",
          aliases: ["spoof-css.js", "ubo-spoof-css.js", "ubo-spoof-css"],
          description: null,
          docs: "https://github.com/AdguardTeam/Scriptlets/blob/master/wiki/about-scriptlets.md#spoof-css",
          versionAdded: "1.10.1",
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          parameters: [{
            name: "selectors",
            required: true,
            description: null,
            pattern: null,
            "default": null,
            debug: false
          }, {
            name: "cssPropertyName",
            required: true,
            description: null,
            pattern: null,
            "default": null,
            debug: false
          }, {
            name: "cssPropertyValue",
            required: true,
            description: null,
            pattern: null,
            "default": null,
            debug: false
          }]
        }, {
          name: "spoof-css.js",
          aliases: null,
          description: null,
          docs: "https://github.com/gorhill/uBlock/wiki/Resources-Library#spoof-cssjs-",
          versionAdded: null,
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          parameters: [{
            name: "selectors",
            required: true,
            description: null,
            pattern: null,
            "default": null,
            debug: false
          }, {
            name: "cssPropertyName",
            required: true,
            description: null,
            pattern: null,
            "default": null,
            debug: false
          }, {
            name: "cssPropertyValue",
            required: true,
            description: null,
            pattern: null,
            "default": null,
            debug: false
          }, {
            name: "arguments",
            required: false,
            description: null,
            pattern: null,
            "default": null,
            debug: false
          }]
        }],
        map: {
          "1": 0,
          "2": 0,
          "4": 0,
          "8": 0,
          "16": 0,
          "32": 0,
          "64": 0,
          "1024": 1,
          "2048": 1,
          "4096": 1,
          "8192": 1
        }
      }, {
        shared: [{
          name: "trusted-click-element",
          aliases: null,
          description: null,
          docs: null,
          versionAdded: "1.7.3",
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          parameters: [{
            name: "selectors",
            required: true,
            description: null,
            pattern: null,
            "default": null,
            debug: false
          }, {
            name: "extraMatch",
            required: false,
            description: null,
            pattern: null,
            "default": null,
            debug: false
          }, {
            name: "delay",
            required: false,
            description: null,
            pattern: null,
            "default": null,
            debug: false
          }]
        }],
        map: {
          "1": 0,
          "2": 0,
          "4": 0,
          "8": 0,
          "16": 0,
          "32": 0,
          "64": 0
        }
      }, {
        shared: [{
          name: "trusted-create-element",
          aliases: null,
          description: null,
          docs: null,
          versionAdded: "1.10.1",
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          parameters: [{
            name: "parentSelector",
            required: true,
            description: null,
            pattern: null,
            "default": null,
            debug: false
          }, {
            name: "tagName",
            required: true,
            description: null,
            pattern: null,
            "default": null,
            debug: false
          }, {
            name: "attributePairs",
            required: false,
            description: null,
            pattern: null,
            "default": null,
            debug: false
          }, {
            name: "textContent",
            required: false,
            description: null,
            pattern: null,
            "default": null,
            debug: false
          }, {
            name: "cleanupDelayMs",
            required: false,
            description: null,
            pattern: null,
            "default": null,
            debug: false
          }]
        }],
        map: {
          "1": 0,
          "2": 0,
          "4": 0,
          "8": 0,
          "16": 0,
          "32": 0,
          "64": 0
        }
      }, {
        shared: [{
          name: "trusted-dispatch-event",
          aliases: null,
          description: null,
          docs: null,
          versionAdded: null,
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          parameters: [{
            name: "event",
            required: true,
            description: null,
            pattern: null,
            "default": null,
            debug: false
          }, {
            name: "target",
            required: false,
            description: null,
            pattern: null,
            "default": null,
            debug: false
          }]
        }],
        map: {
          "1": 0,
          "2": 0,
          "4": 0,
          "8": 0,
          "16": 0,
          "32": 0,
          "64": 0
        }
      }, {
        shared: [{
          name: "trusted-prune-inbound-object",
          aliases: null,
          description: null,
          docs: null,
          versionAdded: "1.9.91",
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          parameters: [{
            name: "functionName",
            required: true,
            description: null,
            pattern: null,
            "default": null,
            debug: false
          }, {
            name: "propsToRemove",
            required: false,
            description: null,
            pattern: null,
            "default": null,
            debug: false
          }, {
            name: "obligatoryProps",
            required: false,
            description: null,
            pattern: null,
            "default": null,
            debug: false
          }, {
            name: "stack",
            required: false,
            description: null,
            pattern: null,
            "default": null,
            debug: false
          }]
        }],
        map: {
          "1": 0,
          "2": 0,
          "4": 0,
          "8": 0,
          "16": 0,
          "32": 0,
          "64": 0
        }
      }, {
        shared: [{
          name: "trusted-replace-fetch-response",
          aliases: null,
          description: null,
          docs: null,
          versionAdded: "1.7.3",
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          parameters: [{
            name: "pattern",
            required: false,
            description: null,
            pattern: null,
            "default": null,
            debug: false
          }, {
            name: "replacement",
            required: false,
            description: null,
            pattern: null,
            "default": null,
            debug: false
          }, {
            name: "propsToMatch",
            required: false,
            description: null,
            pattern: null,
            "default": null,
            debug: false
          }]
        }],
        map: {
          "1": 0,
          "2": 0,
          "4": 0,
          "8": 0,
          "16": 0,
          "32": 0,
          "64": 0
        }
      }, {
        shared: [{
          name: "trusted-replace-node-text",
          aliases: null,
          description: null,
          docs: null,
          versionAdded: "1.9.37",
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          parameters: [{
            name: "nodeName",
            required: true,
            description: null,
            pattern: null,
            "default": null,
            debug: false
          }, {
            name: "textMatch",
            required: true,
            description: null,
            pattern: null,
            "default": null,
            debug: false
          }, {
            name: "pattern",
            required: true,
            description: null,
            pattern: null,
            "default": null,
            debug: false
          }, {
            name: "replacement",
            required: true,
            description: null,
            pattern: null,
            "default": null,
            debug: false
          }]
        }],
        map: {
          "1": 0,
          "2": 0,
          "4": 0,
          "8": 0,
          "16": 0,
          "32": 0,
          "64": 0
        }
      }, {
        shared: [{
          name: "trusted-replace-xhr-response",
          aliases: null,
          description: null,
          docs: null,
          versionAdded: "1.7.3",
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          parameters: [{
            name: "pattern",
            required: false,
            description: null,
            pattern: null,
            "default": null,
            debug: false
          }, {
            name: "replacement",
            required: false,
            description: null,
            pattern: null,
            "default": null,
            debug: false
          }, {
            name: "propsToMatch",
            required: false,
            description: null,
            pattern: null,
            "default": null,
            debug: false
          }]
        }],
        map: {
          "1": 0,
          "2": 0,
          "4": 0,
          "8": 0,
          "16": 0,
          "32": 0,
          "64": 0
        }
      }, {
        shared: [{
          name: "trusted-set-attr",
          aliases: null,
          description: null,
          docs: null,
          versionAdded: "1.10.1",
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          parameters: [{
            name: "selector",
            required: true,
            description: null,
            pattern: null,
            "default": null,
            debug: false
          }, {
            name: "attr",
            required: true,
            description: null,
            pattern: null,
            "default": null,
            debug: false
          }, {
            name: "value",
            required: false,
            description: null,
            pattern: null,
            "default": null,
            debug: false
          }]
        }],
        map: {
          "1": 0,
          "2": 0,
          "4": 0,
          "8": 0,
          "16": 0,
          "32": 0,
          "64": 0
        }
      }, {
        shared: [{
          name: "trusted-set-constant",
          aliases: null,
          description: null,
          docs: null,
          versionAdded: "1.8.2",
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          parameters: [{
            name: "property",
            required: true,
            description: null,
            pattern: null,
            "default": null,
            debug: false
          }, {
            name: "value",
            required: true,
            description: null,
            pattern: null,
            "default": null,
            debug: false
          }, {
            name: "stack",
            required: false,
            description: null,
            pattern: null,
            "default": null,
            debug: false
          }]
        }],
        map: {
          "1": 0,
          "2": 0,
          "4": 0,
          "8": 0,
          "16": 0,
          "32": 0,
          "64": 0
        }
      }, {
        shared: [{
          name: "trusted-set-cookie-reload",
          aliases: null,
          description: null,
          docs: null,
          versionAdded: "1.7.10",
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          parameters: [{
            name: "name",
            required: true,
            description: null,
            pattern: null,
            "default": null,
            debug: false
          }, {
            name: "value",
            required: true,
            description: null,
            pattern: null,
            "default": null,
            debug: false
          }, {
            name: "offsetExpiresSec",
            required: false,
            description: null,
            pattern: null,
            "default": null,
            debug: false
          }, {
            name: "path",
            required: false,
            description: null,
            pattern: null,
            "default": null,
            debug: false
          }, {
            name: "domain",
            required: false,
            description: null,
            pattern: null,
            "default": null,
            debug: false
          }]
        }],
        map: {
          "1": 0,
          "2": 0,
          "4": 0,
          "8": 0,
          "16": 0,
          "32": 0,
          "64": 0
        }
      }, {
        shared: [{
          name: "trusted-set-cookie",
          aliases: null,
          description: null,
          docs: null,
          versionAdded: "1.7.3",
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          parameters: [{
            name: "name",
            required: true,
            description: null,
            pattern: null,
            "default": null,
            debug: false
          }, {
            name: "value",
            required: true,
            description: null,
            pattern: null,
            "default": null,
            debug: false
          }, {
            name: "offsetExpiresSec",
            required: false,
            description: null,
            pattern: null,
            "default": null,
            debug: false
          }, {
            name: "path",
            required: false,
            description: null,
            pattern: null,
            "default": null,
            debug: false
          }, {
            name: "domain",
            required: false,
            description: null,
            pattern: null,
            "default": null,
            debug: false
          }]
        }],
        map: {
          "1": 0,
          "2": 0,
          "4": 0,
          "8": 0,
          "16": 0,
          "32": 0,
          "64": 0
        }
      }, {
        shared: [{
          name: "trusted-set-local-storage-item",
          aliases: null,
          description: null,
          docs: null,
          versionAdded: "1.7.3",
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          parameters: [{
            name: "key",
            required: true,
            description: null,
            pattern: null,
            "default": null,
            debug: false
          }, {
            name: "value",
            required: true,
            description: null,
            pattern: null,
            "default": null,
            debug: false
          }]
        }],
        map: {
          "1": 0,
          "2": 0,
          "4": 0,
          "8": 0,
          "16": 0,
          "32": 0,
          "64": 0
        }
      }, {
        shared: [{
          name: "trusted-suppress-native-method",
          aliases: null,
          description: null,
          docs: null,
          versionAdded: "1.10.25",
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          parameters: [{
            name: "methodPath",
            required: true,
            description: null,
            pattern: null,
            "default": null,
            debug: false
          }, {
            name: "signatureStr",
            required: true,
            description: null,
            pattern: null,
            "default": null,
            debug: false
          }, {
            name: "how",
            required: false,
            description: null,
            pattern: null,
            "default": null,
            debug: false
          }, {
            name: "stack",
            required: false,
            description: null,
            pattern: null,
            "default": null,
            debug: false
          }]
        }],
        map: {
          "1": 0,
          "2": 0,
          "4": 0,
          "8": 0,
          "16": 0,
          "32": 0,
          "64": 0
        }
      }, {
        shared: [{
          name: "xml-prune",
          aliases: ["xml-prune.js", "ubo-xml-prune.js", "ubo-xml-prune"],
          description: null,
          docs: "https://github.com/AdguardTeam/Scriptlets/blob/master/wiki/about-scriptlets.md#xml-prune",
          versionAdded: "1.7.3",
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          parameters: [{
            name: "propsToMatch",
            required: false,
            description: null,
            pattern: null,
            "default": null,
            debug: false
          }, {
            name: "optionalProp",
            required: false,
            description: null,
            pattern: null,
            "default": null,
            debug: false
          }, {
            name: "urlToMatch",
            required: false,
            description: null,
            pattern: null,
            "default": null,
            debug: false
          }]
        }, {
          name: "xml-prune.js",
          aliases: null,
          description: null,
          docs: "https://github.com/gorhill/uBlock/wiki/Resources-Library#xml-prunejs-",
          versionAdded: "1.49.3rc6",
          versionRemoved: null,
          deprecated: false,
          deprecationMessage: null,
          removed: false,
          removalMessage: null,
          parameters: [{
            name: "propsToMatch",
            required: false,
            description: null,
            pattern: null,
            "default": null,
            debug: false
          }, {
            name: "optionalProp",
            required: false,
            description: null,
            pattern: null,
            "default": null,
            debug: false
          }, {
            name: "urlToMatch",
            required: false,
            description: null,
            pattern: null,
            "default": null,
            debug: false
          }]
        }],
        map: {
          "1": 0,
          "2": 0,
          "4": 0,
          "8": 0,
          "16": 0,
          "32": 0,
          "64": 0,
          "1024": 1,
          "2048": 1,
          "4096": 1,
          "8192": 1
        }
      }],
      map: {
        "abort-current-inline-script": 0,
        "abort-current-script.js": 0,
        "ubo-abort-current-script.js": 0,
        "acs.js": 0,
        "ubo-acs.js": 0,
        "ubo-abort-current-script": 0,
        "ubo-acs": 0,
        "abort-current-inline-script.js": 0,
        "ubo-abort-current-inline-script.js": 0,
        "acis.js": 0,
        "ubo-acis.js": 0,
        "ubo-abort-current-inline-script": 0,
        "ubo-acis": 0,
        "abp-abort-current-inline-script": 0,
        "abort-on-property-read": 1,
        "abort-on-property-read.js": 1,
        "ubo-abort-on-property-read.js": 1,
        "aopr.js": 1,
        "ubo-aopr.js": 1,
        "ubo-abort-on-property-read": 1,
        "ubo-aopr": 1,
        "abp-abort-on-property-read": 1,
        "abort-on-property-write": 2,
        "abort-on-property-write.js": 2,
        "ubo-abort-on-property-write.js": 2,
        "aopw.js": 2,
        "ubo-aopw.js": 2,
        "ubo-abort-on-property-write": 2,
        "ubo-aopw": 2,
        "abp-abort-on-property-write": 2,
        "abort-on-stack-trace": 3,
        "abort-on-stack-trace.js": 3,
        "ubo-abort-on-stack-trace.js": 3,
        "aost.js": 3,
        "ubo-aost.js": 3,
        "ubo-abort-on-stack-trace": 3,
        "ubo-aost": 3,
        "abp-abort-on-stack-trace": 3,
        "adjust-setInterval": 4,
        "nano-setInterval-booster.js": 4,
        "ubo-nano-setInterval-booster.js": 4,
        "nano-sib.js": 4,
        "ubo-nano-sib.js": 4,
        "adjust-setInterval.js": 4,
        "ubo-adjust-setInterval.js": 4,
        "ubo-nano-setInterval-booster": 4,
        "ubo-nano-sib": 4,
        "ubo-adjust-setInterval": 4,
        "adjust-setTimeout": 5,
        "adjust-setTimeout.js": 5,
        "ubo-adjust-setTimeout.js": 5,
        "nano-setTimeout-booster.js": 5,
        "ubo-nano-setTimeout-booster.js": 5,
        "nano-stb.js": 5,
        "ubo-nano-stb.js": 5,
        "ubo-adjust-setTimeout": 5,
        "ubo-nano-setTimeout-booster": 5,
        "ubo-nano-stb": 5,
        "amazon-apstag": 6,
        "ubo-amazon_apstag.js": 6,
        "amazon_apstag.js": 6,
        "call-nothrow": 7,
        "call-nothrow.js": 7,
        "ubo-call-nothrow.js": 7,
        "ubo-call-nothrow": 7,
        "close-window": 8,
        "window-close-if.js": 8,
        "ubo-window-close-if.js": 8,
        "ubo-window-close-if": 8,
        "close-window.js": 8,
        "ubo-close-window.js": 8,
        "ubo-close-window": 8,
        "debug-current-inline-script": 9,
        "debug-on-property-read": 10,
        "debug-on-property-write": 11,
        "didomi-loader": 12,
        "dir-string": 13,
        "disable-newtab-links": 14,
        "disable-newtab-links.js": 14,
        "ubo-disable-newtab-links.js": 14,
        "ubo-disable-newtab-links": 14,
        "evaldata-prune": 15,
        "evaldata-prune.js": 15,
        "ubo-evaldata-prune.js": 15,
        "ubo-evaldata-prune": 15,
        fingerprintjs2: 16,
        "ubo-fingerprint2.js": 16,
        "fingerprint2.js": 16,
        fingerprintjs3: 17,
        "ubo-fingerprint3.js": 17,
        "fingerprint3.js": 17,
        gemius: 18,
        "google-analytics-ga": 19,
        "ubo-google-analytics_ga.js": 19,
        "google-analytics_ga.js": 19,
        "google-analytics": 20,
        "ubo-google-analytics_analytics.js": 20,
        "google-analytics_analytics.js": 20,
        "googletagmanager-gtm": 20,
        "ubo-googletagmanager_gtm.js": 20,
        "googletagmanager_gtm.js": 20,
        "google-ima3": 21,
        "ubo-google-ima.js": 21,
        "google-ima.js": 21,
        "googlesyndication-adsbygoogle": 22,
        "ubo-googlesyndication_adsbygoogle.js": 22,
        "googlesyndication_adsbygoogle.js": 22,
        "googletagservices-gpt": 23,
        "ubo-googletagservices_gpt.js": 23,
        "googletagservices_gpt.js": 23,
        "hide-in-shadow-dom": 24,
        "href-sanitizer": 25,
        "href-sanitizer.js": 25,
        "ubo-href-sanitizer.js": 25,
        "ubo-href-sanitizer": 25,
        "inject-css-in-shadow-dom": 26,
        "json-prune-fetch-response": 27,
        "json-prune-fetch-response.js": 27,
        "ubo-json-prune-fetch-response.js": 27,
        "ubo-json-prune-fetch-response": 27,
        "json-prune-xhr-response": 28,
        "json-prune-xhr-response.js": 28,
        "ubo-json-prune-xhr-response.js": 28,
        "ubo-json-prune-xhr-response": 28,
        "json-prune": 29,
        "json-prune.js": 29,
        "ubo-json-prune.js": 29,
        "ubo-json-prune": 29,
        "abp-json-prune": 29,
        "log-addEventListener": 30,
        "addEventListener-logger.js": 30,
        "ubo-addEventListener-logger.js": 30,
        "aell.js": 30,
        "ubo-aell.js": 30,
        "ubo-addEventListener-logger": 30,
        "ubo-aell": 30,
        "log-eval": 31,
        "log-on-stack-trace": 32,
        log: 33,
        "abp-log": 33,
        "m3u-prune": 34,
        "m3u-prune.js": 34,
        "ubo-m3u-prune.js": 34,
        "ubo-m3u-prune": 34,
        matomo: 35,
        "metrika-yandex-tag": 36,
        "metrika-yandex-watch": 37,
        "naver-wcslog": 38,
        "no-protected-audience": 39,
        "no-topics": 40,
        noeval: 41,
        "noeval.js": 41,
        "silent-noeval.js": 41,
        "ubo-noeval.js": 41,
        "ubo-silent-noeval.js": 41,
        "ubo-noeval": 41,
        "ubo-silent-noeval": 41,
        nowebrtc: 42,
        "nowebrtc.js": 42,
        "ubo-nowebrtc.js": 42,
        "ubo-nowebrtc": 42,
        "pardot-1.0": 43,
        prebid: 44,
        "prevent-addEventListener": 45,
        "addEventListener-defuser.js": 45,
        "ubo-addEventListener-defuser.js": 45,
        "aeld.js": 45,
        "ubo-aeld.js": 45,
        "ubo-addEventListener-defuser": 45,
        "ubo-aeld": 45,
        "abp-prevent-listener": 45,
        "prevent-addEventListener.js": 45,
        "prevent-listener": 45,
        "prevent-adfly": 46,
        "adfly-defuser.js": 46,
        "ubo-adfly-defuser.js": 46,
        "ubo-adfly-defuser": 46,
        "prevent-bab": 47,
        "prevent-element-src-loading": 48,
        "prevent-eval-if": 49,
        "noeval-if.js": 49,
        "ubo-noeval-if.js": 49,
        "ubo-noeval-if": 49,
        "prevent-eval-if.js": 49,
        "prevent-fab-3.2.0": 50,
        "nofab.js": 50,
        "ubo-nofab.js": 50,
        "fuckadblock.js-3.2.0": 50,
        "ubo-fuckadblock.js-3.2.0": 50,
        "ubo-nofab": 50,
        "prevent-fetch": 51,
        "prevent-fetch.js": 51,
        "no-fetch-if.js": 51,
        "ubo-no-fetch-if.js": 51,
        "ubo-no-fetch-if": 51,
        "prevent-popads-net": 52,
        "popads.net.js": 52,
        "ubo-popads.net.js": 52,
        "ubo-popads.net": 52,
        "prevent-refresh": 53,
        "prevent-refresh.js": 53,
        "refresh-defuser.js": 53,
        "refresh-defuser": 53,
        "ubo-prevent-refresh.js": 53,
        "ubo-prevent-refresh": 53,
        "ubo-refresh-defuser.js": 53,
        "ubo-refresh-defuser": 53,
        "prevent-requestAnimationFrame": 54,
        "no-requestAnimationFrame-if.js": 54,
        "ubo-no-requestAnimationFrame-if.js": 54,
        "norafif.js": 54,
        "ubo-norafif.js": 54,
        "ubo-no-requestAnimationFrame-if": 54,
        "ubo-norafif": 54,
        "prevent-requestAnimationFrame.js": 54,
        "prevent-setInterval": 55,
        "no-setInterval-if.js": 55,
        "ubo-no-setInterval-if.js": 55,
        "setInterval-defuser.js": 55,
        "ubo-setInterval-defuser.js": 55,
        "nosiif.js": 55,
        "ubo-nosiif.js": 55,
        "sid.js": 55,
        "ubo-sid.js": 55,
        "ubo-no-setInterval-if": 55,
        "ubo-setInterval-defuser": 55,
        "ubo-nosiif": 55,
        "ubo-sid": 55,
        "prevent-setInterval.js": 55,
        "prevent-setTimeout": 56,
        "no-setTimeout-if.js": 56,
        "ubo-no-setTimeout-if.js": 56,
        "nostif.js": 56,
        "ubo-nostif.js": 56,
        "ubo-no-setTimeout-if": 56,
        "ubo-nostif": 56,
        "setTimeout-defuser.js": 56,
        "ubo-setTimeout-defuser.js": 56,
        "ubo-setTimeout-defuser": 56,
        "std.js": 56,
        "ubo-std.js": 56,
        "ubo-std": 56,
        "prevent-setTimeout.js": 56,
        "prevent-window-open": 57,
        "window.open-defuser.js": 57,
        "ubo-window.open-defuser.js": 57,
        "ubo-window.open-defuser": 57,
        "nowoif.js": 57,
        "ubo-nowoif.js": 57,
        "ubo-nowoif": 57,
        "no-window-open-if.js": 57,
        "ubo-no-window-open-if.js": 57,
        "ubo-no-window-open-if": 57,
        "prevent-window-open.js": 57,
        "prevent-xhr": 58,
        "no-xhr-if.js": 58,
        "ubo-no-xhr-if.js": 58,
        "ubo-no-xhr-if": 58,
        "prevent-xhr.js": 58,
        "remove-attr": 59,
        "remove-attr.js": 59,
        "ubo-remove-attr.js": 59,
        "ra.js": 59,
        "ubo-ra.js": 59,
        "ubo-remove-attr": 59,
        "ubo-ra": 59,
        ra: 59,
        "remove-class": 60,
        "remove-class.js": 60,
        "ubo-remove-class.js": 60,
        "rc.js": 60,
        "ubo-rc.js": 60,
        "ubo-remove-class": 60,
        "ubo-rc": 60,
        rc: 60,
        "remove-cookie": 61,
        "cookie-remover.js": 61,
        "ubo-cookie-remover.js": 61,
        "ubo-cookie-remover": 61,
        "remove-cookie.js": 61,
        "ubo-remove-cookie.js": 61,
        "ubo-remove-cookie": 61,
        "abp-cookie-remover": 61,
        "cookie-remover": 61,
        "remove-in-shadow-dom": 62,
        "remove-node-text": 63,
        "remove-node-text.js": 63,
        "ubo-remove-node-text.js": 63,
        "rmnt.js": 63,
        "ubo-rmnt.js": 63,
        "ubo-remove-node-text": 63,
        "ubo-rmnt": 63,
        "scorecardresearch-beacon": 64,
        "ubo-scorecardresearch_beacon.js": 64,
        "scorecardresearch_beacon.js": 64,
        "set-attr": 65,
        "set-attr.js": 65,
        "ubo-set-attr.js": 65,
        "ubo-set-attr": 65,
        "set-constant": 66,
        "set-constant.js": 66,
        "ubo-set-constant.js": 66,
        "set.js": 66,
        "ubo-set.js": 66,
        "ubo-set-constant": 66,
        "ubo-set": 66,
        "override-property-read": 66,
        "set-cookie-reload": 67,
        "set-cookie-reload.js": 67,
        "ubo-set-cookie-reload.js": 67,
        "ubo-set-cookie-reload": 67,
        "set-cookie": 68,
        "set-cookie.js": 68,
        "ubo-set-cookie.js": 68,
        "ubo-set-cookie": 68,
        "set-local-storage-item": 69,
        "set-local-storage-item.js": 69,
        "ubo-set-local-storage-item.js": 69,
        "ubo-set-local-storage-item": 69,
        "set-popads-dummy": 70,
        "popads-dummy.js": 70,
        "ubo-popads-dummy.js": 70,
        "ubo-popads-dummy": 70,
        "set-session-storage-item": 71,
        "set-session-storage-item.js": 71,
        "ubo-set-session-storage-item.js": 71,
        "ubo-set-session-storage-item": 71,
        "spoof-css": 72,
        "spoof-css.js": 72,
        "ubo-spoof-css.js": 72,
        "ubo-spoof-css": 72,
        "trusted-click-element": 73,
        "trusted-create-element": 74,
        "trusted-dispatch-event": 75,
        "trusted-prune-inbound-object": 76,
        "trusted-replace-fetch-response": 77,
        "trusted-replace-node-text": 78,
        "trusted-replace-xhr-response": 79,
        "trusted-set-attr": 80,
        "trusted-set-constant": 81,
        "trusted-set-cookie-reload": 82,
        "trusted-set-cookie": 83,
        "trusted-set-local-storage-item": 84,
        "trusted-suppress-native-method": 85,
        "xml-prune": 86,
        "xml-prune.js": 86,
        "ubo-xml-prune.js": 86,
        "ubo-xml-prune": 86
      }
    };
    var compatibilityTableData = {
      modifiersCompatibilityTableData: modifiersCompatibilityTableData,
      redirectsCompatibilityTableData: redirectsCompatibilityTableData,
      scriptletsCompatibilityTableData: scriptletsCompatibilityTableData
    };
    compatibilityTableData$1.default = compatibilityTableData;
    var modifiersCompatibilityTableData_1 = compatibilityTableData$1.modifiersCompatibilityTableData = modifiersCompatibilityTableData;
    var redirectsCompatibilityTableData_1 = compatibilityTableData$1.redirectsCompatibilityTableData = redirectsCompatibilityTableData;
    var scriptletsCompatibilityTableData_1 = compatibilityTableData$1.scriptletsCompatibilityTableData = scriptletsCompatibilityTableData;

    var util;
    (function (util) {
        util.assertEqual = (val) => val;
        function assertIs(_arg) { }
        util.assertIs = assertIs;
        function assertNever(_x) {
            throw new Error();
        }
        util.assertNever = assertNever;
        util.arrayToEnum = (items) => {
            const obj = {};
            for (const item of items) {
                obj[item] = item;
            }
            return obj;
        };
        util.getValidEnumValues = (obj) => {
            const validKeys = util.objectKeys(obj).filter((k) => typeof obj[obj[k]] !== "number");
            const filtered = {};
            for (const k of validKeys) {
                filtered[k] = obj[k];
            }
            return util.objectValues(filtered);
        };
        util.objectValues = (obj) => {
            return util.objectKeys(obj).map(function (e) {
                return obj[e];
            });
        };
        util.objectKeys = typeof Object.keys === "function" // eslint-disable-line ban/ban
            ? (obj) => Object.keys(obj) // eslint-disable-line ban/ban
            : (object) => {
                const keys = [];
                for (const key in object) {
                    if (Object.prototype.hasOwnProperty.call(object, key)) {
                        keys.push(key);
                    }
                }
                return keys;
            };
        util.find = (arr, checker) => {
            for (const item of arr) {
                if (checker(item))
                    return item;
            }
            return undefined;
        };
        util.isInteger = typeof Number.isInteger === "function"
            ? (val) => Number.isInteger(val) // eslint-disable-line ban/ban
            : (val) => typeof val === "number" && isFinite(val) && Math.floor(val) === val;
        function joinValues(array, separator = " | ") {
            return array
                .map((val) => (typeof val === "string" ? `'${val}'` : val))
                .join(separator);
        }
        util.joinValues = joinValues;
        util.jsonStringifyReplacer = (_, value) => {
            if (typeof value === "bigint") {
                return value.toString();
            }
            return value;
        };
    })(util || (util = {}));
    var objectUtil;
    (function (objectUtil) {
        objectUtil.mergeShapes = (first, second) => {
            return {
                ...first,
                ...second, // second overwrites first
            };
        };
    })(objectUtil || (objectUtil = {}));
    const ZodParsedType = util.arrayToEnum([
        "string",
        "nan",
        "number",
        "integer",
        "float",
        "boolean",
        "date",
        "bigint",
        "symbol",
        "function",
        "undefined",
        "null",
        "array",
        "object",
        "unknown",
        "promise",
        "void",
        "never",
        "map",
        "set",
    ]);
    const getParsedType = (data) => {
        const t = typeof data;
        switch (t) {
            case "undefined":
                return ZodParsedType.undefined;
            case "string":
                return ZodParsedType.string;
            case "number":
                return isNaN(data) ? ZodParsedType.nan : ZodParsedType.number;
            case "boolean":
                return ZodParsedType.boolean;
            case "function":
                return ZodParsedType.function;
            case "bigint":
                return ZodParsedType.bigint;
            case "symbol":
                return ZodParsedType.symbol;
            case "object":
                if (Array.isArray(data)) {
                    return ZodParsedType.array;
                }
                if (data === null) {
                    return ZodParsedType.null;
                }
                if (data.then &&
                    typeof data.then === "function" &&
                    data.catch &&
                    typeof data.catch === "function") {
                    return ZodParsedType.promise;
                }
                if (typeof Map !== "undefined" && data instanceof Map) {
                    return ZodParsedType.map;
                }
                if (typeof Set !== "undefined" && data instanceof Set) {
                    return ZodParsedType.set;
                }
                if (typeof Date !== "undefined" && data instanceof Date) {
                    return ZodParsedType.date;
                }
                return ZodParsedType.object;
            default:
                return ZodParsedType.unknown;
        }
    };

    const ZodIssueCode = util.arrayToEnum([
        "invalid_type",
        "invalid_literal",
        "custom",
        "invalid_union",
        "invalid_union_discriminator",
        "invalid_enum_value",
        "unrecognized_keys",
        "invalid_arguments",
        "invalid_return_type",
        "invalid_date",
        "invalid_string",
        "too_small",
        "too_big",
        "invalid_intersection_types",
        "not_multiple_of",
        "not_finite",
    ]);
    const quotelessJson = (obj) => {
        const json = JSON.stringify(obj, null, 2);
        return json.replace(/"([^"]+)":/g, "$1:");
    };
    class ZodError extends Error {
        constructor(issues) {
            super();
            this.issues = [];
            this.addIssue = (sub) => {
                this.issues = [...this.issues, sub];
            };
            this.addIssues = (subs = []) => {
                this.issues = [...this.issues, ...subs];
            };
            const actualProto = new.target.prototype;
            if (Object.setPrototypeOf) {
                // eslint-disable-next-line ban/ban
                Object.setPrototypeOf(this, actualProto);
            }
            else {
                this.__proto__ = actualProto;
            }
            this.name = "ZodError";
            this.issues = issues;
        }
        get errors() {
            return this.issues;
        }
        format(_mapper) {
            const mapper = _mapper ||
                function (issue) {
                    return issue.message;
                };
            const fieldErrors = { _errors: [] };
            const processError = (error) => {
                for (const issue of error.issues) {
                    if (issue.code === "invalid_union") {
                        issue.unionErrors.map(processError);
                    }
                    else if (issue.code === "invalid_return_type") {
                        processError(issue.returnTypeError);
                    }
                    else if (issue.code === "invalid_arguments") {
                        processError(issue.argumentsError);
                    }
                    else if (issue.path.length === 0) {
                        fieldErrors._errors.push(mapper(issue));
                    }
                    else {
                        let curr = fieldErrors;
                        let i = 0;
                        while (i < issue.path.length) {
                            const el = issue.path[i];
                            const terminal = i === issue.path.length - 1;
                            if (!terminal) {
                                curr[el] = curr[el] || { _errors: [] };
                                // if (typeof el === "string") {
                                //   curr[el] = curr[el] || { _errors: [] };
                                // } else if (typeof el === "number") {
                                //   const errorArray: any = [];
                                //   errorArray._errors = [];
                                //   curr[el] = curr[el] || errorArray;
                                // }
                            }
                            else {
                                curr[el] = curr[el] || { _errors: [] };
                                curr[el]._errors.push(mapper(issue));
                            }
                            curr = curr[el];
                            i++;
                        }
                    }
                }
            };
            processError(this);
            return fieldErrors;
        }
        toString() {
            return this.message;
        }
        get message() {
            return JSON.stringify(this.issues, util.jsonStringifyReplacer, 2);
        }
        get isEmpty() {
            return this.issues.length === 0;
        }
        flatten(mapper = (issue) => issue.message) {
            const fieldErrors = {};
            const formErrors = [];
            for (const sub of this.issues) {
                if (sub.path.length > 0) {
                    fieldErrors[sub.path[0]] = fieldErrors[sub.path[0]] || [];
                    fieldErrors[sub.path[0]].push(mapper(sub));
                }
                else {
                    formErrors.push(mapper(sub));
                }
            }
            return { formErrors, fieldErrors };
        }
        get formErrors() {
            return this.flatten();
        }
    }
    ZodError.create = (issues) => {
        const error = new ZodError(issues);
        return error;
    };

    const errorMap = (issue, _ctx) => {
        let message;
        switch (issue.code) {
            case ZodIssueCode.invalid_type:
                if (issue.received === ZodParsedType.undefined) {
                    message = "Required";
                }
                else {
                    message = `Expected ${issue.expected}, received ${issue.received}`;
                }
                break;
            case ZodIssueCode.invalid_literal:
                message = `Invalid literal value, expected ${JSON.stringify(issue.expected, util.jsonStringifyReplacer)}`;
                break;
            case ZodIssueCode.unrecognized_keys:
                message = `Unrecognized key(s) in object: ${util.joinValues(issue.keys, ", ")}`;
                break;
            case ZodIssueCode.invalid_union:
                message = `Invalid input`;
                break;
            case ZodIssueCode.invalid_union_discriminator:
                message = `Invalid discriminator value. Expected ${util.joinValues(issue.options)}`;
                break;
            case ZodIssueCode.invalid_enum_value:
                message = `Invalid enum value. Expected ${util.joinValues(issue.options)}, received '${issue.received}'`;
                break;
            case ZodIssueCode.invalid_arguments:
                message = `Invalid function arguments`;
                break;
            case ZodIssueCode.invalid_return_type:
                message = `Invalid function return type`;
                break;
            case ZodIssueCode.invalid_date:
                message = `Invalid date`;
                break;
            case ZodIssueCode.invalid_string:
                if (typeof issue.validation === "object") {
                    if ("includes" in issue.validation) {
                        message = `Invalid input: must include "${issue.validation.includes}"`;
                        if (typeof issue.validation.position === "number") {
                            message = `${message} at one or more positions greater than or equal to ${issue.validation.position}`;
                        }
                    }
                    else if ("startsWith" in issue.validation) {
                        message = `Invalid input: must start with "${issue.validation.startsWith}"`;
                    }
                    else if ("endsWith" in issue.validation) {
                        message = `Invalid input: must end with "${issue.validation.endsWith}"`;
                    }
                    else {
                        util.assertNever(issue.validation);
                    }
                }
                else if (issue.validation !== "regex") {
                    message = `Invalid ${issue.validation}`;
                }
                else {
                    message = "Invalid";
                }
                break;
            case ZodIssueCode.too_small:
                if (issue.type === "array")
                    message = `Array must contain ${issue.exact ? "exactly" : issue.inclusive ? `at least` : `more than`} ${issue.minimum} element(s)`;
                else if (issue.type === "string")
                    message = `String must contain ${issue.exact ? "exactly" : issue.inclusive ? `at least` : `over`} ${issue.minimum} character(s)`;
                else if (issue.type === "number")
                    message = `Number must be ${issue.exact
                    ? `exactly equal to `
                    : issue.inclusive
                        ? `greater than or equal to `
                        : `greater than `}${issue.minimum}`;
                else if (issue.type === "date")
                    message = `Date must be ${issue.exact
                    ? `exactly equal to `
                    : issue.inclusive
                        ? `greater than or equal to `
                        : `greater than `}${new Date(Number(issue.minimum))}`;
                else
                    message = "Invalid input";
                break;
            case ZodIssueCode.too_big:
                if (issue.type === "array")
                    message = `Array must contain ${issue.exact ? `exactly` : issue.inclusive ? `at most` : `less than`} ${issue.maximum} element(s)`;
                else if (issue.type === "string")
                    message = `String must contain ${issue.exact ? `exactly` : issue.inclusive ? `at most` : `under`} ${issue.maximum} character(s)`;
                else if (issue.type === "number")
                    message = `Number must be ${issue.exact
                    ? `exactly`
                    : issue.inclusive
                        ? `less than or equal to`
                        : `less than`} ${issue.maximum}`;
                else if (issue.type === "bigint")
                    message = `BigInt must be ${issue.exact
                    ? `exactly`
                    : issue.inclusive
                        ? `less than or equal to`
                        : `less than`} ${issue.maximum}`;
                else if (issue.type === "date")
                    message = `Date must be ${issue.exact
                    ? `exactly`
                    : issue.inclusive
                        ? `smaller than or equal to`
                        : `smaller than`} ${new Date(Number(issue.maximum))}`;
                else
                    message = "Invalid input";
                break;
            case ZodIssueCode.custom:
                message = `Invalid input`;
                break;
            case ZodIssueCode.invalid_intersection_types:
                message = `Intersection results could not be merged`;
                break;
            case ZodIssueCode.not_multiple_of:
                message = `Number must be a multiple of ${issue.multipleOf}`;
                break;
            case ZodIssueCode.not_finite:
                message = "Number must be finite";
                break;
            default:
                message = _ctx.defaultError;
                util.assertNever(issue);
        }
        return { message };
    };

    let overrideErrorMap = errorMap;
    function setErrorMap(map) {
        overrideErrorMap = map;
    }
    function getErrorMap() {
        return overrideErrorMap;
    }

    const makeIssue = (params) => {
        const { data, path, errorMaps, issueData } = params;
        const fullPath = [...path, ...(issueData.path || [])];
        const fullIssue = {
            ...issueData,
            path: fullPath,
        };
        let errorMessage = "";
        const maps = errorMaps
            .filter((m) => !!m)
            .slice()
            .reverse();
        for (const map of maps) {
            errorMessage = map(fullIssue, { data, defaultError: errorMessage }).message;
        }
        return {
            ...issueData,
            path: fullPath,
            message: issueData.message || errorMessage,
        };
    };
    const EMPTY_PATH = [];
    function addIssueToContext(ctx, issueData) {
        const issue = makeIssue({
            issueData: issueData,
            data: ctx.data,
            path: ctx.path,
            errorMaps: [
                ctx.common.contextualErrorMap,
                ctx.schemaErrorMap,
                getErrorMap(),
                errorMap, // then global default map
            ].filter((x) => !!x),
        });
        ctx.common.issues.push(issue);
    }
    class ParseStatus {
        constructor() {
            this.value = "valid";
        }
        dirty() {
            if (this.value === "valid")
                this.value = "dirty";
        }
        abort() {
            if (this.value !== "aborted")
                this.value = "aborted";
        }
        static mergeArray(status, results) {
            const arrayValue = [];
            for (const s of results) {
                if (s.status === "aborted")
                    return INVALID;
                if (s.status === "dirty")
                    status.dirty();
                arrayValue.push(s.value);
            }
            return { status: status.value, value: arrayValue };
        }
        static async mergeObjectAsync(status, pairs) {
            const syncPairs = [];
            for (const pair of pairs) {
                syncPairs.push({
                    key: await pair.key,
                    value: await pair.value,
                });
            }
            return ParseStatus.mergeObjectSync(status, syncPairs);
        }
        static mergeObjectSync(status, pairs) {
            const finalObject = {};
            for (const pair of pairs) {
                const { key, value } = pair;
                if (key.status === "aborted")
                    return INVALID;
                if (value.status === "aborted")
                    return INVALID;
                if (key.status === "dirty")
                    status.dirty();
                if (value.status === "dirty")
                    status.dirty();
                if (typeof value.value !== "undefined" || pair.alwaysSet) {
                    finalObject[key.value] = value.value;
                }
            }
            return { status: status.value, value: finalObject };
        }
    }
    const INVALID = Object.freeze({
        status: "aborted",
    });
    const DIRTY = (value) => ({ status: "dirty", value });
    const OK = (value) => ({ status: "valid", value });
    const isAborted = (x) => x.status === "aborted";
    const isDirty = (x) => x.status === "dirty";
    const isValid = (x) => x.status === "valid";
    const isAsync = (x) => typeof Promise !== "undefined" && x instanceof Promise;

    var errorUtil;
    (function (errorUtil) {
        errorUtil.errToObj = (message) => typeof message === "string" ? { message } : message || {};
        errorUtil.toString = (message) => typeof message === "string" ? message : message === null || message === void 0 ? void 0 : message.message;
    })(errorUtil || (errorUtil = {}));

    class ParseInputLazyPath {
        constructor(parent, value, path, key) {
            this._cachedPath = [];
            this.parent = parent;
            this.data = value;
            this._path = path;
            this._key = key;
        }
        get path() {
            if (!this._cachedPath.length) {
                if (this._key instanceof Array) {
                    this._cachedPath.push(...this._path, ...this._key);
                }
                else {
                    this._cachedPath.push(...this._path, this._key);
                }
            }
            return this._cachedPath;
        }
    }
    const handleResult = (ctx, result) => {
        if (isValid(result)) {
            return { success: true, data: result.value };
        }
        else {
            if (!ctx.common.issues.length) {
                throw new Error("Validation failed but no issues detected.");
            }
            return {
                success: false,
                get error() {
                    if (this._error)
                        return this._error;
                    const error = new ZodError(ctx.common.issues);
                    this._error = error;
                    return this._error;
                },
            };
        }
    };
    function processCreateParams(params) {
        if (!params)
            return {};
        const { errorMap, invalid_type_error, required_error, description } = params;
        if (errorMap && (invalid_type_error || required_error)) {
            throw new Error(`Can't use "invalid_type_error" or "required_error" in conjunction with custom error map.`);
        }
        if (errorMap)
            return { errorMap: errorMap, description };
        const customMap = (iss, ctx) => {
            if (iss.code !== "invalid_type")
                return { message: ctx.defaultError };
            if (typeof ctx.data === "undefined") {
                return { message: required_error !== null && required_error !== void 0 ? required_error : ctx.defaultError };
            }
            return { message: invalid_type_error !== null && invalid_type_error !== void 0 ? invalid_type_error : ctx.defaultError };
        };
        return { errorMap: customMap, description };
    }
    class ZodType {
        constructor(def) {
            /** Alias of safeParseAsync */
            this.spa = this.safeParseAsync;
            this._def = def;
            this.parse = this.parse.bind(this);
            this.safeParse = this.safeParse.bind(this);
            this.parseAsync = this.parseAsync.bind(this);
            this.safeParseAsync = this.safeParseAsync.bind(this);
            this.spa = this.spa.bind(this);
            this.refine = this.refine.bind(this);
            this.refinement = this.refinement.bind(this);
            this.superRefine = this.superRefine.bind(this);
            this.optional = this.optional.bind(this);
            this.nullable = this.nullable.bind(this);
            this.nullish = this.nullish.bind(this);
            this.array = this.array.bind(this);
            this.promise = this.promise.bind(this);
            this.or = this.or.bind(this);
            this.and = this.and.bind(this);
            this.transform = this.transform.bind(this);
            this.brand = this.brand.bind(this);
            this.default = this.default.bind(this);
            this.catch = this.catch.bind(this);
            this.describe = this.describe.bind(this);
            this.pipe = this.pipe.bind(this);
            this.isNullable = this.isNullable.bind(this);
            this.isOptional = this.isOptional.bind(this);
        }
        get description() {
            return this._def.description;
        }
        _getType(input) {
            return getParsedType(input.data);
        }
        _getOrReturnCtx(input, ctx) {
            return (ctx || {
                common: input.parent.common,
                data: input.data,
                parsedType: getParsedType(input.data),
                schemaErrorMap: this._def.errorMap,
                path: input.path,
                parent: input.parent,
            });
        }
        _processInputParams(input) {
            return {
                status: new ParseStatus(),
                ctx: {
                    common: input.parent.common,
                    data: input.data,
                    parsedType: getParsedType(input.data),
                    schemaErrorMap: this._def.errorMap,
                    path: input.path,
                    parent: input.parent,
                },
            };
        }
        _parseSync(input) {
            const result = this._parse(input);
            if (isAsync(result)) {
                throw new Error("Synchronous parse encountered promise.");
            }
            return result;
        }
        _parseAsync(input) {
            const result = this._parse(input);
            return Promise.resolve(result);
        }
        parse(data, params) {
            const result = this.safeParse(data, params);
            if (result.success)
                return result.data;
            throw result.error;
        }
        safeParse(data, params) {
            var _a;
            const ctx = {
                common: {
                    issues: [],
                    async: (_a = params === null || params === void 0 ? void 0 : params.async) !== null && _a !== void 0 ? _a : false,
                    contextualErrorMap: params === null || params === void 0 ? void 0 : params.errorMap,
                },
                path: (params === null || params === void 0 ? void 0 : params.path) || [],
                schemaErrorMap: this._def.errorMap,
                parent: null,
                data,
                parsedType: getParsedType(data),
            };
            const result = this._parseSync({ data, path: ctx.path, parent: ctx });
            return handleResult(ctx, result);
        }
        async parseAsync(data, params) {
            const result = await this.safeParseAsync(data, params);
            if (result.success)
                return result.data;
            throw result.error;
        }
        async safeParseAsync(data, params) {
            const ctx = {
                common: {
                    issues: [],
                    contextualErrorMap: params === null || params === void 0 ? void 0 : params.errorMap,
                    async: true,
                },
                path: (params === null || params === void 0 ? void 0 : params.path) || [],
                schemaErrorMap: this._def.errorMap,
                parent: null,
                data,
                parsedType: getParsedType(data),
            };
            const maybeAsyncResult = this._parse({ data, path: ctx.path, parent: ctx });
            const result = await (isAsync(maybeAsyncResult)
                ? maybeAsyncResult
                : Promise.resolve(maybeAsyncResult));
            return handleResult(ctx, result);
        }
        refine(check, message) {
            const getIssueProperties = (val) => {
                if (typeof message === "string" || typeof message === "undefined") {
                    return { message };
                }
                else if (typeof message === "function") {
                    return message(val);
                }
                else {
                    return message;
                }
            };
            return this._refinement((val, ctx) => {
                const result = check(val);
                const setError = () => ctx.addIssue({
                    code: ZodIssueCode.custom,
                    ...getIssueProperties(val),
                });
                if (typeof Promise !== "undefined" && result instanceof Promise) {
                    return result.then((data) => {
                        if (!data) {
                            setError();
                            return false;
                        }
                        else {
                            return true;
                        }
                    });
                }
                if (!result) {
                    setError();
                    return false;
                }
                else {
                    return true;
                }
            });
        }
        refinement(check, refinementData) {
            return this._refinement((val, ctx) => {
                if (!check(val)) {
                    ctx.addIssue(typeof refinementData === "function"
                        ? refinementData(val, ctx)
                        : refinementData);
                    return false;
                }
                else {
                    return true;
                }
            });
        }
        _refinement(refinement) {
            return new ZodEffects({
                schema: this,
                typeName: ZodFirstPartyTypeKind.ZodEffects,
                effect: { type: "refinement", refinement },
            });
        }
        superRefine(refinement) {
            return this._refinement(refinement);
        }
        optional() {
            return ZodOptional.create(this, this._def);
        }
        nullable() {
            return ZodNullable.create(this, this._def);
        }
        nullish() {
            return this.nullable().optional();
        }
        array() {
            return ZodArray.create(this, this._def);
        }
        promise() {
            return ZodPromise.create(this, this._def);
        }
        or(option) {
            return ZodUnion.create([this, option], this._def);
        }
        and(incoming) {
            return ZodIntersection.create(this, incoming, this._def);
        }
        transform(transform) {
            return new ZodEffects({
                ...processCreateParams(this._def),
                schema: this,
                typeName: ZodFirstPartyTypeKind.ZodEffects,
                effect: { type: "transform", transform },
            });
        }
        default(def) {
            const defaultValueFunc = typeof def === "function" ? def : () => def;
            return new ZodDefault({
                ...processCreateParams(this._def),
                innerType: this,
                defaultValue: defaultValueFunc,
                typeName: ZodFirstPartyTypeKind.ZodDefault,
            });
        }
        brand() {
            return new ZodBranded({
                typeName: ZodFirstPartyTypeKind.ZodBranded,
                type: this,
                ...processCreateParams(this._def),
            });
        }
        catch(def) {
            const catchValueFunc = typeof def === "function" ? def : () => def;
            return new ZodCatch({
                ...processCreateParams(this._def),
                innerType: this,
                catchValue: catchValueFunc,
                typeName: ZodFirstPartyTypeKind.ZodCatch,
            });
        }
        describe(description) {
            const This = this.constructor;
            return new This({
                ...this._def,
                description,
            });
        }
        pipe(target) {
            return ZodPipeline.create(this, target);
        }
        isOptional() {
            return this.safeParse(undefined).success;
        }
        isNullable() {
            return this.safeParse(null).success;
        }
    }
    const cuidRegex = /^c[^\s-]{8,}$/i;
    const cuid2Regex = /^[a-z][a-z0-9]*$/;
    const ulidRegex = /[0-9A-HJKMNP-TV-Z]{26}/;
    const uuidRegex = /^([a-f0-9]{8}-[a-f0-9]{4}-[1-5][a-f0-9]{3}-[a-f0-9]{4}-[a-f0-9]{12}|00000000-0000-0000-0000-000000000000)$/i;
    // from https://stackoverflow.com/a/46181/1550155
    // old version: too slow, didn't support unicode
    // const emailRegex = /^((([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+(\.([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+)*)|((\x22)((((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(([\x01-\x08\x0b\x0c\x0e-\x1f\x7f]|\x21|[\x23-\x5b]|[\x5d-\x7e]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(\\([\x01-\x09\x0b\x0c\x0d-\x7f]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]))))*(((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(\x22)))@((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))$/i;
    //old email regex
    // const emailRegex = /^(([^<>()[\].,;:\s@"]+(\.[^<>()[\].,;:\s@"]+)*)|(".+"))@((?!-)([^<>()[\].,;:\s@"]+\.)+[^<>()[\].,;:\s@"]{1,})[^-<>()[\].,;:\s@"]$/i;
    // eslint-disable-next-line
    const emailRegex = /^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[(((25[0-5])|(2[0-4][0-9])|(1[0-9]{2})|([0-9]{1,2}))\.){3}((25[0-5])|(2[0-4][0-9])|(1[0-9]{2})|([0-9]{1,2}))\])|(\[IPv6:(([a-f0-9]{1,4}:){7}|::([a-f0-9]{1,4}:){0,6}|([a-f0-9]{1,4}:){1}:([a-f0-9]{1,4}:){0,5}|([a-f0-9]{1,4}:){2}:([a-f0-9]{1,4}:){0,4}|([a-f0-9]{1,4}:){3}:([a-f0-9]{1,4}:){0,3}|([a-f0-9]{1,4}:){4}:([a-f0-9]{1,4}:){0,2}|([a-f0-9]{1,4}:){5}:([a-f0-9]{1,4}:){0,1})([a-f0-9]{1,4}|(((25[0-5])|(2[0-4][0-9])|(1[0-9]{2})|([0-9]{1,2}))\.){3}((25[0-5])|(2[0-4][0-9])|(1[0-9]{2})|([0-9]{1,2})))\])|([A-Za-z0-9]([A-Za-z0-9-]*[A-Za-z0-9])*(\.[A-Za-z]{2,})+))$/;
    // from https://thekevinscott.com/emojis-in-javascript/#writing-a-regular-expression
    const emojiRegex = /^(\p{Extended_Pictographic}|\p{Emoji_Component})+$/u;
    const ipv4Regex = /^(((25[0-5])|(2[0-4][0-9])|(1[0-9]{2})|([0-9]{1,2}))\.){3}((25[0-5])|(2[0-4][0-9])|(1[0-9]{2})|([0-9]{1,2}))$/;
    const ipv6Regex = /^(([a-f0-9]{1,4}:){7}|::([a-f0-9]{1,4}:){0,6}|([a-f0-9]{1,4}:){1}:([a-f0-9]{1,4}:){0,5}|([a-f0-9]{1,4}:){2}:([a-f0-9]{1,4}:){0,4}|([a-f0-9]{1,4}:){3}:([a-f0-9]{1,4}:){0,3}|([a-f0-9]{1,4}:){4}:([a-f0-9]{1,4}:){0,2}|([a-f0-9]{1,4}:){5}:([a-f0-9]{1,4}:){0,1})([a-f0-9]{1,4}|(((25[0-5])|(2[0-4][0-9])|(1[0-9]{2})|([0-9]{1,2}))\.){3}((25[0-5])|(2[0-4][0-9])|(1[0-9]{2})|([0-9]{1,2})))$/;
    // Adapted from https://stackoverflow.com/a/3143231
    const datetimeRegex = (args) => {
        if (args.precision) {
            if (args.offset) {
                return new RegExp(`^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}\\.\\d{${args.precision}}(([+-]\\d{2}(:?\\d{2})?)|Z)$`);
            }
            else {
                return new RegExp(`^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}\\.\\d{${args.precision}}Z$`);
            }
        }
        else if (args.precision === 0) {
            if (args.offset) {
                return new RegExp(`^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}(([+-]\\d{2}(:?\\d{2})?)|Z)$`);
            }
            else {
                return new RegExp(`^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}Z$`);
            }
        }
        else {
            if (args.offset) {
                return new RegExp(`^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}(\\.\\d+)?(([+-]\\d{2}(:?\\d{2})?)|Z)$`);
            }
            else {
                return new RegExp(`^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}(\\.\\d+)?Z$`);
            }
        }
    };
    function isValidIP(ip, version) {
        if ((version === "v4" || !version) && ipv4Regex.test(ip)) {
            return true;
        }
        if ((version === "v6" || !version) && ipv6Regex.test(ip)) {
            return true;
        }
        return false;
    }
    class ZodString extends ZodType {
        constructor() {
            super(...arguments);
            this._regex = (regex, validation, message) => this.refinement((data) => regex.test(data), {
                validation,
                code: ZodIssueCode.invalid_string,
                ...errorUtil.errToObj(message),
            });
            /**
             * @deprecated Use z.string().min(1) instead.
             * @see {@link ZodString.min}
             */
            this.nonempty = (message) => this.min(1, errorUtil.errToObj(message));
            this.trim = () => new ZodString({
                ...this._def,
                checks: [...this._def.checks, { kind: "trim" }],
            });
            this.toLowerCase = () => new ZodString({
                ...this._def,
                checks: [...this._def.checks, { kind: "toLowerCase" }],
            });
            this.toUpperCase = () => new ZodString({
                ...this._def,
                checks: [...this._def.checks, { kind: "toUpperCase" }],
            });
        }
        _parse(input) {
            if (this._def.coerce) {
                input.data = String(input.data);
            }
            const parsedType = this._getType(input);
            if (parsedType !== ZodParsedType.string) {
                const ctx = this._getOrReturnCtx(input);
                addIssueToContext(ctx, {
                    code: ZodIssueCode.invalid_type,
                    expected: ZodParsedType.string,
                    received: ctx.parsedType,
                }
                //
                );
                return INVALID;
            }
            const status = new ParseStatus();
            let ctx = undefined;
            for (const check of this._def.checks) {
                if (check.kind === "min") {
                    if (input.data.length < check.value) {
                        ctx = this._getOrReturnCtx(input, ctx);
                        addIssueToContext(ctx, {
                            code: ZodIssueCode.too_small,
                            minimum: check.value,
                            type: "string",
                            inclusive: true,
                            exact: false,
                            message: check.message,
                        });
                        status.dirty();
                    }
                }
                else if (check.kind === "max") {
                    if (input.data.length > check.value) {
                        ctx = this._getOrReturnCtx(input, ctx);
                        addIssueToContext(ctx, {
                            code: ZodIssueCode.too_big,
                            maximum: check.value,
                            type: "string",
                            inclusive: true,
                            exact: false,
                            message: check.message,
                        });
                        status.dirty();
                    }
                }
                else if (check.kind === "length") {
                    const tooBig = input.data.length > check.value;
                    const tooSmall = input.data.length < check.value;
                    if (tooBig || tooSmall) {
                        ctx = this._getOrReturnCtx(input, ctx);
                        if (tooBig) {
                            addIssueToContext(ctx, {
                                code: ZodIssueCode.too_big,
                                maximum: check.value,
                                type: "string",
                                inclusive: true,
                                exact: true,
                                message: check.message,
                            });
                        }
                        else if (tooSmall) {
                            addIssueToContext(ctx, {
                                code: ZodIssueCode.too_small,
                                minimum: check.value,
                                type: "string",
                                inclusive: true,
                                exact: true,
                                message: check.message,
                            });
                        }
                        status.dirty();
                    }
                }
                else if (check.kind === "email") {
                    if (!emailRegex.test(input.data)) {
                        ctx = this._getOrReturnCtx(input, ctx);
                        addIssueToContext(ctx, {
                            validation: "email",
                            code: ZodIssueCode.invalid_string,
                            message: check.message,
                        });
                        status.dirty();
                    }
                }
                else if (check.kind === "emoji") {
                    if (!emojiRegex.test(input.data)) {
                        ctx = this._getOrReturnCtx(input, ctx);
                        addIssueToContext(ctx, {
                            validation: "emoji",
                            code: ZodIssueCode.invalid_string,
                            message: check.message,
                        });
                        status.dirty();
                    }
                }
                else if (check.kind === "uuid") {
                    if (!uuidRegex.test(input.data)) {
                        ctx = this._getOrReturnCtx(input, ctx);
                        addIssueToContext(ctx, {
                            validation: "uuid",
                            code: ZodIssueCode.invalid_string,
                            message: check.message,
                        });
                        status.dirty();
                    }
                }
                else if (check.kind === "cuid") {
                    if (!cuidRegex.test(input.data)) {
                        ctx = this._getOrReturnCtx(input, ctx);
                        addIssueToContext(ctx, {
                            validation: "cuid",
                            code: ZodIssueCode.invalid_string,
                            message: check.message,
                        });
                        status.dirty();
                    }
                }
                else if (check.kind === "cuid2") {
                    if (!cuid2Regex.test(input.data)) {
                        ctx = this._getOrReturnCtx(input, ctx);
                        addIssueToContext(ctx, {
                            validation: "cuid2",
                            code: ZodIssueCode.invalid_string,
                            message: check.message,
                        });
                        status.dirty();
                    }
                }
                else if (check.kind === "ulid") {
                    if (!ulidRegex.test(input.data)) {
                        ctx = this._getOrReturnCtx(input, ctx);
                        addIssueToContext(ctx, {
                            validation: "ulid",
                            code: ZodIssueCode.invalid_string,
                            message: check.message,
                        });
                        status.dirty();
                    }
                }
                else if (check.kind === "url") {
                    try {
                        new URL(input.data);
                    }
                    catch (_a) {
                        ctx = this._getOrReturnCtx(input, ctx);
                        addIssueToContext(ctx, {
                            validation: "url",
                            code: ZodIssueCode.invalid_string,
                            message: check.message,
                        });
                        status.dirty();
                    }
                }
                else if (check.kind === "regex") {
                    check.regex.lastIndex = 0;
                    const testResult = check.regex.test(input.data);
                    if (!testResult) {
                        ctx = this._getOrReturnCtx(input, ctx);
                        addIssueToContext(ctx, {
                            validation: "regex",
                            code: ZodIssueCode.invalid_string,
                            message: check.message,
                        });
                        status.dirty();
                    }
                }
                else if (check.kind === "trim") {
                    input.data = input.data.trim();
                }
                else if (check.kind === "includes") {
                    if (!input.data.includes(check.value, check.position)) {
                        ctx = this._getOrReturnCtx(input, ctx);
                        addIssueToContext(ctx, {
                            code: ZodIssueCode.invalid_string,
                            validation: { includes: check.value, position: check.position },
                            message: check.message,
                        });
                        status.dirty();
                    }
                }
                else if (check.kind === "toLowerCase") {
                    input.data = input.data.toLowerCase();
                }
                else if (check.kind === "toUpperCase") {
                    input.data = input.data.toUpperCase();
                }
                else if (check.kind === "startsWith") {
                    if (!input.data.startsWith(check.value)) {
                        ctx = this._getOrReturnCtx(input, ctx);
                        addIssueToContext(ctx, {
                            code: ZodIssueCode.invalid_string,
                            validation: { startsWith: check.value },
                            message: check.message,
                        });
                        status.dirty();
                    }
                }
                else if (check.kind === "endsWith") {
                    if (!input.data.endsWith(check.value)) {
                        ctx = this._getOrReturnCtx(input, ctx);
                        addIssueToContext(ctx, {
                            code: ZodIssueCode.invalid_string,
                            validation: { endsWith: check.value },
                            message: check.message,
                        });
                        status.dirty();
                    }
                }
                else if (check.kind === "datetime") {
                    const regex = datetimeRegex(check);
                    if (!regex.test(input.data)) {
                        ctx = this._getOrReturnCtx(input, ctx);
                        addIssueToContext(ctx, {
                            code: ZodIssueCode.invalid_string,
                            validation: "datetime",
                            message: check.message,
                        });
                        status.dirty();
                    }
                }
                else if (check.kind === "ip") {
                    if (!isValidIP(input.data, check.version)) {
                        ctx = this._getOrReturnCtx(input, ctx);
                        addIssueToContext(ctx, {
                            validation: "ip",
                            code: ZodIssueCode.invalid_string,
                            message: check.message,
                        });
                        status.dirty();
                    }
                }
                else {
                    util.assertNever(check);
                }
            }
            return { status: status.value, value: input.data };
        }
        _addCheck(check) {
            return new ZodString({
                ...this._def,
                checks: [...this._def.checks, check],
            });
        }
        email(message) {
            return this._addCheck({ kind: "email", ...errorUtil.errToObj(message) });
        }
        url(message) {
            return this._addCheck({ kind: "url", ...errorUtil.errToObj(message) });
        }
        emoji(message) {
            return this._addCheck({ kind: "emoji", ...errorUtil.errToObj(message) });
        }
        uuid(message) {
            return this._addCheck({ kind: "uuid", ...errorUtil.errToObj(message) });
        }
        cuid(message) {
            return this._addCheck({ kind: "cuid", ...errorUtil.errToObj(message) });
        }
        cuid2(message) {
            return this._addCheck({ kind: "cuid2", ...errorUtil.errToObj(message) });
        }
        ulid(message) {
            return this._addCheck({ kind: "ulid", ...errorUtil.errToObj(message) });
        }
        ip(options) {
            return this._addCheck({ kind: "ip", ...errorUtil.errToObj(options) });
        }
        datetime(options) {
            var _a;
            if (typeof options === "string") {
                return this._addCheck({
                    kind: "datetime",
                    precision: null,
                    offset: false,
                    message: options,
                });
            }
            return this._addCheck({
                kind: "datetime",
                precision: typeof (options === null || options === void 0 ? void 0 : options.precision) === "undefined" ? null : options === null || options === void 0 ? void 0 : options.precision,
                offset: (_a = options === null || options === void 0 ? void 0 : options.offset) !== null && _a !== void 0 ? _a : false,
                ...errorUtil.errToObj(options === null || options === void 0 ? void 0 : options.message),
            });
        }
        regex(regex, message) {
            return this._addCheck({
                kind: "regex",
                regex: regex,
                ...errorUtil.errToObj(message),
            });
        }
        includes(value, options) {
            return this._addCheck({
                kind: "includes",
                value: value,
                position: options === null || options === void 0 ? void 0 : options.position,
                ...errorUtil.errToObj(options === null || options === void 0 ? void 0 : options.message),
            });
        }
        startsWith(value, message) {
            return this._addCheck({
                kind: "startsWith",
                value: value,
                ...errorUtil.errToObj(message),
            });
        }
        endsWith(value, message) {
            return this._addCheck({
                kind: "endsWith",
                value: value,
                ...errorUtil.errToObj(message),
            });
        }
        min(minLength, message) {
            return this._addCheck({
                kind: "min",
                value: minLength,
                ...errorUtil.errToObj(message),
            });
        }
        max(maxLength, message) {
            return this._addCheck({
                kind: "max",
                value: maxLength,
                ...errorUtil.errToObj(message),
            });
        }
        length(len, message) {
            return this._addCheck({
                kind: "length",
                value: len,
                ...errorUtil.errToObj(message),
            });
        }
        get isDatetime() {
            return !!this._def.checks.find((ch) => ch.kind === "datetime");
        }
        get isEmail() {
            return !!this._def.checks.find((ch) => ch.kind === "email");
        }
        get isURL() {
            return !!this._def.checks.find((ch) => ch.kind === "url");
        }
        get isEmoji() {
            return !!this._def.checks.find((ch) => ch.kind === "emoji");
        }
        get isUUID() {
            return !!this._def.checks.find((ch) => ch.kind === "uuid");
        }
        get isCUID() {
            return !!this._def.checks.find((ch) => ch.kind === "cuid");
        }
        get isCUID2() {
            return !!this._def.checks.find((ch) => ch.kind === "cuid2");
        }
        get isULID() {
            return !!this._def.checks.find((ch) => ch.kind === "ulid");
        }
        get isIP() {
            return !!this._def.checks.find((ch) => ch.kind === "ip");
        }
        get minLength() {
            let min = null;
            for (const ch of this._def.checks) {
                if (ch.kind === "min") {
                    if (min === null || ch.value > min)
                        min = ch.value;
                }
            }
            return min;
        }
        get maxLength() {
            let max = null;
            for (const ch of this._def.checks) {
                if (ch.kind === "max") {
                    if (max === null || ch.value < max)
                        max = ch.value;
                }
            }
            return max;
        }
    }
    ZodString.create = (params) => {
        var _a;
        return new ZodString({
            checks: [],
            typeName: ZodFirstPartyTypeKind.ZodString,
            coerce: (_a = params === null || params === void 0 ? void 0 : params.coerce) !== null && _a !== void 0 ? _a : false,
            ...processCreateParams(params),
        });
    };
    // https://stackoverflow.com/questions/3966484/why-does-modulus-operator-return-fractional-number-in-javascript/31711034#31711034
    function floatSafeRemainder(val, step) {
        const valDecCount = (val.toString().split(".")[1] || "").length;
        const stepDecCount = (step.toString().split(".")[1] || "").length;
        const decCount = valDecCount > stepDecCount ? valDecCount : stepDecCount;
        const valInt = parseInt(val.toFixed(decCount).replace(".", ""));
        const stepInt = parseInt(step.toFixed(decCount).replace(".", ""));
        return (valInt % stepInt) / Math.pow(10, decCount);
    }
    class ZodNumber extends ZodType {
        constructor() {
            super(...arguments);
            this.min = this.gte;
            this.max = this.lte;
            this.step = this.multipleOf;
        }
        _parse(input) {
            if (this._def.coerce) {
                input.data = Number(input.data);
            }
            const parsedType = this._getType(input);
            if (parsedType !== ZodParsedType.number) {
                const ctx = this._getOrReturnCtx(input);
                addIssueToContext(ctx, {
                    code: ZodIssueCode.invalid_type,
                    expected: ZodParsedType.number,
                    received: ctx.parsedType,
                });
                return INVALID;
            }
            let ctx = undefined;
            const status = new ParseStatus();
            for (const check of this._def.checks) {
                if (check.kind === "int") {
                    if (!util.isInteger(input.data)) {
                        ctx = this._getOrReturnCtx(input, ctx);
                        addIssueToContext(ctx, {
                            code: ZodIssueCode.invalid_type,
                            expected: "integer",
                            received: "float",
                            message: check.message,
                        });
                        status.dirty();
                    }
                }
                else if (check.kind === "min") {
                    const tooSmall = check.inclusive
                        ? input.data < check.value
                        : input.data <= check.value;
                    if (tooSmall) {
                        ctx = this._getOrReturnCtx(input, ctx);
                        addIssueToContext(ctx, {
                            code: ZodIssueCode.too_small,
                            minimum: check.value,
                            type: "number",
                            inclusive: check.inclusive,
                            exact: false,
                            message: check.message,
                        });
                        status.dirty();
                    }
                }
                else if (check.kind === "max") {
                    const tooBig = check.inclusive
                        ? input.data > check.value
                        : input.data >= check.value;
                    if (tooBig) {
                        ctx = this._getOrReturnCtx(input, ctx);
                        addIssueToContext(ctx, {
                            code: ZodIssueCode.too_big,
                            maximum: check.value,
                            type: "number",
                            inclusive: check.inclusive,
                            exact: false,
                            message: check.message,
                        });
                        status.dirty();
                    }
                }
                else if (check.kind === "multipleOf") {
                    if (floatSafeRemainder(input.data, check.value) !== 0) {
                        ctx = this._getOrReturnCtx(input, ctx);
                        addIssueToContext(ctx, {
                            code: ZodIssueCode.not_multiple_of,
                            multipleOf: check.value,
                            message: check.message,
                        });
                        status.dirty();
                    }
                }
                else if (check.kind === "finite") {
                    if (!Number.isFinite(input.data)) {
                        ctx = this._getOrReturnCtx(input, ctx);
                        addIssueToContext(ctx, {
                            code: ZodIssueCode.not_finite,
                            message: check.message,
                        });
                        status.dirty();
                    }
                }
                else {
                    util.assertNever(check);
                }
            }
            return { status: status.value, value: input.data };
        }
        gte(value, message) {
            return this.setLimit("min", value, true, errorUtil.toString(message));
        }
        gt(value, message) {
            return this.setLimit("min", value, false, errorUtil.toString(message));
        }
        lte(value, message) {
            return this.setLimit("max", value, true, errorUtil.toString(message));
        }
        lt(value, message) {
            return this.setLimit("max", value, false, errorUtil.toString(message));
        }
        setLimit(kind, value, inclusive, message) {
            return new ZodNumber({
                ...this._def,
                checks: [
                    ...this._def.checks,
                    {
                        kind,
                        value,
                        inclusive,
                        message: errorUtil.toString(message),
                    },
                ],
            });
        }
        _addCheck(check) {
            return new ZodNumber({
                ...this._def,
                checks: [...this._def.checks, check],
            });
        }
        int(message) {
            return this._addCheck({
                kind: "int",
                message: errorUtil.toString(message),
            });
        }
        positive(message) {
            return this._addCheck({
                kind: "min",
                value: 0,
                inclusive: false,
                message: errorUtil.toString(message),
            });
        }
        negative(message) {
            return this._addCheck({
                kind: "max",
                value: 0,
                inclusive: false,
                message: errorUtil.toString(message),
            });
        }
        nonpositive(message) {
            return this._addCheck({
                kind: "max",
                value: 0,
                inclusive: true,
                message: errorUtil.toString(message),
            });
        }
        nonnegative(message) {
            return this._addCheck({
                kind: "min",
                value: 0,
                inclusive: true,
                message: errorUtil.toString(message),
            });
        }
        multipleOf(value, message) {
            return this._addCheck({
                kind: "multipleOf",
                value: value,
                message: errorUtil.toString(message),
            });
        }
        finite(message) {
            return this._addCheck({
                kind: "finite",
                message: errorUtil.toString(message),
            });
        }
        safe(message) {
            return this._addCheck({
                kind: "min",
                inclusive: true,
                value: Number.MIN_SAFE_INTEGER,
                message: errorUtil.toString(message),
            })._addCheck({
                kind: "max",
                inclusive: true,
                value: Number.MAX_SAFE_INTEGER,
                message: errorUtil.toString(message),
            });
        }
        get minValue() {
            let min = null;
            for (const ch of this._def.checks) {
                if (ch.kind === "min") {
                    if (min === null || ch.value > min)
                        min = ch.value;
                }
            }
            return min;
        }
        get maxValue() {
            let max = null;
            for (const ch of this._def.checks) {
                if (ch.kind === "max") {
                    if (max === null || ch.value < max)
                        max = ch.value;
                }
            }
            return max;
        }
        get isInt() {
            return !!this._def.checks.find((ch) => ch.kind === "int" ||
                (ch.kind === "multipleOf" && util.isInteger(ch.value)));
        }
        get isFinite() {
            let max = null, min = null;
            for (const ch of this._def.checks) {
                if (ch.kind === "finite" ||
                    ch.kind === "int" ||
                    ch.kind === "multipleOf") {
                    return true;
                }
                else if (ch.kind === "min") {
                    if (min === null || ch.value > min)
                        min = ch.value;
                }
                else if (ch.kind === "max") {
                    if (max === null || ch.value < max)
                        max = ch.value;
                }
            }
            return Number.isFinite(min) && Number.isFinite(max);
        }
    }
    ZodNumber.create = (params) => {
        return new ZodNumber({
            checks: [],
            typeName: ZodFirstPartyTypeKind.ZodNumber,
            coerce: (params === null || params === void 0 ? void 0 : params.coerce) || false,
            ...processCreateParams(params),
        });
    };
    class ZodBigInt extends ZodType {
        constructor() {
            super(...arguments);
            this.min = this.gte;
            this.max = this.lte;
        }
        _parse(input) {
            if (this._def.coerce) {
                input.data = BigInt(input.data);
            }
            const parsedType = this._getType(input);
            if (parsedType !== ZodParsedType.bigint) {
                const ctx = this._getOrReturnCtx(input);
                addIssueToContext(ctx, {
                    code: ZodIssueCode.invalid_type,
                    expected: ZodParsedType.bigint,
                    received: ctx.parsedType,
                });
                return INVALID;
            }
            let ctx = undefined;
            const status = new ParseStatus();
            for (const check of this._def.checks) {
                if (check.kind === "min") {
                    const tooSmall = check.inclusive
                        ? input.data < check.value
                        : input.data <= check.value;
                    if (tooSmall) {
                        ctx = this._getOrReturnCtx(input, ctx);
                        addIssueToContext(ctx, {
                            code: ZodIssueCode.too_small,
                            type: "bigint",
                            minimum: check.value,
                            inclusive: check.inclusive,
                            message: check.message,
                        });
                        status.dirty();
                    }
                }
                else if (check.kind === "max") {
                    const tooBig = check.inclusive
                        ? input.data > check.value
                        : input.data >= check.value;
                    if (tooBig) {
                        ctx = this._getOrReturnCtx(input, ctx);
                        addIssueToContext(ctx, {
                            code: ZodIssueCode.too_big,
                            type: "bigint",
                            maximum: check.value,
                            inclusive: check.inclusive,
                            message: check.message,
                        });
                        status.dirty();
                    }
                }
                else if (check.kind === "multipleOf") {
                    if (input.data % check.value !== BigInt(0)) {
                        ctx = this._getOrReturnCtx(input, ctx);
                        addIssueToContext(ctx, {
                            code: ZodIssueCode.not_multiple_of,
                            multipleOf: check.value,
                            message: check.message,
                        });
                        status.dirty();
                    }
                }
                else {
                    util.assertNever(check);
                }
            }
            return { status: status.value, value: input.data };
        }
        gte(value, message) {
            return this.setLimit("min", value, true, errorUtil.toString(message));
        }
        gt(value, message) {
            return this.setLimit("min", value, false, errorUtil.toString(message));
        }
        lte(value, message) {
            return this.setLimit("max", value, true, errorUtil.toString(message));
        }
        lt(value, message) {
            return this.setLimit("max", value, false, errorUtil.toString(message));
        }
        setLimit(kind, value, inclusive, message) {
            return new ZodBigInt({
                ...this._def,
                checks: [
                    ...this._def.checks,
                    {
                        kind,
                        value,
                        inclusive,
                        message: errorUtil.toString(message),
                    },
                ],
            });
        }
        _addCheck(check) {
            return new ZodBigInt({
                ...this._def,
                checks: [...this._def.checks, check],
            });
        }
        positive(message) {
            return this._addCheck({
                kind: "min",
                value: BigInt(0),
                inclusive: false,
                message: errorUtil.toString(message),
            });
        }
        negative(message) {
            return this._addCheck({
                kind: "max",
                value: BigInt(0),
                inclusive: false,
                message: errorUtil.toString(message),
            });
        }
        nonpositive(message) {
            return this._addCheck({
                kind: "max",
                value: BigInt(0),
                inclusive: true,
                message: errorUtil.toString(message),
            });
        }
        nonnegative(message) {
            return this._addCheck({
                kind: "min",
                value: BigInt(0),
                inclusive: true,
                message: errorUtil.toString(message),
            });
        }
        multipleOf(value, message) {
            return this._addCheck({
                kind: "multipleOf",
                value,
                message: errorUtil.toString(message),
            });
        }
        get minValue() {
            let min = null;
            for (const ch of this._def.checks) {
                if (ch.kind === "min") {
                    if (min === null || ch.value > min)
                        min = ch.value;
                }
            }
            return min;
        }
        get maxValue() {
            let max = null;
            for (const ch of this._def.checks) {
                if (ch.kind === "max") {
                    if (max === null || ch.value < max)
                        max = ch.value;
                }
            }
            return max;
        }
    }
    ZodBigInt.create = (params) => {
        var _a;
        return new ZodBigInt({
            checks: [],
            typeName: ZodFirstPartyTypeKind.ZodBigInt,
            coerce: (_a = params === null || params === void 0 ? void 0 : params.coerce) !== null && _a !== void 0 ? _a : false,
            ...processCreateParams(params),
        });
    };
    class ZodBoolean extends ZodType {
        _parse(input) {
            if (this._def.coerce) {
                input.data = Boolean(input.data);
            }
            const parsedType = this._getType(input);
            if (parsedType !== ZodParsedType.boolean) {
                const ctx = this._getOrReturnCtx(input);
                addIssueToContext(ctx, {
                    code: ZodIssueCode.invalid_type,
                    expected: ZodParsedType.boolean,
                    received: ctx.parsedType,
                });
                return INVALID;
            }
            return OK(input.data);
        }
    }
    ZodBoolean.create = (params) => {
        return new ZodBoolean({
            typeName: ZodFirstPartyTypeKind.ZodBoolean,
            coerce: (params === null || params === void 0 ? void 0 : params.coerce) || false,
            ...processCreateParams(params),
        });
    };
    class ZodDate extends ZodType {
        _parse(input) {
            if (this._def.coerce) {
                input.data = new Date(input.data);
            }
            const parsedType = this._getType(input);
            if (parsedType !== ZodParsedType.date) {
                const ctx = this._getOrReturnCtx(input);
                addIssueToContext(ctx, {
                    code: ZodIssueCode.invalid_type,
                    expected: ZodParsedType.date,
                    received: ctx.parsedType,
                });
                return INVALID;
            }
            if (isNaN(input.data.getTime())) {
                const ctx = this._getOrReturnCtx(input);
                addIssueToContext(ctx, {
                    code: ZodIssueCode.invalid_date,
                });
                return INVALID;
            }
            const status = new ParseStatus();
            let ctx = undefined;
            for (const check of this._def.checks) {
                if (check.kind === "min") {
                    if (input.data.getTime() < check.value) {
                        ctx = this._getOrReturnCtx(input, ctx);
                        addIssueToContext(ctx, {
                            code: ZodIssueCode.too_small,
                            message: check.message,
                            inclusive: true,
                            exact: false,
                            minimum: check.value,
                            type: "date",
                        });
                        status.dirty();
                    }
                }
                else if (check.kind === "max") {
                    if (input.data.getTime() > check.value) {
                        ctx = this._getOrReturnCtx(input, ctx);
                        addIssueToContext(ctx, {
                            code: ZodIssueCode.too_big,
                            message: check.message,
                            inclusive: true,
                            exact: false,
                            maximum: check.value,
                            type: "date",
                        });
                        status.dirty();
                    }
                }
                else {
                    util.assertNever(check);
                }
            }
            return {
                status: status.value,
                value: new Date(input.data.getTime()),
            };
        }
        _addCheck(check) {
            return new ZodDate({
                ...this._def,
                checks: [...this._def.checks, check],
            });
        }
        min(minDate, message) {
            return this._addCheck({
                kind: "min",
                value: minDate.getTime(),
                message: errorUtil.toString(message),
            });
        }
        max(maxDate, message) {
            return this._addCheck({
                kind: "max",
                value: maxDate.getTime(),
                message: errorUtil.toString(message),
            });
        }
        get minDate() {
            let min = null;
            for (const ch of this._def.checks) {
                if (ch.kind === "min") {
                    if (min === null || ch.value > min)
                        min = ch.value;
                }
            }
            return min != null ? new Date(min) : null;
        }
        get maxDate() {
            let max = null;
            for (const ch of this._def.checks) {
                if (ch.kind === "max") {
                    if (max === null || ch.value < max)
                        max = ch.value;
                }
            }
            return max != null ? new Date(max) : null;
        }
    }
    ZodDate.create = (params) => {
        return new ZodDate({
            checks: [],
            coerce: (params === null || params === void 0 ? void 0 : params.coerce) || false,
            typeName: ZodFirstPartyTypeKind.ZodDate,
            ...processCreateParams(params),
        });
    };
    class ZodSymbol extends ZodType {
        _parse(input) {
            const parsedType = this._getType(input);
            if (parsedType !== ZodParsedType.symbol) {
                const ctx = this._getOrReturnCtx(input);
                addIssueToContext(ctx, {
                    code: ZodIssueCode.invalid_type,
                    expected: ZodParsedType.symbol,
                    received: ctx.parsedType,
                });
                return INVALID;
            }
            return OK(input.data);
        }
    }
    ZodSymbol.create = (params) => {
        return new ZodSymbol({
            typeName: ZodFirstPartyTypeKind.ZodSymbol,
            ...processCreateParams(params),
        });
    };
    class ZodUndefined extends ZodType {
        _parse(input) {
            const parsedType = this._getType(input);
            if (parsedType !== ZodParsedType.undefined) {
                const ctx = this._getOrReturnCtx(input);
                addIssueToContext(ctx, {
                    code: ZodIssueCode.invalid_type,
                    expected: ZodParsedType.undefined,
                    received: ctx.parsedType,
                });
                return INVALID;
            }
            return OK(input.data);
        }
    }
    ZodUndefined.create = (params) => {
        return new ZodUndefined({
            typeName: ZodFirstPartyTypeKind.ZodUndefined,
            ...processCreateParams(params),
        });
    };
    class ZodNull extends ZodType {
        _parse(input) {
            const parsedType = this._getType(input);
            if (parsedType !== ZodParsedType.null) {
                const ctx = this._getOrReturnCtx(input);
                addIssueToContext(ctx, {
                    code: ZodIssueCode.invalid_type,
                    expected: ZodParsedType.null,
                    received: ctx.parsedType,
                });
                return INVALID;
            }
            return OK(input.data);
        }
    }
    ZodNull.create = (params) => {
        return new ZodNull({
            typeName: ZodFirstPartyTypeKind.ZodNull,
            ...processCreateParams(params),
        });
    };
    class ZodAny extends ZodType {
        constructor() {
            super(...arguments);
            // to prevent instances of other classes from extending ZodAny. this causes issues with catchall in ZodObject.
            this._any = true;
        }
        _parse(input) {
            return OK(input.data);
        }
    }
    ZodAny.create = (params) => {
        return new ZodAny({
            typeName: ZodFirstPartyTypeKind.ZodAny,
            ...processCreateParams(params),
        });
    };
    class ZodUnknown extends ZodType {
        constructor() {
            super(...arguments);
            // required
            this._unknown = true;
        }
        _parse(input) {
            return OK(input.data);
        }
    }
    ZodUnknown.create = (params) => {
        return new ZodUnknown({
            typeName: ZodFirstPartyTypeKind.ZodUnknown,
            ...processCreateParams(params),
        });
    };
    class ZodNever extends ZodType {
        _parse(input) {
            const ctx = this._getOrReturnCtx(input);
            addIssueToContext(ctx, {
                code: ZodIssueCode.invalid_type,
                expected: ZodParsedType.never,
                received: ctx.parsedType,
            });
            return INVALID;
        }
    }
    ZodNever.create = (params) => {
        return new ZodNever({
            typeName: ZodFirstPartyTypeKind.ZodNever,
            ...processCreateParams(params),
        });
    };
    class ZodVoid extends ZodType {
        _parse(input) {
            const parsedType = this._getType(input);
            if (parsedType !== ZodParsedType.undefined) {
                const ctx = this._getOrReturnCtx(input);
                addIssueToContext(ctx, {
                    code: ZodIssueCode.invalid_type,
                    expected: ZodParsedType.void,
                    received: ctx.parsedType,
                });
                return INVALID;
            }
            return OK(input.data);
        }
    }
    ZodVoid.create = (params) => {
        return new ZodVoid({
            typeName: ZodFirstPartyTypeKind.ZodVoid,
            ...processCreateParams(params),
        });
    };
    class ZodArray extends ZodType {
        _parse(input) {
            const { ctx, status } = this._processInputParams(input);
            const def = this._def;
            if (ctx.parsedType !== ZodParsedType.array) {
                addIssueToContext(ctx, {
                    code: ZodIssueCode.invalid_type,
                    expected: ZodParsedType.array,
                    received: ctx.parsedType,
                });
                return INVALID;
            }
            if (def.exactLength !== null) {
                const tooBig = ctx.data.length > def.exactLength.value;
                const tooSmall = ctx.data.length < def.exactLength.value;
                if (tooBig || tooSmall) {
                    addIssueToContext(ctx, {
                        code: tooBig ? ZodIssueCode.too_big : ZodIssueCode.too_small,
                        minimum: (tooSmall ? def.exactLength.value : undefined),
                        maximum: (tooBig ? def.exactLength.value : undefined),
                        type: "array",
                        inclusive: true,
                        exact: true,
                        message: def.exactLength.message,
                    });
                    status.dirty();
                }
            }
            if (def.minLength !== null) {
                if (ctx.data.length < def.minLength.value) {
                    addIssueToContext(ctx, {
                        code: ZodIssueCode.too_small,
                        minimum: def.minLength.value,
                        type: "array",
                        inclusive: true,
                        exact: false,
                        message: def.minLength.message,
                    });
                    status.dirty();
                }
            }
            if (def.maxLength !== null) {
                if (ctx.data.length > def.maxLength.value) {
                    addIssueToContext(ctx, {
                        code: ZodIssueCode.too_big,
                        maximum: def.maxLength.value,
                        type: "array",
                        inclusive: true,
                        exact: false,
                        message: def.maxLength.message,
                    });
                    status.dirty();
                }
            }
            if (ctx.common.async) {
                return Promise.all([...ctx.data].map((item, i) => {
                    return def.type._parseAsync(new ParseInputLazyPath(ctx, item, ctx.path, i));
                })).then((result) => {
                    return ParseStatus.mergeArray(status, result);
                });
            }
            const result = [...ctx.data].map((item, i) => {
                return def.type._parseSync(new ParseInputLazyPath(ctx, item, ctx.path, i));
            });
            return ParseStatus.mergeArray(status, result);
        }
        get element() {
            return this._def.type;
        }
        min(minLength, message) {
            return new ZodArray({
                ...this._def,
                minLength: { value: minLength, message: errorUtil.toString(message) },
            });
        }
        max(maxLength, message) {
            return new ZodArray({
                ...this._def,
                maxLength: { value: maxLength, message: errorUtil.toString(message) },
            });
        }
        length(len, message) {
            return new ZodArray({
                ...this._def,
                exactLength: { value: len, message: errorUtil.toString(message) },
            });
        }
        nonempty(message) {
            return this.min(1, message);
        }
    }
    ZodArray.create = (schema, params) => {
        return new ZodArray({
            type: schema,
            minLength: null,
            maxLength: null,
            exactLength: null,
            typeName: ZodFirstPartyTypeKind.ZodArray,
            ...processCreateParams(params),
        });
    };
    function deepPartialify(schema) {
        if (schema instanceof ZodObject) {
            const newShape = {};
            for (const key in schema.shape) {
                const fieldSchema = schema.shape[key];
                newShape[key] = ZodOptional.create(deepPartialify(fieldSchema));
            }
            return new ZodObject({
                ...schema._def,
                shape: () => newShape,
            });
        }
        else if (schema instanceof ZodArray) {
            return new ZodArray({
                ...schema._def,
                type: deepPartialify(schema.element),
            });
        }
        else if (schema instanceof ZodOptional) {
            return ZodOptional.create(deepPartialify(schema.unwrap()));
        }
        else if (schema instanceof ZodNullable) {
            return ZodNullable.create(deepPartialify(schema.unwrap()));
        }
        else if (schema instanceof ZodTuple) {
            return ZodTuple.create(schema.items.map((item) => deepPartialify(item)));
        }
        else {
            return schema;
        }
    }
    class ZodObject extends ZodType {
        constructor() {
            super(...arguments);
            this._cached = null;
            /**
             * @deprecated In most cases, this is no longer needed - unknown properties are now silently stripped.
             * If you want to pass through unknown properties, use `.passthrough()` instead.
             */
            this.nonstrict = this.passthrough;
            // extend<
            //   Augmentation extends ZodRawShape,
            //   NewOutput extends util.flatten<{
            //     [k in keyof Augmentation | keyof Output]: k extends keyof Augmentation
            //       ? Augmentation[k]["_output"]
            //       : k extends keyof Output
            //       ? Output[k]
            //       : never;
            //   }>,
            //   NewInput extends util.flatten<{
            //     [k in keyof Augmentation | keyof Input]: k extends keyof Augmentation
            //       ? Augmentation[k]["_input"]
            //       : k extends keyof Input
            //       ? Input[k]
            //       : never;
            //   }>
            // >(
            //   augmentation: Augmentation
            // ): ZodObject<
            //   extendShape<T, Augmentation>,
            //   UnknownKeys,
            //   Catchall,
            //   NewOutput,
            //   NewInput
            // > {
            //   return new ZodObject({
            //     ...this._def,
            //     shape: () => ({
            //       ...this._def.shape(),
            //       ...augmentation,
            //     }),
            //   }) as any;
            // }
            /**
             * @deprecated Use `.extend` instead
             *  */
            this.augment = this.extend;
        }
        _getCached() {
            if (this._cached !== null)
                return this._cached;
            const shape = this._def.shape();
            const keys = util.objectKeys(shape);
            return (this._cached = { shape, keys });
        }
        _parse(input) {
            const parsedType = this._getType(input);
            if (parsedType !== ZodParsedType.object) {
                const ctx = this._getOrReturnCtx(input);
                addIssueToContext(ctx, {
                    code: ZodIssueCode.invalid_type,
                    expected: ZodParsedType.object,
                    received: ctx.parsedType,
                });
                return INVALID;
            }
            const { status, ctx } = this._processInputParams(input);
            const { shape, keys: shapeKeys } = this._getCached();
            const extraKeys = [];
            if (!(this._def.catchall instanceof ZodNever &&
                this._def.unknownKeys === "strip")) {
                for (const key in ctx.data) {
                    if (!shapeKeys.includes(key)) {
                        extraKeys.push(key);
                    }
                }
            }
            const pairs = [];
            for (const key of shapeKeys) {
                const keyValidator = shape[key];
                const value = ctx.data[key];
                pairs.push({
                    key: { status: "valid", value: key },
                    value: keyValidator._parse(new ParseInputLazyPath(ctx, value, ctx.path, key)),
                    alwaysSet: key in ctx.data,
                });
            }
            if (this._def.catchall instanceof ZodNever) {
                const unknownKeys = this._def.unknownKeys;
                if (unknownKeys === "passthrough") {
                    for (const key of extraKeys) {
                        pairs.push({
                            key: { status: "valid", value: key },
                            value: { status: "valid", value: ctx.data[key] },
                        });
                    }
                }
                else if (unknownKeys === "strict") {
                    if (extraKeys.length > 0) {
                        addIssueToContext(ctx, {
                            code: ZodIssueCode.unrecognized_keys,
                            keys: extraKeys,
                        });
                        status.dirty();
                    }
                }
                else if (unknownKeys === "strip") ;
                else {
                    throw new Error(`Internal ZodObject error: invalid unknownKeys value.`);
                }
            }
            else {
                // run catchall validation
                const catchall = this._def.catchall;
                for (const key of extraKeys) {
                    const value = ctx.data[key];
                    pairs.push({
                        key: { status: "valid", value: key },
                        value: catchall._parse(new ParseInputLazyPath(ctx, value, ctx.path, key) //, ctx.child(key), value, getParsedType(value)
                        ),
                        alwaysSet: key in ctx.data,
                    });
                }
            }
            if (ctx.common.async) {
                return Promise.resolve()
                    .then(async () => {
                    const syncPairs = [];
                    for (const pair of pairs) {
                        const key = await pair.key;
                        syncPairs.push({
                            key,
                            value: await pair.value,
                            alwaysSet: pair.alwaysSet,
                        });
                    }
                    return syncPairs;
                })
                    .then((syncPairs) => {
                    return ParseStatus.mergeObjectSync(status, syncPairs);
                });
            }
            else {
                return ParseStatus.mergeObjectSync(status, pairs);
            }
        }
        get shape() {
            return this._def.shape();
        }
        strict(message) {
            errorUtil.errToObj;
            return new ZodObject({
                ...this._def,
                unknownKeys: "strict",
                ...(message !== undefined
                    ? {
                        errorMap: (issue, ctx) => {
                            var _a, _b, _c, _d;
                            const defaultError = (_c = (_b = (_a = this._def).errorMap) === null || _b === void 0 ? void 0 : _b.call(_a, issue, ctx).message) !== null && _c !== void 0 ? _c : ctx.defaultError;
                            if (issue.code === "unrecognized_keys")
                                return {
                                    message: (_d = errorUtil.errToObj(message).message) !== null && _d !== void 0 ? _d : defaultError,
                                };
                            return {
                                message: defaultError,
                            };
                        },
                    }
                    : {}),
            });
        }
        strip() {
            return new ZodObject({
                ...this._def,
                unknownKeys: "strip",
            });
        }
        passthrough() {
            return new ZodObject({
                ...this._def,
                unknownKeys: "passthrough",
            });
        }
        // const AugmentFactory =
        //   <Def extends ZodObjectDef>(def: Def) =>
        //   <Augmentation extends ZodRawShape>(
        //     augmentation: Augmentation
        //   ): ZodObject<
        //     extendShape<ReturnType<Def["shape"]>, Augmentation>,
        //     Def["unknownKeys"],
        //     Def["catchall"]
        //   > => {
        //     return new ZodObject({
        //       ...def,
        //       shape: () => ({
        //         ...def.shape(),
        //         ...augmentation,
        //       }),
        //     }) as any;
        //   };
        extend(augmentation) {
            return new ZodObject({
                ...this._def,
                shape: () => ({
                    ...this._def.shape(),
                    ...augmentation,
                }),
            });
        }
        /**
         * Prior to zod@1.0.12 there was a bug in the
         * inferred type of merged objects. Please
         * upgrade if you are experiencing issues.
         */
        merge(merging) {
            const merged = new ZodObject({
                unknownKeys: merging._def.unknownKeys,
                catchall: merging._def.catchall,
                shape: () => ({
                    ...this._def.shape(),
                    ...merging._def.shape(),
                }),
                typeName: ZodFirstPartyTypeKind.ZodObject,
            });
            return merged;
        }
        // merge<
        //   Incoming extends AnyZodObject,
        //   Augmentation extends Incoming["shape"],
        //   NewOutput extends {
        //     [k in keyof Augmentation | keyof Output]: k extends keyof Augmentation
        //       ? Augmentation[k]["_output"]
        //       : k extends keyof Output
        //       ? Output[k]
        //       : never;
        //   },
        //   NewInput extends {
        //     [k in keyof Augmentation | keyof Input]: k extends keyof Augmentation
        //       ? Augmentation[k]["_input"]
        //       : k extends keyof Input
        //       ? Input[k]
        //       : never;
        //   }
        // >(
        //   merging: Incoming
        // ): ZodObject<
        //   extendShape<T, ReturnType<Incoming["_def"]["shape"]>>,
        //   Incoming["_def"]["unknownKeys"],
        //   Incoming["_def"]["catchall"],
        //   NewOutput,
        //   NewInput
        // > {
        //   const merged: any = new ZodObject({
        //     unknownKeys: merging._def.unknownKeys,
        //     catchall: merging._def.catchall,
        //     shape: () =>
        //       objectUtil.mergeShapes(this._def.shape(), merging._def.shape()),
        //     typeName: ZodFirstPartyTypeKind.ZodObject,
        //   }) as any;
        //   return merged;
        // }
        setKey(key, schema) {
            return this.augment({ [key]: schema });
        }
        // merge<Incoming extends AnyZodObject>(
        //   merging: Incoming
        // ): //ZodObject<T & Incoming["_shape"], UnknownKeys, Catchall> = (merging) => {
        // ZodObject<
        //   extendShape<T, ReturnType<Incoming["_def"]["shape"]>>,
        //   Incoming["_def"]["unknownKeys"],
        //   Incoming["_def"]["catchall"]
        // > {
        //   // const mergedShape = objectUtil.mergeShapes(
        //   //   this._def.shape(),
        //   //   merging._def.shape()
        //   // );
        //   const merged: any = new ZodObject({
        //     unknownKeys: merging._def.unknownKeys,
        //     catchall: merging._def.catchall,
        //     shape: () =>
        //       objectUtil.mergeShapes(this._def.shape(), merging._def.shape()),
        //     typeName: ZodFirstPartyTypeKind.ZodObject,
        //   }) as any;
        //   return merged;
        // }
        catchall(index) {
            return new ZodObject({
                ...this._def,
                catchall: index,
            });
        }
        pick(mask) {
            const shape = {};
            util.objectKeys(mask).forEach((key) => {
                if (mask[key] && this.shape[key]) {
                    shape[key] = this.shape[key];
                }
            });
            return new ZodObject({
                ...this._def,
                shape: () => shape,
            });
        }
        omit(mask) {
            const shape = {};
            util.objectKeys(this.shape).forEach((key) => {
                if (!mask[key]) {
                    shape[key] = this.shape[key];
                }
            });
            return new ZodObject({
                ...this._def,
                shape: () => shape,
            });
        }
        /**
         * @deprecated
         */
        deepPartial() {
            return deepPartialify(this);
        }
        partial(mask) {
            const newShape = {};
            util.objectKeys(this.shape).forEach((key) => {
                const fieldSchema = this.shape[key];
                if (mask && !mask[key]) {
                    newShape[key] = fieldSchema;
                }
                else {
                    newShape[key] = fieldSchema.optional();
                }
            });
            return new ZodObject({
                ...this._def,
                shape: () => newShape,
            });
        }
        required(mask) {
            const newShape = {};
            util.objectKeys(this.shape).forEach((key) => {
                if (mask && !mask[key]) {
                    newShape[key] = this.shape[key];
                }
                else {
                    const fieldSchema = this.shape[key];
                    let newField = fieldSchema;
                    while (newField instanceof ZodOptional) {
                        newField = newField._def.innerType;
                    }
                    newShape[key] = newField;
                }
            });
            return new ZodObject({
                ...this._def,
                shape: () => newShape,
            });
        }
        keyof() {
            return createZodEnum(util.objectKeys(this.shape));
        }
    }
    ZodObject.create = (shape, params) => {
        return new ZodObject({
            shape: () => shape,
            unknownKeys: "strip",
            catchall: ZodNever.create(),
            typeName: ZodFirstPartyTypeKind.ZodObject,
            ...processCreateParams(params),
        });
    };
    ZodObject.strictCreate = (shape, params) => {
        return new ZodObject({
            shape: () => shape,
            unknownKeys: "strict",
            catchall: ZodNever.create(),
            typeName: ZodFirstPartyTypeKind.ZodObject,
            ...processCreateParams(params),
        });
    };
    ZodObject.lazycreate = (shape, params) => {
        return new ZodObject({
            shape,
            unknownKeys: "strip",
            catchall: ZodNever.create(),
            typeName: ZodFirstPartyTypeKind.ZodObject,
            ...processCreateParams(params),
        });
    };
    class ZodUnion extends ZodType {
        _parse(input) {
            const { ctx } = this._processInputParams(input);
            const options = this._def.options;
            function handleResults(results) {
                // return first issue-free validation if it exists
                for (const result of results) {
                    if (result.result.status === "valid") {
                        return result.result;
                    }
                }
                for (const result of results) {
                    if (result.result.status === "dirty") {
                        // add issues from dirty option
                        ctx.common.issues.push(...result.ctx.common.issues);
                        return result.result;
                    }
                }
                // return invalid
                const unionErrors = results.map((result) => new ZodError(result.ctx.common.issues));
                addIssueToContext(ctx, {
                    code: ZodIssueCode.invalid_union,
                    unionErrors,
                });
                return INVALID;
            }
            if (ctx.common.async) {
                return Promise.all(options.map(async (option) => {
                    const childCtx = {
                        ...ctx,
                        common: {
                            ...ctx.common,
                            issues: [],
                        },
                        parent: null,
                    };
                    return {
                        result: await option._parseAsync({
                            data: ctx.data,
                            path: ctx.path,
                            parent: childCtx,
                        }),
                        ctx: childCtx,
                    };
                })).then(handleResults);
            }
            else {
                let dirty = undefined;
                const issues = [];
                for (const option of options) {
                    const childCtx = {
                        ...ctx,
                        common: {
                            ...ctx.common,
                            issues: [],
                        },
                        parent: null,
                    };
                    const result = option._parseSync({
                        data: ctx.data,
                        path: ctx.path,
                        parent: childCtx,
                    });
                    if (result.status === "valid") {
                        return result;
                    }
                    else if (result.status === "dirty" && !dirty) {
                        dirty = { result, ctx: childCtx };
                    }
                    if (childCtx.common.issues.length) {
                        issues.push(childCtx.common.issues);
                    }
                }
                if (dirty) {
                    ctx.common.issues.push(...dirty.ctx.common.issues);
                    return dirty.result;
                }
                const unionErrors = issues.map((issues) => new ZodError(issues));
                addIssueToContext(ctx, {
                    code: ZodIssueCode.invalid_union,
                    unionErrors,
                });
                return INVALID;
            }
        }
        get options() {
            return this._def.options;
        }
    }
    ZodUnion.create = (types, params) => {
        return new ZodUnion({
            options: types,
            typeName: ZodFirstPartyTypeKind.ZodUnion,
            ...processCreateParams(params),
        });
    };
    /////////////////////////////////////////////////////
    /////////////////////////////////////////////////////
    //////////                                 //////////
    //////////      ZodDiscriminatedUnion      //////////
    //////////                                 //////////
    /////////////////////////////////////////////////////
    /////////////////////////////////////////////////////
    const getDiscriminator = (type) => {
        if (type instanceof ZodLazy) {
            return getDiscriminator(type.schema);
        }
        else if (type instanceof ZodEffects) {
            return getDiscriminator(type.innerType());
        }
        else if (type instanceof ZodLiteral) {
            return [type.value];
        }
        else if (type instanceof ZodEnum) {
            return type.options;
        }
        else if (type instanceof ZodNativeEnum) {
            // eslint-disable-next-line ban/ban
            return Object.keys(type.enum);
        }
        else if (type instanceof ZodDefault) {
            return getDiscriminator(type._def.innerType);
        }
        else if (type instanceof ZodUndefined) {
            return [undefined];
        }
        else if (type instanceof ZodNull) {
            return [null];
        }
        else {
            return null;
        }
    };
    class ZodDiscriminatedUnion extends ZodType {
        _parse(input) {
            const { ctx } = this._processInputParams(input);
            if (ctx.parsedType !== ZodParsedType.object) {
                addIssueToContext(ctx, {
                    code: ZodIssueCode.invalid_type,
                    expected: ZodParsedType.object,
                    received: ctx.parsedType,
                });
                return INVALID;
            }
            const discriminator = this.discriminator;
            const discriminatorValue = ctx.data[discriminator];
            const option = this.optionsMap.get(discriminatorValue);
            if (!option) {
                addIssueToContext(ctx, {
                    code: ZodIssueCode.invalid_union_discriminator,
                    options: Array.from(this.optionsMap.keys()),
                    path: [discriminator],
                });
                return INVALID;
            }
            if (ctx.common.async) {
                return option._parseAsync({
                    data: ctx.data,
                    path: ctx.path,
                    parent: ctx,
                });
            }
            else {
                return option._parseSync({
                    data: ctx.data,
                    path: ctx.path,
                    parent: ctx,
                });
            }
        }
        get discriminator() {
            return this._def.discriminator;
        }
        get options() {
            return this._def.options;
        }
        get optionsMap() {
            return this._def.optionsMap;
        }
        /**
         * The constructor of the discriminated union schema. Its behaviour is very similar to that of the normal z.union() constructor.
         * However, it only allows a union of objects, all of which need to share a discriminator property. This property must
         * have a different value for each object in the union.
         * @param discriminator the name of the discriminator property
         * @param types an array of object schemas
         * @param params
         */
        static create(discriminator, options, params) {
            // Get all the valid discriminator values
            const optionsMap = new Map();
            // try {
            for (const type of options) {
                const discriminatorValues = getDiscriminator(type.shape[discriminator]);
                if (!discriminatorValues) {
                    throw new Error(`A discriminator value for key \`${discriminator}\` could not be extracted from all schema options`);
                }
                for (const value of discriminatorValues) {
                    if (optionsMap.has(value)) {
                        throw new Error(`Discriminator property ${String(discriminator)} has duplicate value ${String(value)}`);
                    }
                    optionsMap.set(value, type);
                }
            }
            return new ZodDiscriminatedUnion({
                typeName: ZodFirstPartyTypeKind.ZodDiscriminatedUnion,
                discriminator,
                options,
                optionsMap,
                ...processCreateParams(params),
            });
        }
    }
    function mergeValues(a, b) {
        const aType = getParsedType(a);
        const bType = getParsedType(b);
        if (a === b) {
            return { valid: true, data: a };
        }
        else if (aType === ZodParsedType.object && bType === ZodParsedType.object) {
            const bKeys = util.objectKeys(b);
            const sharedKeys = util
                .objectKeys(a)
                .filter((key) => bKeys.indexOf(key) !== -1);
            const newObj = { ...a, ...b };
            for (const key of sharedKeys) {
                const sharedValue = mergeValues(a[key], b[key]);
                if (!sharedValue.valid) {
                    return { valid: false };
                }
                newObj[key] = sharedValue.data;
            }
            return { valid: true, data: newObj };
        }
        else if (aType === ZodParsedType.array && bType === ZodParsedType.array) {
            if (a.length !== b.length) {
                return { valid: false };
            }
            const newArray = [];
            for (let index = 0; index < a.length; index++) {
                const itemA = a[index];
                const itemB = b[index];
                const sharedValue = mergeValues(itemA, itemB);
                if (!sharedValue.valid) {
                    return { valid: false };
                }
                newArray.push(sharedValue.data);
            }
            return { valid: true, data: newArray };
        }
        else if (aType === ZodParsedType.date &&
            bType === ZodParsedType.date &&
            +a === +b) {
            return { valid: true, data: a };
        }
        else {
            return { valid: false };
        }
    }
    class ZodIntersection extends ZodType {
        _parse(input) {
            const { status, ctx } = this._processInputParams(input);
            const handleParsed = (parsedLeft, parsedRight) => {
                if (isAborted(parsedLeft) || isAborted(parsedRight)) {
                    return INVALID;
                }
                const merged = mergeValues(parsedLeft.value, parsedRight.value);
                if (!merged.valid) {
                    addIssueToContext(ctx, {
                        code: ZodIssueCode.invalid_intersection_types,
                    });
                    return INVALID;
                }
                if (isDirty(parsedLeft) || isDirty(parsedRight)) {
                    status.dirty();
                }
                return { status: status.value, value: merged.data };
            };
            if (ctx.common.async) {
                return Promise.all([
                    this._def.left._parseAsync({
                        data: ctx.data,
                        path: ctx.path,
                        parent: ctx,
                    }),
                    this._def.right._parseAsync({
                        data: ctx.data,
                        path: ctx.path,
                        parent: ctx,
                    }),
                ]).then(([left, right]) => handleParsed(left, right));
            }
            else {
                return handleParsed(this._def.left._parseSync({
                    data: ctx.data,
                    path: ctx.path,
                    parent: ctx,
                }), this._def.right._parseSync({
                    data: ctx.data,
                    path: ctx.path,
                    parent: ctx,
                }));
            }
        }
    }
    ZodIntersection.create = (left, right, params) => {
        return new ZodIntersection({
            left: left,
            right: right,
            typeName: ZodFirstPartyTypeKind.ZodIntersection,
            ...processCreateParams(params),
        });
    };
    class ZodTuple extends ZodType {
        _parse(input) {
            const { status, ctx } = this._processInputParams(input);
            if (ctx.parsedType !== ZodParsedType.array) {
                addIssueToContext(ctx, {
                    code: ZodIssueCode.invalid_type,
                    expected: ZodParsedType.array,
                    received: ctx.parsedType,
                });
                return INVALID;
            }
            if (ctx.data.length < this._def.items.length) {
                addIssueToContext(ctx, {
                    code: ZodIssueCode.too_small,
                    minimum: this._def.items.length,
                    inclusive: true,
                    exact: false,
                    type: "array",
                });
                return INVALID;
            }
            const rest = this._def.rest;
            if (!rest && ctx.data.length > this._def.items.length) {
                addIssueToContext(ctx, {
                    code: ZodIssueCode.too_big,
                    maximum: this._def.items.length,
                    inclusive: true,
                    exact: false,
                    type: "array",
                });
                status.dirty();
            }
            const items = [...ctx.data]
                .map((item, itemIndex) => {
                const schema = this._def.items[itemIndex] || this._def.rest;
                if (!schema)
                    return null;
                return schema._parse(new ParseInputLazyPath(ctx, item, ctx.path, itemIndex));
            })
                .filter((x) => !!x); // filter nulls
            if (ctx.common.async) {
                return Promise.all(items).then((results) => {
                    return ParseStatus.mergeArray(status, results);
                });
            }
            else {
                return ParseStatus.mergeArray(status, items);
            }
        }
        get items() {
            return this._def.items;
        }
        rest(rest) {
            return new ZodTuple({
                ...this._def,
                rest,
            });
        }
    }
    ZodTuple.create = (schemas, params) => {
        if (!Array.isArray(schemas)) {
            throw new Error("You must pass an array of schemas to z.tuple([ ... ])");
        }
        return new ZodTuple({
            items: schemas,
            typeName: ZodFirstPartyTypeKind.ZodTuple,
            rest: null,
            ...processCreateParams(params),
        });
    };
    class ZodRecord extends ZodType {
        get keySchema() {
            return this._def.keyType;
        }
        get valueSchema() {
            return this._def.valueType;
        }
        _parse(input) {
            const { status, ctx } = this._processInputParams(input);
            if (ctx.parsedType !== ZodParsedType.object) {
                addIssueToContext(ctx, {
                    code: ZodIssueCode.invalid_type,
                    expected: ZodParsedType.object,
                    received: ctx.parsedType,
                });
                return INVALID;
            }
            const pairs = [];
            const keyType = this._def.keyType;
            const valueType = this._def.valueType;
            for (const key in ctx.data) {
                pairs.push({
                    key: keyType._parse(new ParseInputLazyPath(ctx, key, ctx.path, key)),
                    value: valueType._parse(new ParseInputLazyPath(ctx, ctx.data[key], ctx.path, key)),
                });
            }
            if (ctx.common.async) {
                return ParseStatus.mergeObjectAsync(status, pairs);
            }
            else {
                return ParseStatus.mergeObjectSync(status, pairs);
            }
        }
        get element() {
            return this._def.valueType;
        }
        static create(first, second, third) {
            if (second instanceof ZodType) {
                return new ZodRecord({
                    keyType: first,
                    valueType: second,
                    typeName: ZodFirstPartyTypeKind.ZodRecord,
                    ...processCreateParams(third),
                });
            }
            return new ZodRecord({
                keyType: ZodString.create(),
                valueType: first,
                typeName: ZodFirstPartyTypeKind.ZodRecord,
                ...processCreateParams(second),
            });
        }
    }
    class ZodMap extends ZodType {
        _parse(input) {
            const { status, ctx } = this._processInputParams(input);
            if (ctx.parsedType !== ZodParsedType.map) {
                addIssueToContext(ctx, {
                    code: ZodIssueCode.invalid_type,
                    expected: ZodParsedType.map,
                    received: ctx.parsedType,
                });
                return INVALID;
            }
            const keyType = this._def.keyType;
            const valueType = this._def.valueType;
            const pairs = [...ctx.data.entries()].map(([key, value], index) => {
                return {
                    key: keyType._parse(new ParseInputLazyPath(ctx, key, ctx.path, [index, "key"])),
                    value: valueType._parse(new ParseInputLazyPath(ctx, value, ctx.path, [index, "value"])),
                };
            });
            if (ctx.common.async) {
                const finalMap = new Map();
                return Promise.resolve().then(async () => {
                    for (const pair of pairs) {
                        const key = await pair.key;
                        const value = await pair.value;
                        if (key.status === "aborted" || value.status === "aborted") {
                            return INVALID;
                        }
                        if (key.status === "dirty" || value.status === "dirty") {
                            status.dirty();
                        }
                        finalMap.set(key.value, value.value);
                    }
                    return { status: status.value, value: finalMap };
                });
            }
            else {
                const finalMap = new Map();
                for (const pair of pairs) {
                    const key = pair.key;
                    const value = pair.value;
                    if (key.status === "aborted" || value.status === "aborted") {
                        return INVALID;
                    }
                    if (key.status === "dirty" || value.status === "dirty") {
                        status.dirty();
                    }
                    finalMap.set(key.value, value.value);
                }
                return { status: status.value, value: finalMap };
            }
        }
    }
    ZodMap.create = (keyType, valueType, params) => {
        return new ZodMap({
            valueType,
            keyType,
            typeName: ZodFirstPartyTypeKind.ZodMap,
            ...processCreateParams(params),
        });
    };
    class ZodSet extends ZodType {
        _parse(input) {
            const { status, ctx } = this._processInputParams(input);
            if (ctx.parsedType !== ZodParsedType.set) {
                addIssueToContext(ctx, {
                    code: ZodIssueCode.invalid_type,
                    expected: ZodParsedType.set,
                    received: ctx.parsedType,
                });
                return INVALID;
            }
            const def = this._def;
            if (def.minSize !== null) {
                if (ctx.data.size < def.minSize.value) {
                    addIssueToContext(ctx, {
                        code: ZodIssueCode.too_small,
                        minimum: def.minSize.value,
                        type: "set",
                        inclusive: true,
                        exact: false,
                        message: def.minSize.message,
                    });
                    status.dirty();
                }
            }
            if (def.maxSize !== null) {
                if (ctx.data.size > def.maxSize.value) {
                    addIssueToContext(ctx, {
                        code: ZodIssueCode.too_big,
                        maximum: def.maxSize.value,
                        type: "set",
                        inclusive: true,
                        exact: false,
                        message: def.maxSize.message,
                    });
                    status.dirty();
                }
            }
            const valueType = this._def.valueType;
            function finalizeSet(elements) {
                const parsedSet = new Set();
                for (const element of elements) {
                    if (element.status === "aborted")
                        return INVALID;
                    if (element.status === "dirty")
                        status.dirty();
                    parsedSet.add(element.value);
                }
                return { status: status.value, value: parsedSet };
            }
            const elements = [...ctx.data.values()].map((item, i) => valueType._parse(new ParseInputLazyPath(ctx, item, ctx.path, i)));
            if (ctx.common.async) {
                return Promise.all(elements).then((elements) => finalizeSet(elements));
            }
            else {
                return finalizeSet(elements);
            }
        }
        min(minSize, message) {
            return new ZodSet({
                ...this._def,
                minSize: { value: minSize, message: errorUtil.toString(message) },
            });
        }
        max(maxSize, message) {
            return new ZodSet({
                ...this._def,
                maxSize: { value: maxSize, message: errorUtil.toString(message) },
            });
        }
        size(size, message) {
            return this.min(size, message).max(size, message);
        }
        nonempty(message) {
            return this.min(1, message);
        }
    }
    ZodSet.create = (valueType, params) => {
        return new ZodSet({
            valueType,
            minSize: null,
            maxSize: null,
            typeName: ZodFirstPartyTypeKind.ZodSet,
            ...processCreateParams(params),
        });
    };
    class ZodFunction extends ZodType {
        constructor() {
            super(...arguments);
            this.validate = this.implement;
        }
        _parse(input) {
            const { ctx } = this._processInputParams(input);
            if (ctx.parsedType !== ZodParsedType.function) {
                addIssueToContext(ctx, {
                    code: ZodIssueCode.invalid_type,
                    expected: ZodParsedType.function,
                    received: ctx.parsedType,
                });
                return INVALID;
            }
            function makeArgsIssue(args, error) {
                return makeIssue({
                    data: args,
                    path: ctx.path,
                    errorMaps: [
                        ctx.common.contextualErrorMap,
                        ctx.schemaErrorMap,
                        getErrorMap(),
                        errorMap,
                    ].filter((x) => !!x),
                    issueData: {
                        code: ZodIssueCode.invalid_arguments,
                        argumentsError: error,
                    },
                });
            }
            function makeReturnsIssue(returns, error) {
                return makeIssue({
                    data: returns,
                    path: ctx.path,
                    errorMaps: [
                        ctx.common.contextualErrorMap,
                        ctx.schemaErrorMap,
                        getErrorMap(),
                        errorMap,
                    ].filter((x) => !!x),
                    issueData: {
                        code: ZodIssueCode.invalid_return_type,
                        returnTypeError: error,
                    },
                });
            }
            const params = { errorMap: ctx.common.contextualErrorMap };
            const fn = ctx.data;
            if (this._def.returns instanceof ZodPromise) {
                return OK(async (...args) => {
                    const error = new ZodError([]);
                    const parsedArgs = await this._def.args
                        .parseAsync(args, params)
                        .catch((e) => {
                        error.addIssue(makeArgsIssue(args, e));
                        throw error;
                    });
                    const result = await fn(...parsedArgs);
                    const parsedReturns = await this._def.returns._def.type
                        .parseAsync(result, params)
                        .catch((e) => {
                        error.addIssue(makeReturnsIssue(result, e));
                        throw error;
                    });
                    return parsedReturns;
                });
            }
            else {
                return OK((...args) => {
                    const parsedArgs = this._def.args.safeParse(args, params);
                    if (!parsedArgs.success) {
                        throw new ZodError([makeArgsIssue(args, parsedArgs.error)]);
                    }
                    const result = fn(...parsedArgs.data);
                    const parsedReturns = this._def.returns.safeParse(result, params);
                    if (!parsedReturns.success) {
                        throw new ZodError([makeReturnsIssue(result, parsedReturns.error)]);
                    }
                    return parsedReturns.data;
                });
            }
        }
        parameters() {
            return this._def.args;
        }
        returnType() {
            return this._def.returns;
        }
        args(...items) {
            return new ZodFunction({
                ...this._def,
                args: ZodTuple.create(items).rest(ZodUnknown.create()),
            });
        }
        returns(returnType) {
            return new ZodFunction({
                ...this._def,
                returns: returnType,
            });
        }
        implement(func) {
            const validatedFunc = this.parse(func);
            return validatedFunc;
        }
        strictImplement(func) {
            const validatedFunc = this.parse(func);
            return validatedFunc;
        }
        static create(args, returns, params) {
            return new ZodFunction({
                args: (args
                    ? args
                    : ZodTuple.create([]).rest(ZodUnknown.create())),
                returns: returns || ZodUnknown.create(),
                typeName: ZodFirstPartyTypeKind.ZodFunction,
                ...processCreateParams(params),
            });
        }
    }
    class ZodLazy extends ZodType {
        get schema() {
            return this._def.getter();
        }
        _parse(input) {
            const { ctx } = this._processInputParams(input);
            const lazySchema = this._def.getter();
            return lazySchema._parse({ data: ctx.data, path: ctx.path, parent: ctx });
        }
    }
    ZodLazy.create = (getter, params) => {
        return new ZodLazy({
            getter: getter,
            typeName: ZodFirstPartyTypeKind.ZodLazy,
            ...processCreateParams(params),
        });
    };
    class ZodLiteral extends ZodType {
        _parse(input) {
            if (input.data !== this._def.value) {
                const ctx = this._getOrReturnCtx(input);
                addIssueToContext(ctx, {
                    received: ctx.data,
                    code: ZodIssueCode.invalid_literal,
                    expected: this._def.value,
                });
                return INVALID;
            }
            return { status: "valid", value: input.data };
        }
        get value() {
            return this._def.value;
        }
    }
    ZodLiteral.create = (value, params) => {
        return new ZodLiteral({
            value: value,
            typeName: ZodFirstPartyTypeKind.ZodLiteral,
            ...processCreateParams(params),
        });
    };
    function createZodEnum(values, params) {
        return new ZodEnum({
            values: values,
            typeName: ZodFirstPartyTypeKind.ZodEnum,
            ...processCreateParams(params),
        });
    }
    class ZodEnum extends ZodType {
        _parse(input) {
            if (typeof input.data !== "string") {
                const ctx = this._getOrReturnCtx(input);
                const expectedValues = this._def.values;
                addIssueToContext(ctx, {
                    expected: util.joinValues(expectedValues),
                    received: ctx.parsedType,
                    code: ZodIssueCode.invalid_type,
                });
                return INVALID;
            }
            if (this._def.values.indexOf(input.data) === -1) {
                const ctx = this._getOrReturnCtx(input);
                const expectedValues = this._def.values;
                addIssueToContext(ctx, {
                    received: ctx.data,
                    code: ZodIssueCode.invalid_enum_value,
                    options: expectedValues,
                });
                return INVALID;
            }
            return OK(input.data);
        }
        get options() {
            return this._def.values;
        }
        get enum() {
            const enumValues = {};
            for (const val of this._def.values) {
                enumValues[val] = val;
            }
            return enumValues;
        }
        get Values() {
            const enumValues = {};
            for (const val of this._def.values) {
                enumValues[val] = val;
            }
            return enumValues;
        }
        get Enum() {
            const enumValues = {};
            for (const val of this._def.values) {
                enumValues[val] = val;
            }
            return enumValues;
        }
        extract(values) {
            return ZodEnum.create(values);
        }
        exclude(values) {
            return ZodEnum.create(this.options.filter((opt) => !values.includes(opt)));
        }
    }
    ZodEnum.create = createZodEnum;
    class ZodNativeEnum extends ZodType {
        _parse(input) {
            const nativeEnumValues = util.getValidEnumValues(this._def.values);
            const ctx = this._getOrReturnCtx(input);
            if (ctx.parsedType !== ZodParsedType.string &&
                ctx.parsedType !== ZodParsedType.number) {
                const expectedValues = util.objectValues(nativeEnumValues);
                addIssueToContext(ctx, {
                    expected: util.joinValues(expectedValues),
                    received: ctx.parsedType,
                    code: ZodIssueCode.invalid_type,
                });
                return INVALID;
            }
            if (nativeEnumValues.indexOf(input.data) === -1) {
                const expectedValues = util.objectValues(nativeEnumValues);
                addIssueToContext(ctx, {
                    received: ctx.data,
                    code: ZodIssueCode.invalid_enum_value,
                    options: expectedValues,
                });
                return INVALID;
            }
            return OK(input.data);
        }
        get enum() {
            return this._def.values;
        }
    }
    ZodNativeEnum.create = (values, params) => {
        return new ZodNativeEnum({
            values: values,
            typeName: ZodFirstPartyTypeKind.ZodNativeEnum,
            ...processCreateParams(params),
        });
    };
    class ZodPromise extends ZodType {
        unwrap() {
            return this._def.type;
        }
        _parse(input) {
            const { ctx } = this._processInputParams(input);
            if (ctx.parsedType !== ZodParsedType.promise &&
                ctx.common.async === false) {
                addIssueToContext(ctx, {
                    code: ZodIssueCode.invalid_type,
                    expected: ZodParsedType.promise,
                    received: ctx.parsedType,
                });
                return INVALID;
            }
            const promisified = ctx.parsedType === ZodParsedType.promise
                ? ctx.data
                : Promise.resolve(ctx.data);
            return OK(promisified.then((data) => {
                return this._def.type.parseAsync(data, {
                    path: ctx.path,
                    errorMap: ctx.common.contextualErrorMap,
                });
            }));
        }
    }
    ZodPromise.create = (schema, params) => {
        return new ZodPromise({
            type: schema,
            typeName: ZodFirstPartyTypeKind.ZodPromise,
            ...processCreateParams(params),
        });
    };
    class ZodEffects extends ZodType {
        innerType() {
            return this._def.schema;
        }
        sourceType() {
            return this._def.schema._def.typeName === ZodFirstPartyTypeKind.ZodEffects
                ? this._def.schema.sourceType()
                : this._def.schema;
        }
        _parse(input) {
            const { status, ctx } = this._processInputParams(input);
            const effect = this._def.effect || null;
            if (effect.type === "preprocess") {
                const processed = effect.transform(ctx.data);
                if (ctx.common.async) {
                    return Promise.resolve(processed).then((processed) => {
                        return this._def.schema._parseAsync({
                            data: processed,
                            path: ctx.path,
                            parent: ctx,
                        });
                    });
                }
                else {
                    return this._def.schema._parseSync({
                        data: processed,
                        path: ctx.path,
                        parent: ctx,
                    });
                }
            }
            const checkCtx = {
                addIssue: (arg) => {
                    addIssueToContext(ctx, arg);
                    if (arg.fatal) {
                        status.abort();
                    }
                    else {
                        status.dirty();
                    }
                },
                get path() {
                    return ctx.path;
                },
            };
            checkCtx.addIssue = checkCtx.addIssue.bind(checkCtx);
            if (effect.type === "refinement") {
                const executeRefinement = (acc
                // effect: RefinementEffect<any>
                ) => {
                    const result = effect.refinement(acc, checkCtx);
                    if (ctx.common.async) {
                        return Promise.resolve(result);
                    }
                    if (result instanceof Promise) {
                        throw new Error("Async refinement encountered during synchronous parse operation. Use .parseAsync instead.");
                    }
                    return acc;
                };
                if (ctx.common.async === false) {
                    const inner = this._def.schema._parseSync({
                        data: ctx.data,
                        path: ctx.path,
                        parent: ctx,
                    });
                    if (inner.status === "aborted")
                        return INVALID;
                    if (inner.status === "dirty")
                        status.dirty();
                    // return value is ignored
                    executeRefinement(inner.value);
                    return { status: status.value, value: inner.value };
                }
                else {
                    return this._def.schema
                        ._parseAsync({ data: ctx.data, path: ctx.path, parent: ctx })
                        .then((inner) => {
                        if (inner.status === "aborted")
                            return INVALID;
                        if (inner.status === "dirty")
                            status.dirty();
                        return executeRefinement(inner.value).then(() => {
                            return { status: status.value, value: inner.value };
                        });
                    });
                }
            }
            if (effect.type === "transform") {
                if (ctx.common.async === false) {
                    const base = this._def.schema._parseSync({
                        data: ctx.data,
                        path: ctx.path,
                        parent: ctx,
                    });
                    if (!isValid(base))
                        return base;
                    const result = effect.transform(base.value, checkCtx);
                    if (result instanceof Promise) {
                        throw new Error(`Asynchronous transform encountered during synchronous parse operation. Use .parseAsync instead.`);
                    }
                    return { status: status.value, value: result };
                }
                else {
                    return this._def.schema
                        ._parseAsync({ data: ctx.data, path: ctx.path, parent: ctx })
                        .then((base) => {
                        if (!isValid(base))
                            return base;
                        return Promise.resolve(effect.transform(base.value, checkCtx)).then((result) => ({ status: status.value, value: result }));
                    });
                }
            }
            util.assertNever(effect);
        }
    }
    ZodEffects.create = (schema, effect, params) => {
        return new ZodEffects({
            schema,
            typeName: ZodFirstPartyTypeKind.ZodEffects,
            effect,
            ...processCreateParams(params),
        });
    };
    ZodEffects.createWithPreprocess = (preprocess, schema, params) => {
        return new ZodEffects({
            schema,
            effect: { type: "preprocess", transform: preprocess },
            typeName: ZodFirstPartyTypeKind.ZodEffects,
            ...processCreateParams(params),
        });
    };
    class ZodOptional extends ZodType {
        _parse(input) {
            const parsedType = this._getType(input);
            if (parsedType === ZodParsedType.undefined) {
                return OK(undefined);
            }
            return this._def.innerType._parse(input);
        }
        unwrap() {
            return this._def.innerType;
        }
    }
    ZodOptional.create = (type, params) => {
        return new ZodOptional({
            innerType: type,
            typeName: ZodFirstPartyTypeKind.ZodOptional,
            ...processCreateParams(params),
        });
    };
    class ZodNullable extends ZodType {
        _parse(input) {
            const parsedType = this._getType(input);
            if (parsedType === ZodParsedType.null) {
                return OK(null);
            }
            return this._def.innerType._parse(input);
        }
        unwrap() {
            return this._def.innerType;
        }
    }
    ZodNullable.create = (type, params) => {
        return new ZodNullable({
            innerType: type,
            typeName: ZodFirstPartyTypeKind.ZodNullable,
            ...processCreateParams(params),
        });
    };
    class ZodDefault extends ZodType {
        _parse(input) {
            const { ctx } = this._processInputParams(input);
            let data = ctx.data;
            if (ctx.parsedType === ZodParsedType.undefined) {
                data = this._def.defaultValue();
            }
            return this._def.innerType._parse({
                data,
                path: ctx.path,
                parent: ctx,
            });
        }
        removeDefault() {
            return this._def.innerType;
        }
    }
    ZodDefault.create = (type, params) => {
        return new ZodDefault({
            innerType: type,
            typeName: ZodFirstPartyTypeKind.ZodDefault,
            defaultValue: typeof params.default === "function"
                ? params.default
                : () => params.default,
            ...processCreateParams(params),
        });
    };
    class ZodCatch extends ZodType {
        _parse(input) {
            const { ctx } = this._processInputParams(input);
            // newCtx is used to not collect issues from inner types in ctx
            const newCtx = {
                ...ctx,
                common: {
                    ...ctx.common,
                    issues: [],
                },
            };
            const result = this._def.innerType._parse({
                data: newCtx.data,
                path: newCtx.path,
                parent: {
                    ...newCtx,
                },
            });
            if (isAsync(result)) {
                return result.then((result) => {
                    return {
                        status: "valid",
                        value: result.status === "valid"
                            ? result.value
                            : this._def.catchValue({
                                get error() {
                                    return new ZodError(newCtx.common.issues);
                                },
                                input: newCtx.data,
                            }),
                    };
                });
            }
            else {
                return {
                    status: "valid",
                    value: result.status === "valid"
                        ? result.value
                        : this._def.catchValue({
                            get error() {
                                return new ZodError(newCtx.common.issues);
                            },
                            input: newCtx.data,
                        }),
                };
            }
        }
        removeCatch() {
            return this._def.innerType;
        }
    }
    ZodCatch.create = (type, params) => {
        return new ZodCatch({
            innerType: type,
            typeName: ZodFirstPartyTypeKind.ZodCatch,
            catchValue: typeof params.catch === "function" ? params.catch : () => params.catch,
            ...processCreateParams(params),
        });
    };
    class ZodNaN extends ZodType {
        _parse(input) {
            const parsedType = this._getType(input);
            if (parsedType !== ZodParsedType.nan) {
                const ctx = this._getOrReturnCtx(input);
                addIssueToContext(ctx, {
                    code: ZodIssueCode.invalid_type,
                    expected: ZodParsedType.nan,
                    received: ctx.parsedType,
                });
                return INVALID;
            }
            return { status: "valid", value: input.data };
        }
    }
    ZodNaN.create = (params) => {
        return new ZodNaN({
            typeName: ZodFirstPartyTypeKind.ZodNaN,
            ...processCreateParams(params),
        });
    };
    const BRAND = Symbol("zod_brand");
    class ZodBranded extends ZodType {
        _parse(input) {
            const { ctx } = this._processInputParams(input);
            const data = ctx.data;
            return this._def.type._parse({
                data,
                path: ctx.path,
                parent: ctx,
            });
        }
        unwrap() {
            return this._def.type;
        }
    }
    class ZodPipeline extends ZodType {
        _parse(input) {
            const { status, ctx } = this._processInputParams(input);
            if (ctx.common.async) {
                const handleAsync = async () => {
                    const inResult = await this._def.in._parseAsync({
                        data: ctx.data,
                        path: ctx.path,
                        parent: ctx,
                    });
                    if (inResult.status === "aborted")
                        return INVALID;
                    if (inResult.status === "dirty") {
                        status.dirty();
                        return DIRTY(inResult.value);
                    }
                    else {
                        return this._def.out._parseAsync({
                            data: inResult.value,
                            path: ctx.path,
                            parent: ctx,
                        });
                    }
                };
                return handleAsync();
            }
            else {
                const inResult = this._def.in._parseSync({
                    data: ctx.data,
                    path: ctx.path,
                    parent: ctx,
                });
                if (inResult.status === "aborted")
                    return INVALID;
                if (inResult.status === "dirty") {
                    status.dirty();
                    return {
                        status: "dirty",
                        value: inResult.value,
                    };
                }
                else {
                    return this._def.out._parseSync({
                        data: inResult.value,
                        path: ctx.path,
                        parent: ctx,
                    });
                }
            }
        }
        static create(a, b) {
            return new ZodPipeline({
                in: a,
                out: b,
                typeName: ZodFirstPartyTypeKind.ZodPipeline,
            });
        }
    }
    const custom = (check, params = {}, 
    /*
     * @deprecated
     *
     * Pass `fatal` into the params object instead:
     *
     * ```ts
     * z.string().custom((val) => val.length > 5, { fatal: false })
     * ```
     *
     */
    fatal) => {
        if (check)
            return ZodAny.create().superRefine((data, ctx) => {
                var _a, _b;
                if (!check(data)) {
                    const p = typeof params === "function"
                        ? params(data)
                        : typeof params === "string"
                            ? { message: params }
                            : params;
                    const _fatal = (_b = (_a = p.fatal) !== null && _a !== void 0 ? _a : fatal) !== null && _b !== void 0 ? _b : true;
                    const p2 = typeof p === "string" ? { message: p } : p;
                    ctx.addIssue({ code: "custom", ...p2, fatal: _fatal });
                }
            });
        return ZodAny.create();
    };
    const late = {
        object: ZodObject.lazycreate,
    };
    var ZodFirstPartyTypeKind;
    (function (ZodFirstPartyTypeKind) {
        ZodFirstPartyTypeKind["ZodString"] = "ZodString";
        ZodFirstPartyTypeKind["ZodNumber"] = "ZodNumber";
        ZodFirstPartyTypeKind["ZodNaN"] = "ZodNaN";
        ZodFirstPartyTypeKind["ZodBigInt"] = "ZodBigInt";
        ZodFirstPartyTypeKind["ZodBoolean"] = "ZodBoolean";
        ZodFirstPartyTypeKind["ZodDate"] = "ZodDate";
        ZodFirstPartyTypeKind["ZodSymbol"] = "ZodSymbol";
        ZodFirstPartyTypeKind["ZodUndefined"] = "ZodUndefined";
        ZodFirstPartyTypeKind["ZodNull"] = "ZodNull";
        ZodFirstPartyTypeKind["ZodAny"] = "ZodAny";
        ZodFirstPartyTypeKind["ZodUnknown"] = "ZodUnknown";
        ZodFirstPartyTypeKind["ZodNever"] = "ZodNever";
        ZodFirstPartyTypeKind["ZodVoid"] = "ZodVoid";
        ZodFirstPartyTypeKind["ZodArray"] = "ZodArray";
        ZodFirstPartyTypeKind["ZodObject"] = "ZodObject";
        ZodFirstPartyTypeKind["ZodUnion"] = "ZodUnion";
        ZodFirstPartyTypeKind["ZodDiscriminatedUnion"] = "ZodDiscriminatedUnion";
        ZodFirstPartyTypeKind["ZodIntersection"] = "ZodIntersection";
        ZodFirstPartyTypeKind["ZodTuple"] = "ZodTuple";
        ZodFirstPartyTypeKind["ZodRecord"] = "ZodRecord";
        ZodFirstPartyTypeKind["ZodMap"] = "ZodMap";
        ZodFirstPartyTypeKind["ZodSet"] = "ZodSet";
        ZodFirstPartyTypeKind["ZodFunction"] = "ZodFunction";
        ZodFirstPartyTypeKind["ZodLazy"] = "ZodLazy";
        ZodFirstPartyTypeKind["ZodLiteral"] = "ZodLiteral";
        ZodFirstPartyTypeKind["ZodEnum"] = "ZodEnum";
        ZodFirstPartyTypeKind["ZodEffects"] = "ZodEffects";
        ZodFirstPartyTypeKind["ZodNativeEnum"] = "ZodNativeEnum";
        ZodFirstPartyTypeKind["ZodOptional"] = "ZodOptional";
        ZodFirstPartyTypeKind["ZodNullable"] = "ZodNullable";
        ZodFirstPartyTypeKind["ZodDefault"] = "ZodDefault";
        ZodFirstPartyTypeKind["ZodCatch"] = "ZodCatch";
        ZodFirstPartyTypeKind["ZodPromise"] = "ZodPromise";
        ZodFirstPartyTypeKind["ZodBranded"] = "ZodBranded";
        ZodFirstPartyTypeKind["ZodPipeline"] = "ZodPipeline";
    })(ZodFirstPartyTypeKind || (ZodFirstPartyTypeKind = {}));
    const instanceOfType = (
    // const instanceOfType = <T extends new (...args: any[]) => any>(
    cls, params = {
        message: `Input not instance of ${cls.name}`,
    }) => custom((data) => data instanceof cls, params);
    const stringType = ZodString.create;
    const numberType = ZodNumber.create;
    const nanType = ZodNaN.create;
    const bigIntType = ZodBigInt.create;
    const booleanType = ZodBoolean.create;
    const dateType = ZodDate.create;
    const symbolType = ZodSymbol.create;
    const undefinedType = ZodUndefined.create;
    const nullType = ZodNull.create;
    const anyType = ZodAny.create;
    const unknownType = ZodUnknown.create;
    const neverType = ZodNever.create;
    const voidType = ZodVoid.create;
    const arrayType = ZodArray.create;
    const objectType = ZodObject.create;
    const strictObjectType = ZodObject.strictCreate;
    const unionType = ZodUnion.create;
    const discriminatedUnionType = ZodDiscriminatedUnion.create;
    const intersectionType = ZodIntersection.create;
    const tupleType = ZodTuple.create;
    const recordType = ZodRecord.create;
    const mapType = ZodMap.create;
    const setType = ZodSet.create;
    const functionType = ZodFunction.create;
    const lazyType = ZodLazy.create;
    const literalType = ZodLiteral.create;
    const enumType = ZodEnum.create;
    const nativeEnumType = ZodNativeEnum.create;
    const promiseType = ZodPromise.create;
    const effectsType = ZodEffects.create;
    const optionalType = ZodOptional.create;
    const nullableType = ZodNullable.create;
    const preprocessType = ZodEffects.createWithPreprocess;
    const pipelineType = ZodPipeline.create;
    const ostring = () => stringType().optional();
    const onumber = () => numberType().optional();
    const oboolean = () => booleanType().optional();
    const coerce = {
        string: ((arg) => ZodString.create({ ...arg, coerce: true })),
        number: ((arg) => ZodNumber.create({ ...arg, coerce: true })),
        boolean: ((arg) => ZodBoolean.create({
            ...arg,
            coerce: true,
        })),
        bigint: ((arg) => ZodBigInt.create({ ...arg, coerce: true })),
        date: ((arg) => ZodDate.create({ ...arg, coerce: true })),
    };
    const NEVER = INVALID;

    var z = /*#__PURE__*/Object.freeze({
        __proto__: null,
        defaultErrorMap: errorMap,
        setErrorMap: setErrorMap,
        getErrorMap: getErrorMap,
        makeIssue: makeIssue,
        EMPTY_PATH: EMPTY_PATH,
        addIssueToContext: addIssueToContext,
        ParseStatus: ParseStatus,
        INVALID: INVALID,
        DIRTY: DIRTY,
        OK: OK,
        isAborted: isAborted,
        isDirty: isDirty,
        isValid: isValid,
        isAsync: isAsync,
        get util () { return util; },
        get objectUtil () { return objectUtil; },
        ZodParsedType: ZodParsedType,
        getParsedType: getParsedType,
        ZodType: ZodType,
        ZodString: ZodString,
        ZodNumber: ZodNumber,
        ZodBigInt: ZodBigInt,
        ZodBoolean: ZodBoolean,
        ZodDate: ZodDate,
        ZodSymbol: ZodSymbol,
        ZodUndefined: ZodUndefined,
        ZodNull: ZodNull,
        ZodAny: ZodAny,
        ZodUnknown: ZodUnknown,
        ZodNever: ZodNever,
        ZodVoid: ZodVoid,
        ZodArray: ZodArray,
        ZodObject: ZodObject,
        ZodUnion: ZodUnion,
        ZodDiscriminatedUnion: ZodDiscriminatedUnion,
        ZodIntersection: ZodIntersection,
        ZodTuple: ZodTuple,
        ZodRecord: ZodRecord,
        ZodMap: ZodMap,
        ZodSet: ZodSet,
        ZodFunction: ZodFunction,
        ZodLazy: ZodLazy,
        ZodLiteral: ZodLiteral,
        ZodEnum: ZodEnum,
        ZodNativeEnum: ZodNativeEnum,
        ZodPromise: ZodPromise,
        ZodEffects: ZodEffects,
        ZodTransformer: ZodEffects,
        ZodOptional: ZodOptional,
        ZodNullable: ZodNullable,
        ZodDefault: ZodDefault,
        ZodCatch: ZodCatch,
        ZodNaN: ZodNaN,
        BRAND: BRAND,
        ZodBranded: ZodBranded,
        ZodPipeline: ZodPipeline,
        custom: custom,
        Schema: ZodType,
        ZodSchema: ZodType,
        late: late,
        get ZodFirstPartyTypeKind () { return ZodFirstPartyTypeKind; },
        coerce: coerce,
        any: anyType,
        array: arrayType,
        bigint: bigIntType,
        boolean: booleanType,
        date: dateType,
        discriminatedUnion: discriminatedUnionType,
        effect: effectsType,
        'enum': enumType,
        'function': functionType,
        'instanceof': instanceOfType,
        intersection: intersectionType,
        lazy: lazyType,
        literal: literalType,
        map: mapType,
        nan: nanType,
        nativeEnum: nativeEnumType,
        never: neverType,
        'null': nullType,
        nullable: nullableType,
        number: numberType,
        object: objectType,
        oboolean: oboolean,
        onumber: onumber,
        optional: optionalType,
        ostring: ostring,
        pipeline: pipelineType,
        preprocess: preprocessType,
        promise: promiseType,
        record: recordType,
        set: setType,
        strictObject: strictObjectType,
        string: stringType,
        symbol: symbolType,
        transformer: effectsType,
        tuple: tupleType,
        'undefined': undefinedType,
        union: unionType,
        unknown: unknownType,
        'void': voidType,
        NEVER: NEVER,
        ZodIssueCode: ZodIssueCode,
        quotelessJson: quotelessJson,
        ZodError: ZodError
    });

    /*
     * AGTree v2.1.2 (build date: Thu, 19 Sep 2024 15:44:40 GMT)
     * (c) 2024 Adguard Software Ltd.
     * Released under the MIT license
     * https://github.com/AdguardTeam/tsurlfilter/tree/master/packages/agtree#readme
     */

    /**
     * @file Possible adblock syntaxes are listed here.
     */
    /**
     * Possible adblock syntaxes (supported by this library)
     */
    var AdblockSyntax;
    (function (AdblockSyntax) {
        /**
         * Common syntax, which is supported by more than one adblocker (or by all adblockers).
         *
         * We typically use this syntax when we cannot determine the concrete syntax of the rule,
         * because the syntax is used by more than one adblocker natively.
         *
         * @example
         * - `||example.org^$important` is a common syntax, since it is used by all adblockers natively, and
         * we cannot determine at parsing level whether `important` is a valid option or not, and if it is valid,
         * then which adblocker supports it.
         */
        AdblockSyntax["Common"] = "Common";
        /**
         * Adblock Plus syntax.
         *
         * @example
         * - `example.org#$#abort-on-property-read alert` is an Adblock Plus syntax, since it is not used by any other
         * adblockers directly (probably supported by some on-the-fly conversion, but this is not the native syntax).
         * @see {@link https://adblockplus.org/}
         */
        AdblockSyntax["Abp"] = "AdblockPlus";
        /**
         * uBlock Origin syntax.
         *
         * @example
         * - `example.com##+js(set, atob, noopFunc)` is an uBlock Origin syntax, since it is not used by any other
         * adblockers directly (probably supported by some on-the-fly conversion, but this is not the native syntax).
         * @see {@link https://github.com/gorhill/uBlock}
         */
        AdblockSyntax["Ubo"] = "UblockOrigin";
        /**
         * AdGuard syntax.
         *
         * @example
         * - `example.org#%#//scriptlet("abort-on-property-read", "alert")` is an AdGuard syntax, since it is not used
         * by any other adblockers directly (probably supported by some on-the-fly conversion, but this is not the native
         * syntax).
         * @see {@link https://adguard.com/}
         */
        AdblockSyntax["Adg"] = "AdGuard";
    })(AdblockSyntax || (AdblockSyntax = {}));

    /**
     * @file Constant values used by all parts of the library
     */
    // TODO: remove unused constants
    // General
    /**
     * Empty string.
     */
    const EMPTY = '';
    const SPACE = ' ';
    const TAB = '\t';
    const COLON = ':';
    const COMMA = ',';
    const DOT = '.';
    const SEMICOLON = ';';
    const AMPERSAND = '&';
    const ASTERISK = '*';
    const AT_SIGN = '@';
    const CARET = '^';
    const DOLLAR_SIGN = '$';
    const EQUALS = '=';
    const EXCLAMATION_MARK = '!';
    const HASHMARK = '#';
    const PIPE = '|';
    const PLUS = '+';
    const QUESTION_MARK = '?';
    const SLASH = '/';
    const UNDERSCORE = '_';
    // Escape characters
    const BACKSLASH = '\\';
    const ESCAPE_CHARACTER = BACKSLASH;
    // Newlines
    const CR = '\r';
    const FF = '\f';
    const LF = '\n';
    const CRLF = CR + LF;
    // Quotes
    const BACKTICK_QUOTE = '`';
    const DOUBLE_QUOTE = '"';
    const SINGLE_QUOTE = '\'';
    // Brackets
    const OPEN_PARENTHESIS = '(';
    const CLOSE_PARENTHESIS = ')';
    const OPEN_SQUARE_BRACKET = '[';
    const CLOSE_SQUARE_BRACKET = ']';
    const OPEN_CURLY_BRACKET = '{';
    const CLOSE_CURLY_BRACKET = '}';
    // Letters
    const SMALL_LETTER_A = 'a';
    const SMALL_LETTER_B = 'b';
    const SMALL_LETTER_C = 'c';
    const SMALL_LETTER_D = 'd';
    const SMALL_LETTER_E = 'e';
    const SMALL_LETTER_F = 'f';
    const SMALL_LETTER_G = 'g';
    const SMALL_LETTER_H = 'h';
    const SMALL_LETTER_I = 'i';
    const SMALL_LETTER_J = 'j';
    const SMALL_LETTER_K = 'k';
    const SMALL_LETTER_L = 'l';
    const SMALL_LETTER_M = 'm';
    const SMALL_LETTER_N = 'n';
    const SMALL_LETTER_O = 'o';
    const SMALL_LETTER_P = 'p';
    const SMALL_LETTER_Q = 'q';
    const SMALL_LETTER_R = 'r';
    const SMALL_LETTER_S = 's';
    const SMALL_LETTER_T = 't';
    const SMALL_LETTER_U = 'u';
    const SMALL_LETTER_V = 'v';
    const SMALL_LETTER_W = 'w';
    const SMALL_LETTER_X = 'x';
    const SMALL_LETTER_Y = 'y';
    const SMALL_LETTER_Z = 'z';
    /**
     * Set of all small letters.
     */
    const SMALL_LETTERS = new Set([
        SMALL_LETTER_A,
        SMALL_LETTER_B,
        SMALL_LETTER_C,
        SMALL_LETTER_D,
        SMALL_LETTER_E,
        SMALL_LETTER_F,
        SMALL_LETTER_G,
        SMALL_LETTER_H,
        SMALL_LETTER_I,
        SMALL_LETTER_J,
        SMALL_LETTER_K,
        SMALL_LETTER_L,
        SMALL_LETTER_M,
        SMALL_LETTER_N,
        SMALL_LETTER_O,
        SMALL_LETTER_P,
        SMALL_LETTER_Q,
        SMALL_LETTER_R,
        SMALL_LETTER_S,
        SMALL_LETTER_T,
        SMALL_LETTER_U,
        SMALL_LETTER_V,
        SMALL_LETTER_W,
        SMALL_LETTER_X,
        SMALL_LETTER_Y,
        SMALL_LETTER_Z,
    ]);
    // Capital letters
    const CAPITAL_LETTER_A = 'A';
    const CAPITAL_LETTER_B = 'B';
    const CAPITAL_LETTER_C = 'C';
    const CAPITAL_LETTER_D = 'D';
    const CAPITAL_LETTER_E = 'E';
    const CAPITAL_LETTER_F = 'F';
    const CAPITAL_LETTER_G = 'G';
    const CAPITAL_LETTER_H = 'H';
    const CAPITAL_LETTER_I = 'I';
    const CAPITAL_LETTER_J = 'J';
    const CAPITAL_LETTER_K = 'K';
    const CAPITAL_LETTER_L = 'L';
    const CAPITAL_LETTER_M = 'M';
    const CAPITAL_LETTER_N = 'N';
    const CAPITAL_LETTER_O = 'O';
    const CAPITAL_LETTER_P = 'P';
    const CAPITAL_LETTER_Q = 'Q';
    const CAPITAL_LETTER_R = 'R';
    const CAPITAL_LETTER_S = 'S';
    const CAPITAL_LETTER_T = 'T';
    const CAPITAL_LETTER_U = 'U';
    const CAPITAL_LETTER_V = 'V';
    const CAPITAL_LETTER_W = 'W';
    const CAPITAL_LETTER_X = 'X';
    const CAPITAL_LETTER_Y = 'Y';
    const CAPITAL_LETTER_Z = 'Z';
    /**
     * Set of all capital letters.
     */
    const CAPITAL_LETTERS = new Set([
        CAPITAL_LETTER_A,
        CAPITAL_LETTER_B,
        CAPITAL_LETTER_C,
        CAPITAL_LETTER_D,
        CAPITAL_LETTER_E,
        CAPITAL_LETTER_F,
        CAPITAL_LETTER_G,
        CAPITAL_LETTER_H,
        CAPITAL_LETTER_I,
        CAPITAL_LETTER_J,
        CAPITAL_LETTER_K,
        CAPITAL_LETTER_L,
        CAPITAL_LETTER_M,
        CAPITAL_LETTER_N,
        CAPITAL_LETTER_O,
        CAPITAL_LETTER_P,
        CAPITAL_LETTER_Q,
        CAPITAL_LETTER_R,
        CAPITAL_LETTER_S,
        CAPITAL_LETTER_T,
        CAPITAL_LETTER_U,
        CAPITAL_LETTER_V,
        CAPITAL_LETTER_W,
        CAPITAL_LETTER_X,
        CAPITAL_LETTER_Y,
        CAPITAL_LETTER_Z,
    ]);
    // Numbers as strings
    const NUMBER_0 = '0';
    const NUMBER_1 = '1';
    const NUMBER_2 = '2';
    const NUMBER_3 = '3';
    const NUMBER_4 = '4';
    const NUMBER_5 = '5';
    const NUMBER_6 = '6';
    const NUMBER_7 = '7';
    const NUMBER_8 = '8';
    const NUMBER_9 = '9';
    /**
     * Set of all numbers as strings.
     */
    const NUMBERS = new Set([
        NUMBER_0,
        NUMBER_1,
        NUMBER_2,
        NUMBER_3,
        NUMBER_4,
        NUMBER_5,
        NUMBER_6,
        NUMBER_7,
        NUMBER_8,
        NUMBER_9,
    ]);
    const REGEX_MARKER = '/';
    const ADG_SCRIPTLET_MASK = '//scriptlet';
    const UBO_SCRIPTLET_MASK = '+js';
    const UBO_SCRIPTLET_MASK_LEGACY = 'script:inject';
    const UBO_HTML_MASK = '^';
    // Modifiers are separated by ",". For example: "script,domain=example.com"
    const MODIFIERS_SEPARATOR = ',';
    const MODIFIER_ASSIGN_OPERATOR = '=';
    const NEGATION_MARKER = '~';
    /**
     * The wildcard symbol — `*`.
     */
    const WILDCARD = ASTERISK;
    const CSS_MEDIA_MARKER = '@media';
    const CSS_NOT_PSEUDO = 'not';
    const HINT_MARKER = '!+';
    const HINT_MARKER_LEN = HINT_MARKER.length;
    const NETWORK_RULE_EXCEPTION_MARKER = '@@';
    const NETWORK_RULE_EXCEPTION_MARKER_LEN = NETWORK_RULE_EXCEPTION_MARKER.length;
    const NETWORK_RULE_SEPARATOR = '$';
    const AGLINT_COMMAND_PREFIX = 'aglint';
    const AGLINT_CONFIG_COMMENT_MARKER = '--';
    const PREPROCESSOR_MARKER = '!#';
    const PREPROCESSOR_MARKER_LEN = PREPROCESSOR_MARKER.length;
    const PREPROCESSOR_SEPARATOR = ' ';
    const SAFARI_CB_AFFINITY = 'safari_cb_affinity';
    const IF = 'if';
    const INCLUDE = 'include';
    const NULL = 0;
    const UINT8_MAX = 255;
    const UINT16_MAX = 65535;

    /**
     * @file Utility functions for string manipulation.
     */
    const SINGLE_QUOTE_MARKER = "'";
    const DOUBLE_QUOTE_MARKER = '"';
    class StringUtils {
        /**
         * Finds the first occurrence of a character that:
         * - isn't preceded by an escape character
         *
         * @param pattern - Source pattern
         * @param searchedCharacter - Searched character
         * @param start - Start index
         * @param escapeCharacter - Escape character, \ by default
         * @returns Index or -1 if the character not found
         */
        static findNextUnescapedCharacter(pattern, searchedCharacter, start = 0, escapeCharacter = ESCAPE_CHARACTER) {
            for (let i = start; i < pattern.length; i += 1) {
                // The searched character cannot be preceded by an escape
                if (pattern[i] === searchedCharacter && pattern[i - 1] !== escapeCharacter) {
                    return i;
                }
            }
            return -1;
        }
        /**
         * Finds the first occurrence in backward direction of a character that isn't preceded by an escape character.
         *
         * @param pattern - Source pattern
         * @param searchedCharacter - Searched character
         * @param start - Start index
         * @param escapeCharacter - Escape character, \ by default
         * @returns Index or -1 if the character not found
         */
        static findNextUnescapedCharacterBackwards(pattern, searchedCharacter, start = pattern.length - 1, escapeCharacter = ESCAPE_CHARACTER) {
            for (let i = start; i >= 0; i -= 1) {
                // The searched character cannot be preceded by an escape
                if (pattern[i] === searchedCharacter && pattern[i - 1] !== escapeCharacter) {
                    return i;
                }
            }
            return -1;
        }
        /**
         * Finds the last occurrence of a character that:
         * - isn't preceded by an escape character
         *
         * @param pattern - Source pattern
         * @param searchedCharacter - Searched character
         * @param escapeCharacter - Escape character, \ by default
         * @returns Index or -1 if the character not found
         */
        static findLastUnescapedCharacter(pattern, searchedCharacter, escapeCharacter = ESCAPE_CHARACTER) {
            for (let i = pattern.length - 1; i >= 0; i -= 1) {
                // The searched character cannot be preceded by an escape
                if (pattern[i] === searchedCharacter && pattern[i - 1] !== escapeCharacter) {
                    return i;
                }
            }
            return -1;
        }
        /**
         * Finds the next occurrence of a character that:
         * - isn't preceded by an escape character
         * - isn't followed by the specified character
         *
         * @param pattern - Source pattern
         * @param start - Start index
         * @param searchedCharacter - Searched character
         * @param notFollowedBy - Searched character not followed by this character
         * @param escapeCharacter - Escape character, \ by default
         * @returns Index or -1 if the character not found
         */
        static findNextUnescapedCharacterThatNotFollowedBy(pattern, start, searchedCharacter, notFollowedBy, escapeCharacter = ESCAPE_CHARACTER) {
            for (let i = start; i < pattern.length; i += 1) {
                // The searched character cannot be preceded by an escape
                if (pattern[i] === searchedCharacter
                    && pattern[i + 1] !== notFollowedBy
                    && pattern[i - 1] !== escapeCharacter) {
                    return i;
                }
            }
            return -1;
        }
        /**
         * Finds the last occurrence of a character that:
         * - isn't preceded by an escape character
         * - isn't followed by the specified character
         *
         * @param pattern - Source pattern
         * @param searchedCharacter - Searched character
         * @param notFollowedBy - Searched character not followed by this character
         * @param escapeCharacter - Escape character, \ by default
         * @returns Index or -1 if the character not found
         */
        static findLastUnescapedCharacterThatNotFollowedBy(pattern, searchedCharacter, notFollowedBy, escapeCharacter = ESCAPE_CHARACTER) {
            for (let i = pattern.length - 1; i >= 0; i -= 1) {
                // The searched character cannot be preceded by an escape
                if (pattern[i] === searchedCharacter
                    && pattern[i + 1] !== notFollowedBy
                    && pattern[i - 1] !== escapeCharacter) {
                    return i;
                }
            }
            return -1;
        }
        /**
         * Finds the next occurrence of a character that:
         * - isn't part of any string literal ('literal' or "literal")
         * - isn't part of any RegExp expression (/regexp/)
         *
         * @param pattern - Source pattern
         * @param searchedCharacter - Searched character
         * @param start - Start index
         * @returns Index or -1 if the character not found
         */
        static findUnescapedNonStringNonRegexChar(pattern, searchedCharacter, start = 0) {
            let open = null;
            for (let i = start; i < pattern.length; i += 1) {
                if ((pattern[i] === SINGLE_QUOTE_MARKER
                    || pattern[i] === DOUBLE_QUOTE_MARKER
                    || pattern[i] === REGEX_MARKER)
                    && pattern[i - 1] !== ESCAPE_CHARACTER) {
                    if (open === pattern[i]) {
                        open = null;
                    }
                    else if (open === null) {
                        open = pattern[i];
                    }
                }
                else if (open === null && pattern[i] === searchedCharacter && pattern[i - 1] !== ESCAPE_CHARACTER) {
                    return i;
                }
            }
            return -1;
        }
        /**
         * Finds the next occurrence of a character that:
         * - isn't part of any string literal ('literal' or "literal")
         * - isn't preceded by an escape character
         *
         * @param pattern - Source pattern
         * @param searchedCharacter - Searched character
         * @param start - Start index
         * @param escapeCharacter - Escape character, \ by default
         * @returns Index or -1 if the character not found
         */
        static findNextUnquotedUnescapedCharacter(pattern, searchedCharacter, start = 0, escapeCharacter = ESCAPE_CHARACTER) {
            let openQuote = null;
            for (let i = start; i < pattern.length; i += 1) {
                // Unescaped ' or "
                if ((pattern[i] === SINGLE_QUOTE_MARKER || pattern[i] === DOUBLE_QUOTE_MARKER)
                    && pattern[i - 1] !== escapeCharacter) {
                    if (!openQuote)
                        openQuote = pattern[i];
                    else if (openQuote === pattern[i])
                        openQuote = null;
                }
                else if (pattern[i] === searchedCharacter && pattern[i - 1] !== escapeCharacter) {
                    // Unescaped character
                    if (!openQuote) {
                        return i;
                    }
                }
            }
            return -1;
        }
        /**
         * Finds the next occurrence of a character that:
         * - isn't "bracketed"
         * - isn't preceded by an escape character
         *
         * @param pattern - Source pattern
         * @param searchedCharacter - Searched character
         * @param start - Start index
         * @param escapeCharacter - Escape character, \ by default
         * @param openBracket - Open bracket, ( by default
         * @param closeBracket - Close bracket, ( by default
         * @throws If the opening and closing brackets are the same
         * @returns Index or -1 if the character not found
         */
        static findNextNotBracketedUnescapedCharacter(pattern, searchedCharacter, start = 0, escapeCharacter = ESCAPE_CHARACTER, openBracket = '(', closeBracket = ')') {
            if (openBracket === closeBracket) {
                throw new Error('Open and close bracket cannot be the same');
            }
            let depth = 0;
            for (let i = start; i < pattern.length; i += 1) {
                if (pattern[i] === openBracket) {
                    depth += 1;
                }
                else if (pattern[i] === closeBracket) {
                    depth -= 1;
                }
                else if (depth < 1 && pattern[i] === searchedCharacter && pattern[i - 1] !== escapeCharacter) {
                    return i;
                }
            }
            return -1;
        }
        /**
         * Splits the source pattern along characters that:
         * - isn't part of any string literal ('literal' or "literal")
         * - isn't preceded by an escape character
         *
         * @param pattern - Source pattern
         * @param delimeterCharacter - Delimeter character
         * @returns Splitted string
         */
        static splitStringByUnquotedUnescapedCharacter(pattern, delimeterCharacter) {
            const parts = [];
            let delimeterIndex = -1;
            do {
                const prevDelimeterIndex = delimeterIndex;
                delimeterIndex = StringUtils.findNextUnquotedUnescapedCharacter(pattern, delimeterCharacter, delimeterIndex + 1);
                if (delimeterIndex !== -1) {
                    parts.push(pattern.substring(prevDelimeterIndex + 1, delimeterIndex));
                }
                else {
                    parts.push(pattern.substring(prevDelimeterIndex + 1, pattern.length));
                }
            } while (delimeterIndex !== -1);
            return parts;
        }
        /**
         * Splits the source pattern along characters that:
         * - isn't part of any string literal ('literal' or "literal")
         * - isn't part of any RegExp expression (/regexp/)
         * - isn't preceded by an escape character
         *
         * @param pattern - Source pattern
         * @param delimeterCharacter - Delimeter character
         * @returns Splitted string
         */
        static splitStringByUnescapedNonStringNonRegexChar(pattern, delimeterCharacter) {
            const parts = [];
            let delimeterIndex = -1;
            do {
                const prevDelimeterIndex = delimeterIndex;
                delimeterIndex = StringUtils.findUnescapedNonStringNonRegexChar(pattern, delimeterCharacter, delimeterIndex + 1);
                if (delimeterIndex !== -1) {
                    parts.push(pattern.substring(prevDelimeterIndex + 1, delimeterIndex));
                }
                else {
                    parts.push(pattern.substring(prevDelimeterIndex + 1, pattern.length));
                }
            } while (delimeterIndex !== -1);
            return parts;
        }
        /**
         * Splits the source pattern along characters that:
         * - isn't preceded by an escape character
         *
         * @param pattern - Source pattern
         * @param delimeterCharacter - Delimeter character
         * @returns Splitted string
         */
        static splitStringByUnescapedCharacter(pattern, delimeterCharacter) {
            const parts = [];
            let delimeterIndex = -1;
            do {
                const prevDelimeterIndex = delimeterIndex;
                delimeterIndex = StringUtils.findNextUnescapedCharacter(pattern, delimeterCharacter, delimeterIndex + 1);
                if (delimeterIndex !== -1) {
                    parts.push(pattern.substring(prevDelimeterIndex + 1, delimeterIndex));
                }
                else {
                    parts.push(pattern.substring(prevDelimeterIndex + 1, pattern.length));
                }
            } while (delimeterIndex !== -1);
            return parts;
        }
        /**
         * Determines whether the given character is a space or tab character.
         *
         * @param char - The character to check.
         * @returns true if the given character is a space or tab character, false otherwise.
         */
        static isWhitespace(char) {
            return char === SPACE || char === TAB;
        }
        /**
         * Checks if the given character is a digit.
         *
         * @param char The character to check.
         * @returns `true` if the given character is a digit, `false` otherwise.
         */
        static isDigit(char) {
            return char >= NUMBER_0 && char <= NUMBER_9;
        }
        /**
         * Checks if the given character is a small letter.
         *
         * @param char The character to check.
         * @returns `true` if the given character is a small letter, `false` otherwise.
         */
        static isSmallLetter(char) {
            return char >= SMALL_LETTER_A && char <= SMALL_LETTER_Z;
        }
        /**
         * Checks if the given character is a capital letter.
         *
         * @param char The character to check.
         * @returns `true` if the given character is a capital letter, `false` otherwise.
         */
        static isCapitalLetter(char) {
            return char >= CAPITAL_LETTER_A && char <= CAPITAL_LETTER_Z;
        }
        /**
         * Checks if the given character is a letter (small or capital).
         *
         * @param char The character to check.
         * @returns `true` if the given character is a letter, `false` otherwise.
         */
        static isLetter(char) {
            return StringUtils.isSmallLetter(char) || StringUtils.isCapitalLetter(char);
        }
        /**
         * Checks if the given character is a letter or a digit.
         *
         * @param char Character to check
         * @returns `true` if the given character is a letter or a digit, `false` otherwise.
         */
        static isAlphaNumeric(char) {
            return StringUtils.isLetter(char) || StringUtils.isDigit(char);
        }
        /**
         * Searches for the first non-whitespace character in the source pattern.
         *
         * @param pattern - Source pattern
         * @param start - Start index
         * @returns Index or -1 if the character not found
         */
        static findFirstNonWhitespaceCharacter(pattern, start = 0) {
            for (let i = start; i < pattern.length; i += 1) {
                if (!StringUtils.isWhitespace(pattern[i])) {
                    return i;
                }
            }
            return -1;
        }
        /**
         * Searches for the last non-whitespace character in the source pattern.
         *
         * @param pattern - Source pattern
         * @returns Index or -1 if the character not found
         */
        static findLastNonWhitespaceCharacter(pattern) {
            for (let i = pattern.length - 1; i >= 0; i -= 1) {
                if (!StringUtils.isWhitespace(pattern[i])) {
                    return i;
                }
            }
            return -1;
        }
        /**
         * Finds the next whitespace character in the pattern.
         *
         * @param pattern Pattern to search in
         * @param start Start index
         * @returns Index of the next whitespace character or the length of the pattern if not found
         */
        static findNextWhitespaceCharacter(pattern, start = 0) {
            for (let i = start; i < pattern.length; i += 1) {
                if (StringUtils.isWhitespace(pattern[i])) {
                    return i;
                }
            }
            return pattern.length;
        }
        /**
         * Escapes a specified character in the string.
         *
         * @param pattern - Input string
         * @param character - Character to escape
         * @param escapeCharacter - Escape character (optional)
         * @returns Escaped string
         */
        static escapeCharacter(pattern, character, escapeCharacter = ESCAPE_CHARACTER) {
            let result = EMPTY;
            for (let i = 0; i < pattern.length; i += 1) {
                if (pattern[i] === character && pattern[i - 1] !== escapeCharacter) {
                    result += escapeCharacter;
                }
                result += pattern[i];
            }
            return result;
        }
        /**
         * Searches for the next non-whitespace character in the source pattern.
         *
         * @param pattern Pattern to search
         * @param start Start index
         * @returns Index of the next non-whitespace character or the length of the pattern
         */
        static skipWS(pattern, start = 0) {
            let i = start;
            while (i < pattern.length && StringUtils.isWhitespace(pattern[i])) {
                i += 1;
            }
            return Math.min(i, pattern.length);
        }
        /**
         * Searches for the previous non-whitespace character in the source pattern.
         *
         * @param pattern Pattern to search
         * @param start Start index
         * @returns Index of the previous non-whitespace character or -1
         */
        static skipWSBack(pattern, start = pattern.length - 1) {
            let i = start;
            while (i >= 0 && StringUtils.isWhitespace(pattern[i])) {
                i -= 1;
            }
            return Math.max(i, -1);
        }
        /**
         * Checks if the given character is a new line character.
         *
         * @param char Character to check
         * @returns `true` if the given character is a new line character, `false` otherwise.
         */
        static isEOL(char) {
            return char === CR || char === LF || char === FF;
        }
        /**
         * Splits a string along newline characters.
         *
         * @param input - Input string
         * @returns Splitted string
         */
        static splitStringByNewLines(input) {
            return input.split(/\r?\n/);
        }
        /**
         * Splits a string by new lines and stores the new line type for each line
         *
         * @param input The input string to be split
         * @returns An array of tuples, where each tuple contains a line of the input string and its
         * corresponding new line type ("lf", "crlf", or "cr")
         */
        static splitStringByNewLinesEx(input) {
            // Array to store the tuples of line and new line type
            const result = [];
            let currentLine = EMPTY;
            let newLineType = null;
            // Iterate over each character in the input string
            for (let i = 0; i < input.length; i += 1) {
                const char = input[i];
                if (char === CR) {
                    if (input[i + 1] === LF) {
                        newLineType = 'crlf';
                        i += 1;
                    }
                    else {
                        newLineType = 'cr';
                    }
                    result.push([currentLine, newLineType]);
                    currentLine = EMPTY;
                    newLineType = null;
                }
                else if (char === LF) {
                    newLineType = 'lf';
                    result.push([currentLine, newLineType]);
                    currentLine = EMPTY;
                    newLineType = null;
                }
                else {
                    currentLine += char;
                }
            }
            if (result.length === 0 || currentLine !== EMPTY) {
                result.push([currentLine, newLineType]);
            }
            return result;
        }
        /**
         * Merges an array of tuples (line, newLineType) into a single string
         *
         * @param input The array of tuples to be merged
         * @returns A single string containing the lines and new line characters from the input array
         */
        static mergeStringByNewLines(input) {
            let result = EMPTY;
            // Iterate over each tuple in the input array
            for (let i = 0; i < input.length; i += 1) {
                const [line, newLineType] = input[i];
                // Add the line to the result string
                result += line;
                // Add the appropriate new line character based on the newLineType
                if (newLineType !== null) {
                    if (newLineType === 'crlf') {
                        result += CRLF;
                    }
                    else if (newLineType === 'cr') {
                        result += CR;
                    }
                    else {
                        result += LF;
                    }
                }
            }
            return result;
        }
        /**
         * Helper method to parse a raw string as a number
         *
         * @param raw Raw string to parse
         * @returns Parsed number
         * @throws If the raw string can't be parsed as a number
         */
        static parseNumber(raw) {
            const result = parseInt(raw, 10);
            if (Number.isNaN(result)) {
                throw new Error('Expected a number');
            }
            return result;
        }
        /**
         * Checks if the given value is a string.
         *
         * @param value Value to check
         * @returns `true` if the value is a string, `false` otherwise
         */
        static isString(value) {
            return typeof value === 'string';
        }
        /**
         * Escapes the given characters in the input string.
         *
         * @param input Input string
         * @param characters Characters to escape (by default, no characters are escaped)
         * @returns Escaped string
         */
        static escapeCharacters(input, characters = new Set()) {
            let result = EMPTY;
            for (let i = 0; i < input.length; i += 1) {
                if (characters.has(input[i])) {
                    result += ESCAPE_CHARACTER;
                }
                result += input[i];
            }
            return result;
        }
    }

    /**
     * Possible operators in the logical expression.
     */
    var OperatorValue;
    (function (OperatorValue) {
        OperatorValue["Not"] = "!";
        OperatorValue["And"] = "&&";
        OperatorValue["Or"] = "||";
    })(OperatorValue || (OperatorValue = {}));
    /**
     * Represents the different comment markers that can be used in an adblock rule.
     *
     * @example
     * - If the rule is `! This is just a comment`, then the marker will be `!`.
     * - If the rule is `# This is just a comment`, then the marker will be `#`.
     */
    var CommentMarker;
    (function (CommentMarker) {
        /**
         * Regular comment marker. It is supported by all ad blockers.
         */
        CommentMarker["Regular"] = "!";
        /**
         * Hashmark comment marker. It is supported by uBlock Origin and AdGuard,
         * and also used in hosts files.
         */
        CommentMarker["Hashmark"] = "#";
    })(CommentMarker || (CommentMarker = {}));
    /**
     * Represents the main categories that an adblock rule can belong to.
     * Of course, these include additional subcategories.
     */
    var RuleCategory;
    (function (RuleCategory) {
        /**
         * Empty "rules" that are only containing whitespaces. These rules are handled just for convenience.
         */
        RuleCategory["Empty"] = "Empty";
        /**
         * Syntactically invalid rules (tolerant mode only).
         */
        RuleCategory["Invalid"] = "Invalid";
        /**
         * Comment rules, such as comment rules, metadata rules, preprocessor rules, etc.
         */
        RuleCategory["Comment"] = "Comment";
        /**
         * Cosmetic rules, such as element hiding rules, CSS rules, scriptlet rules, HTML rules, and JS rules.
         */
        RuleCategory["Cosmetic"] = "Cosmetic";
        /**
         * Network rules, such as basic network rules, header remover network rules, redirect network rules,
         * response header filtering rules, etc.
         */
        RuleCategory["Network"] = "Network";
    })(RuleCategory || (RuleCategory = {}));
    /**
     * Represents similar types of modifiers values
     * which may be separated by a comma `,` (only for DomainList) or a pipe `|`.
     */
    var ListNodeType;
    (function (ListNodeType) {
        ListNodeType["Unknown"] = "Unknown";
        ListNodeType["AppList"] = "AppList";
        ListNodeType["DomainList"] = "DomainList";
        ListNodeType["MethodList"] = "MethodList";
        ListNodeType["StealthOptionList"] = "StealthOptionList";
    })(ListNodeType || (ListNodeType = {}));
    /**
     * Represents child items for {@link ListNodeType}.
     */
    var ListItemNodeType;
    (function (ListItemNodeType) {
        ListItemNodeType["Unknown"] = "Unknown";
        ListItemNodeType["App"] = "App";
        ListItemNodeType["Domain"] = "Domain";
        ListItemNodeType["Method"] = "Method";
        ListItemNodeType["StealthOption"] = "StealthOption";
    })(ListItemNodeType || (ListItemNodeType = {}));
    /**
     * Represents possible comment types.
     */
    var CommentRuleType;
    (function (CommentRuleType) {
        CommentRuleType["AgentCommentRule"] = "AgentCommentRule";
        CommentRuleType["CommentRule"] = "CommentRule";
        CommentRuleType["ConfigCommentRule"] = "ConfigCommentRule";
        CommentRuleType["HintCommentRule"] = "HintCommentRule";
        CommentRuleType["MetadataCommentRule"] = "MetadataCommentRule";
        CommentRuleType["PreProcessorCommentRule"] = "PreProcessorCommentRule";
    })(CommentRuleType || (CommentRuleType = {}));
    /**
     * Represents possible cosmetic rule types.
     */
    var CosmeticRuleType;
    (function (CosmeticRuleType) {
        CosmeticRuleType["ElementHidingRule"] = "ElementHidingRule";
        CosmeticRuleType["CssInjectionRule"] = "CssInjectionRule";
        CosmeticRuleType["ScriptletInjectionRule"] = "ScriptletInjectionRule";
        CosmeticRuleType["HtmlFilteringRule"] = "HtmlFilteringRule";
        CosmeticRuleType["JsInjectionRule"] = "JsInjectionRule";
    })(CosmeticRuleType || (CosmeticRuleType = {}));
    /**
     * Represents possible cosmetic rule separators.
     */
    var CosmeticRuleSeparator;
    (function (CosmeticRuleSeparator) {
        /**
         * @see {@link https://help.eyeo.com/adblockplus/how-to-write-filters#elemhide_basic}
         */
        CosmeticRuleSeparator["ElementHiding"] = "##";
        /**
         * @see {@link https://help.eyeo.com/adblockplus/how-to-write-filters#elemhide_basic}
         */
        CosmeticRuleSeparator["ElementHidingException"] = "#@#";
        /**
         * @see {@link https://help.eyeo.com/adblockplus/how-to-write-filters#elemhide_basic}
         */
        CosmeticRuleSeparator["ExtendedElementHiding"] = "#?#";
        /**
         * @see {@link https://help.eyeo.com/adblockplus/how-to-write-filters#elemhide_basic}
         */
        CosmeticRuleSeparator["ExtendedElementHidingException"] = "#@?#";
        /**
         * @see {@link https://help.eyeo.com/adblockplus/how-to-write-filters#elemhide_basic}
         */
        CosmeticRuleSeparator["AbpSnippet"] = "#$#";
        /**
         * @see {@link https://help.eyeo.com/adblockplus/how-to-write-filters#elemhide_basic}
         */
        CosmeticRuleSeparator["AbpSnippetException"] = "#@$#";
        /**
         * @see {@link https://kb.adguard.com/en/general/how-to-create-your-own-ad-filters#cosmetic-css-rules}
         */
        CosmeticRuleSeparator["AdgCssInjection"] = "#$#";
        /**
         * @see {@link https://kb.adguard.com/en/general/how-to-create-your-own-ad-filters#cosmetic-css-rules}
         */
        CosmeticRuleSeparator["AdgCssInjectionException"] = "#@$#";
        /**
         * @see {@link https://kb.adguard.com/en/general/how-to-create-your-own-ad-filters#cosmetic-css-rules}
         */
        CosmeticRuleSeparator["AdgExtendedCssInjection"] = "#$?#";
        /**
         * @see {@link https://kb.adguard.com/en/general/how-to-create-your-own-ad-filters#cosmetic-css-rules}
         */
        CosmeticRuleSeparator["AdgExtendedCssInjectionException"] = "#@$?#";
        /**
         * @see {@link https://kb.adguard.com/en/general/how-to-create-your-own-ad-filters#scriptlets}
         */
        CosmeticRuleSeparator["AdgJsInjection"] = "#%#";
        /**
         * @see {@link https://kb.adguard.com/en/general/how-to-create-your-own-ad-filters#scriptlets}
         */
        CosmeticRuleSeparator["AdgJsInjectionException"] = "#@%#";
        /**
         * @see {@link https://kb.adguard.com/en/general/how-to-create-your-own-ad-filters#html-filtering-rules}
         */
        CosmeticRuleSeparator["AdgHtmlFiltering"] = "$$";
        /**
         * @see {@link https://kb.adguard.com/en/general/how-to-create-your-own-ad-filters#html-filtering-rules}
         */
        CosmeticRuleSeparator["AdgHtmlFilteringException"] = "$@$";
    })(CosmeticRuleSeparator || (CosmeticRuleSeparator = {}));
    /**
     * Type map for binary serialization.
     *
     * @note Values should be fit into 8 bits.
     */
    var BinaryTypeMap;
    (function (BinaryTypeMap) {
        // Basic types
        BinaryTypeMap[BinaryTypeMap["Null"] = 1] = "Null";
        BinaryTypeMap[BinaryTypeMap["Undefined"] = 2] = "Undefined";
        BinaryTypeMap[BinaryTypeMap["Boolean"] = 3] = "Boolean";
        BinaryTypeMap[BinaryTypeMap["Int"] = 4] = "Int";
        BinaryTypeMap[BinaryTypeMap["Float"] = 5] = "Float";
        BinaryTypeMap[BinaryTypeMap["NotANumber"] = 6] = "NotANumber";
        BinaryTypeMap[BinaryTypeMap["String"] = 7] = "String";
        // AGTree nodes
        BinaryTypeMap[BinaryTypeMap["FilterListNode"] = 8] = "FilterListNode";
        BinaryTypeMap[BinaryTypeMap["EmptyRule"] = 9] = "EmptyRule";
        BinaryTypeMap[BinaryTypeMap["InvalidRule"] = 10] = "InvalidRule";
        BinaryTypeMap[BinaryTypeMap["CommentRuleNode"] = 11] = "CommentRuleNode";
        BinaryTypeMap[BinaryTypeMap["AgentNode"] = 12] = "AgentNode";
        BinaryTypeMap[BinaryTypeMap["AgentRuleNode"] = 13] = "AgentRuleNode";
        BinaryTypeMap[BinaryTypeMap["HintNode"] = 14] = "HintNode";
        BinaryTypeMap[BinaryTypeMap["HintRuleNode"] = 15] = "HintRuleNode";
        BinaryTypeMap[BinaryTypeMap["MetadataCommentRuleNode"] = 16] = "MetadataCommentRuleNode";
        BinaryTypeMap[BinaryTypeMap["ConfigCommentRuleNode"] = 17] = "ConfigCommentRuleNode";
        BinaryTypeMap[BinaryTypeMap["PreProcessorCommentRuleNode"] = 18] = "PreProcessorCommentRuleNode";
        BinaryTypeMap[BinaryTypeMap["ConfigNode"] = 19] = "ConfigNode";
        BinaryTypeMap[BinaryTypeMap["NetworkRuleNode"] = 20] = "NetworkRuleNode";
        BinaryTypeMap[BinaryTypeMap["HostRuleNode"] = 21] = "HostRuleNode";
        BinaryTypeMap[BinaryTypeMap["ElementHidingRule"] = 22] = "ElementHidingRule";
        BinaryTypeMap[BinaryTypeMap["CssInjectionRule"] = 23] = "CssInjectionRule";
        BinaryTypeMap[BinaryTypeMap["ScriptletInjectionRule"] = 24] = "ScriptletInjectionRule";
        BinaryTypeMap[BinaryTypeMap["JsInjectionRule"] = 25] = "JsInjectionRule";
        BinaryTypeMap[BinaryTypeMap["HtmlFilteringRule"] = 26] = "HtmlFilteringRule";
        BinaryTypeMap[BinaryTypeMap["ScriptletInjectionRuleBodyNode"] = 27] = "ScriptletInjectionRuleBodyNode";
        BinaryTypeMap[BinaryTypeMap["ElementHidingRuleBody"] = 28] = "ElementHidingRuleBody";
        BinaryTypeMap[BinaryTypeMap["CssInjectionRuleBody"] = 29] = "CssInjectionRuleBody";
        BinaryTypeMap[BinaryTypeMap["HtmlFilteringRuleBody"] = 30] = "HtmlFilteringRuleBody";
        BinaryTypeMap[BinaryTypeMap["JsInjectionRuleBody"] = 31] = "JsInjectionRuleBody";
        BinaryTypeMap[BinaryTypeMap["ValueNode"] = 32] = "ValueNode";
        BinaryTypeMap[BinaryTypeMap["RawNode"] = 33] = "RawNode";
        BinaryTypeMap[BinaryTypeMap["ModifierNode"] = 34] = "ModifierNode";
        BinaryTypeMap[BinaryTypeMap["ModifierListNode"] = 35] = "ModifierListNode";
        BinaryTypeMap[BinaryTypeMap["ParameterListNode"] = 36] = "ParameterListNode";
        BinaryTypeMap[BinaryTypeMap["DomainListNode"] = 37] = "DomainListNode";
        BinaryTypeMap[BinaryTypeMap["DomainNode"] = 38] = "DomainNode";
        BinaryTypeMap[BinaryTypeMap["MethodListNode"] = 39] = "MethodListNode";
        BinaryTypeMap[BinaryTypeMap["MethodNode"] = 40] = "MethodNode";
        BinaryTypeMap[BinaryTypeMap["StealthOptionListNode"] = 41] = "StealthOptionListNode";
        BinaryTypeMap[BinaryTypeMap["StealthOptionNode"] = 42] = "StealthOptionNode";
        BinaryTypeMap[BinaryTypeMap["AppListNode"] = 43] = "AppListNode";
        BinaryTypeMap[BinaryTypeMap["AppNode"] = 44] = "AppNode";
        BinaryTypeMap[BinaryTypeMap["HostnameListNode"] = 45] = "HostnameListNode";
        BinaryTypeMap[BinaryTypeMap["InvalidRuleErrorNode"] = 46] = "InvalidRuleErrorNode";
        BinaryTypeMap[BinaryTypeMap["ExpressionVariableNode"] = 47] = "ExpressionVariableNode";
        BinaryTypeMap[BinaryTypeMap["ExpressionOperatorNode"] = 48] = "ExpressionOperatorNode";
        BinaryTypeMap[BinaryTypeMap["ExpressionParenthesisNode"] = 49] = "ExpressionParenthesisNode";
    })(BinaryTypeMap || (BinaryTypeMap = {}));
    /**
     * Value map for binary serialization. This helps to reduce the size of the serialized data,
     * as it allows us to use a single byte to represent frequently used values.
     *
     * ! IMPORTANT: If you change values here, please update the {@link BINARY_SCHEMA_VERSION}!
     *
     * @note Only 256 values can be represented this way.
     */
    const SYNTAX_SERIALIZATION_MAP = new Map([
        [AdblockSyntax.Common, 0],
        [AdblockSyntax.Abp, 1],
        [AdblockSyntax.Adg, 2],
        [AdblockSyntax.Ubo, 3],
    ]);
    /**
     * Value map for binary deserialization. This helps to reduce the size of the serialized data,
     * as it allows us to use a single byte to represent frequently used values.
     */
    const SYNTAX_DESERIALIZATION_MAP = new Map(Array.from(SYNTAX_SERIALIZATION_MAP, ([key, value]) => [value, key]));
    /**
     * Represents the different types of network rules.
     */
    var NetworkRuleType;
    (function (NetworkRuleType) {
        NetworkRuleType["NetworkRule"] = "NetworkRule";
        NetworkRuleType["HostRule"] = "HostRule";
    })(NetworkRuleType || (NetworkRuleType = {}));

    /**
     * @file Customized syntax error class for Adblock Filter Parser.
     */
    const ERROR_NAME$3 = 'AdblockSyntaxError';
    /**
     * Customized syntax error class for Adblock Filter Parser,
     * which contains the location range of the error.
     */
    class AdblockSyntaxError extends SyntaxError {
        /**
         * Start offset of the error.
         */
        start;
        /**
         * End offset of the error.
         */
        end;
        /**
         * Constructs a new `AdblockSyntaxError` instance.
         *
         * @param message Error message.
         * @param start Start offset of the error.
         * @param end End offset of the error.
         */
        constructor(message, start, end) {
            super(message);
            this.name = ERROR_NAME$3;
            this.start = start;
            this.end = end;
        }
    }

    /**
     * @file Customized error class for not implemented features.
     */
    const ERROR_NAME$2 = 'NotImplementedError';
    const BASE_MESSAGE = 'Not implemented';
    /**
     * Customized error class for not implemented features.
     */
    class NotImplementedError extends Error {
        /**
         * Constructs a new `NotImplementedError` instance.
         *
         * @param message Additional error message (optional)
         */
        constructor(message = undefined) {
            // Prepare the full error message
            const fullMessage = message
                ? `${BASE_MESSAGE}: ${message}`
                : BASE_MESSAGE;
            super(fullMessage);
            this.name = ERROR_NAME$2;
        }
    }

    /* eslint-disable @typescript-eslint/no-unused-vars */
    /**
     * @file Base parser class.
     */
    /**
     * Base class for parsers. Each parser should extend this class.
     */
    class ParserBase {
        /**
         * Parses the input string and returns the AST node.
         *
         * @param input Input string to parse.
         * @param options Parser options, see {@link ParserOptions}.
         * @param baseOffset Base offset. Locations in the AST node will be relative to this offset.
         * @param args Additional, parser-specific arguments, if needed.
         */
        static parse(input, options, baseOffset, ...args) {
            throw new NotImplementedError();
        }
        /**
         * Generates a string from the AST node.
         *
         * @param node AST node to generate a string from.
         */
        static generate(node) {
            throw new NotImplementedError();
        }
        /**
         * Serializes the AST node to a byte buffer.
         *
         * @param node AST node to serialize.
         * @param buffer Output byte buffer to write to.
         * @param args Additional, parser-specific arguments, if needed.
         */
        static serialize(node, buffer, ...args) {
            throw new NotImplementedError();
        }
        /**
         * Deserializes the AST node from a byte buffer.
         *
         * @param buffer Input byte buffer to read from.
         * @param node Destination node to write to.
         * @param args Additional, parser-specific arguments, if needed.
         */
        static deserialize(buffer, node, ...args) {
            throw new NotImplementedError();
        }
    }

    /**
     * @file Common options for all parsers.
     */
    /**
     * Default parser options.
     */
    const defaultParserOptions = Object.freeze({
        tolerant: false,
        isLocIncluded: true,
        parseAbpSpecificRules: true,
        parseUboSpecificRules: true,
        includeRaws: true,
        ignoreComments: false,
        parseHostRules: false,
    });

    /**
     * Checks whether the given value is undefined.
     *
     * @param value Value to check.
     *
     * @returns `true` if the value is 'undefined', `false` otherwise.
     */
    const isUndefined$1 = (value) => {
        return typeof value === 'undefined';
    };
    /**
     * Checks whether the given value is null.
     *
     * @param value Value to check.
     *
     * @returns `true` if the value is 'null', `false` otherwise.
     */
    const isNull$1 = (value) => {
        return value === null;
    };
    /**
     * Checks whether the given value is a string.
     *
     * @param value Value to check.
     * @returns `true` if the value is a string, `false` otherwise.
     */
    const isString = (value) => {
        return typeof value === 'string';
    };

    /* eslint-disable no-param-reassign */
    /**
     * Property map for binary serialization. This helps to reduce the size of the serialized data,
     * as it allows us to use a single byte to represent a property.
     *
     * ! IMPORTANT: If you change values here, please update the {@link BINARY_SCHEMA_VERSION}!
     *
     * @note Only 256 values can be represented this way.
     */
    var ValueNodeSerializationMap;
    (function (ValueNodeSerializationMap) {
        ValueNodeSerializationMap[ValueNodeSerializationMap["Value"] = 1] = "Value";
        ValueNodeSerializationMap[ValueNodeSerializationMap["FrequentValue"] = 2] = "FrequentValue";
        ValueNodeSerializationMap[ValueNodeSerializationMap["Start"] = 3] = "Start";
        ValueNodeSerializationMap[ValueNodeSerializationMap["End"] = 4] = "End";
    })(ValueNodeSerializationMap || (ValueNodeSerializationMap = {}));
    /**
     * Value parser.
     * This parser is very simple, it just exists to provide a consistent interface for parsing and generating values.
     */
    class ValueParser extends ParserBase {
        /**
         * Parses a value.
         *
         * @param raw Raw input to parse.
         * @param options Global parser options.
         * @param baseOffset Starting offset of the input. Node locations are calculated relative to this offset.
         *
         * @returns Value node.
         */
        static parse(raw, options = defaultParserOptions, baseOffset = 0) {
            const result = {
                type: 'Value',
                value: raw,
            };
            if (options.isLocIncluded) {
                result.start = baseOffset;
                result.end = baseOffset + raw.length;
            }
            return result;
        }
        /**
         * Converts a value node to a string.
         *
         * @param node Value node.
         * @returns Raw string.
         */
        static generate(node) {
            return node.value;
        }
        /**
         * Serializes a value node to binary format.
         *
         * @param node Node to serialize.
         * @param buffer ByteBuffer for writing binary data.
         * @param frequentValuesMap Optional map of frequent values.
         * @param toLower Whether to lowercase the value before the frequent value match (defaults to `false`).
         */
        static serialize(node, buffer, frequentValuesMap, toLower = false) {
            buffer.writeUint8(BinaryTypeMap.ValueNode);
            const frequentValue = frequentValuesMap?.get(toLower ? node.value.toLowerCase() : node.value);
            // note: do not use just `if (frequentValue)` because it can be 0
            if (!isUndefined$1(frequentValue)) {
                buffer.writeUint8(ValueNodeSerializationMap.FrequentValue);
                buffer.writeUint8(frequentValue);
            }
            else {
                buffer.writeUint8(ValueNodeSerializationMap.Value);
                buffer.writeString(node.value);
            }
            // note: do not use just `if (node.start)` because it can be 0
            if (!isUndefined$1(node.start)) {
                buffer.writeUint8(ValueNodeSerializationMap.Start);
                buffer.writeUint32(node.start);
            }
            if (!isUndefined$1(node.end)) {
                buffer.writeUint8(ValueNodeSerializationMap.End);
                buffer.writeUint32(node.end);
            }
            buffer.writeUint8(NULL);
        }
        /**
         * Deserializes a value node from binary format.
         *
         * @param buffer ByteBuffer for reading binary data.
         * @param node Destination node.
         * @param frequentValuesMap Optional map of frequent values.
         * @throws If the binary data is malformed.
         */
        static deserialize(buffer, node, frequentValuesMap) {
            buffer.assertUint8(BinaryTypeMap.ValueNode);
            node.type = 'Value';
            let prop = buffer.readUint8();
            while (prop !== NULL) {
                switch (prop) {
                    case ValueNodeSerializationMap.Value:
                        node.value = buffer.readString();
                        break;
                    case ValueNodeSerializationMap.FrequentValue:
                        node.value = frequentValuesMap?.get(buffer.readUint8()) ?? EMPTY;
                        break;
                    case ValueNodeSerializationMap.Start:
                        node.start = buffer.readUint32();
                        break;
                    case ValueNodeSerializationMap.End:
                        node.end = buffer.readUint32();
                        break;
                    default:
                        throw new Error(`Invalid property: ${prop}`);
                }
                prop = buffer.readUint8();
            }
        }
    }

    /* eslint-disable no-param-reassign */
    /**
     * Property map for binary serialization. This helps to reduce the size of the serialized data,
     * as it allows us to use a single byte to represent a property.
     *
     * ! IMPORTANT: If you change values here, please update the {@link BINARY_SCHEMA_VERSION}!
     *
     * @note Only 256 values can be represented this way.
     */
    var AgentNodeSerializationMap;
    (function (AgentNodeSerializationMap) {
        AgentNodeSerializationMap[AgentNodeSerializationMap["Adblock"] = 1] = "Adblock";
        AgentNodeSerializationMap[AgentNodeSerializationMap["Version"] = 2] = "Version";
        AgentNodeSerializationMap[AgentNodeSerializationMap["Start"] = 3] = "Start";
        AgentNodeSerializationMap[AgentNodeSerializationMap["End"] = 4] = "End";
    })(AgentNodeSerializationMap || (AgentNodeSerializationMap = {}));
    /**
     * Possible AdGuard agent markers.
     */
    const ADG_NAME_MARKERS = new Set([
        'adguard',
        'adg',
    ]);
    /**
     * Possible uBlock Origin agent markers.
     */
    const UBO_NAME_MARKERS = new Set([
        'ublock',
        'ublock origin',
        'ubo',
    ]);
    /**
     * Possible Adblock Plus agent markers.
     */
    const ABP_NAME_MARKERS = new Set([
        'adblock',
        'adblock plus',
        'adblockplus',
        'abp',
    ]);
    /**
     * Value map for binary deserialization. This helps to reduce the size of the serialized data,
     * as it allows us to use a single byte to represent frequently used values.
     */
    const FREQUENT_AGENTS_DESERIALIZATION_MAP = new Map([
        // AdGuard
        [0, 'AdGuard'],
        [1, 'ADG'],
        // uBlock Origin
        [2, 'uBlock Origin'],
        [3, 'uBlock'],
        [4, 'uBO'],
        // Adblock Plus
        [5, 'Adblock Plus'],
        [6, 'AdblockPlus'],
        [7, 'ABP'],
        [8, 'AdBlock'],
    ]);
    /**
     * Value map for binary serialization. This helps to reduce the size of the serialized data,
     * as it allows us to use a single byte to represent frequently used values.
     *
     * ! IMPORTANT: If you change values here, please update the {@link BINARY_SCHEMA_VERSION}!
     *
     * @note Only 256 values can be represented this way.
     */
    const FREQUENT_AGENTS_SERIALIZATION_MAP = new Map(Array.from(FREQUENT_AGENTS_DESERIALIZATION_MAP).map(([key, value]) => [value.toLowerCase(), key]));
    /**
     * Returns the adblock syntax based on the adblock name parsed from the agent type comment.
     * Needed for modifiers validation of network rules by AGLint.
     *
     * @param name Adblock name.
     *
     * @returns Adblock syntax.
     */
    const getAdblockSyntax = (name) => {
        let syntax = AdblockSyntax.Common;
        const lowerCaseName = name.toLowerCase();
        if (ADG_NAME_MARKERS.has(lowerCaseName)) {
            syntax = AdblockSyntax.Adg;
        }
        else if (UBO_NAME_MARKERS.has(lowerCaseName)) {
            syntax = AdblockSyntax.Ubo;
        }
        else if (ABP_NAME_MARKERS.has(lowerCaseName)) {
            syntax = AdblockSyntax.Abp;
        }
        return syntax;
    };
    /**
     * `AgentParser` is responsible for parsing single adblock agent elements.
     *
     * @example
     * If the adblock agent rule is
     * ```adblock
     * [Adblock Plus 2.0; AdGuard]
     * ```
     * then the adblock agents are `Adblock Plus 2.0` and `AdGuard`, and this
     * class is responsible for parsing them. The rule itself is parsed by
     * `AgentCommentRuleParser`, which uses this class to parse single agents.
     */
    class AgentParser extends ParserBase {
        /**
         * Checks if the string is a valid version.
         *
         * @param str String to check
         * @returns `true` if the string is a valid version, `false` otherwise
         */
        static isValidVersion(str) {
            return valid$1(coerce$2(str)) !== null;
        }
        /**
         * Parses a raw rule as an adblock agent comment.
         *
         * @param raw Raw input to parse.
         * @param options Global parser options.
         * @param baseOffset Starting offset of the input. Node locations are calculated relative to this offset.
         * @returns Agent rule AST
         * @throws {AdblockSyntaxError} If the raw rule cannot be parsed as an adblock agent
         */
        static parse(raw, options = defaultParserOptions, baseOffset = 0) {
            let offset = 0;
            // Save name start position
            const nameStartIndex = offset;
            let nameEndIndex = offset;
            // Prepare variables for name and version
            let name;
            let version;
            // default value for the syntax
            let syntax = AdblockSyntax.Common;
            // Get agent parts by splitting it by spaces. The last part may be a version.
            // Example: "Adblock Plus 2.0"
            while (offset < raw.length) {
                // Skip whitespace before the part
                offset = StringUtils.skipWS(raw, offset);
                const partEnd = StringUtils.findNextWhitespaceCharacter(raw, offset);
                const part = raw.slice(offset, partEnd);
                if (AgentParser.isValidVersion(part)) {
                    if (!isUndefined$1(version)) {
                        throw new AdblockSyntaxError('Duplicated versions are not allowed', baseOffset + offset, baseOffset + partEnd);
                    }
                    const parsedNamePart = raw.slice(nameStartIndex, nameEndIndex);
                    name = ValueParser.parse(parsedNamePart, options, baseOffset + nameStartIndex);
                    version = ValueParser.parse(part, options, baseOffset + offset);
                    syntax = getAdblockSyntax(parsedNamePart);
                }
                else {
                    nameEndIndex = partEnd;
                }
                // Skip whitespace after the part
                offset = StringUtils.skipWS(raw, partEnd);
            }
            // If we didn't find a version, the whole string is the name
            if (isUndefined$1(name)) {
                const parsedNamePart = raw.slice(nameStartIndex, nameEndIndex);
                name = ValueParser.parse(parsedNamePart, options, baseOffset + nameStartIndex);
                syntax = getAdblockSyntax(parsedNamePart);
            }
            // Agent name cannot be empty
            if (name.value.length === 0) {
                throw new AdblockSyntaxError('Agent name cannot be empty', baseOffset, baseOffset + raw.length);
            }
            const result = {
                type: 'Agent',
                adblock: name,
                syntax,
            };
            // only add version if it's present
            if (version) {
                result.version = version;
            }
            if (options.isLocIncluded) {
                result.start = baseOffset;
                result.end = baseOffset + raw.length;
            }
            return result;
        }
        /**
         * Converts an adblock agent node to a string.
         *
         * @param value Agent node
         * @returns Raw string
         */
        static generate(value) {
            let result = EMPTY;
            // Agent adblock name
            result += value.adblock.value;
            // Agent adblock version (if present)
            if (!isUndefined$1(value.version)) {
                // Add a space between the name and the version
                result += SPACE;
                result += value.version.value;
            }
            return result;
        }
        /**
         * Serializes an agent node to binary format.
         *
         * @param node Node to serialize.
         * @param buffer ByteBuffer for writing binary data.
         */
        static serialize(node, buffer) {
            buffer.writeUint8(BinaryTypeMap.AgentNode);
            buffer.writeUint8(AgentNodeSerializationMap.Adblock);
            ValueParser.serialize(node.adblock, buffer, FREQUENT_AGENTS_SERIALIZATION_MAP, true);
            if (!isUndefined$1(node.version)) {
                buffer.writeUint8(AgentNodeSerializationMap.Version);
                ValueParser.serialize(node.version, buffer);
            }
            if (!isUndefined$1(node.start)) {
                buffer.writeUint8(AgentNodeSerializationMap.Start);
                buffer.writeUint32(node.start);
            }
            if (!isUndefined$1(node.end)) {
                buffer.writeUint8(AgentNodeSerializationMap.End);
                buffer.writeUint32(node.end);
            }
            buffer.writeUint8(NULL);
        }
        /**
         * Deserializes an agent node from binary format.
         *
         * @param buffer ByteBuffer for reading binary data.
         * @param node Destination node.
         * @throws If the binary data is malformed.
         */
        static deserialize(buffer, node) {
            buffer.assertUint8(BinaryTypeMap.AgentNode);
            node.type = 'Agent';
            let prop = buffer.readUint8();
            while (prop !== NULL) {
                switch (prop) {
                    case AgentNodeSerializationMap.Adblock:
                        ValueParser.deserialize(buffer, node.adblock = {}, FREQUENT_AGENTS_DESERIALIZATION_MAP);
                        if (node.adblock) {
                            node.syntax = getAdblockSyntax(node.adblock.value);
                        }
                        break;
                    case AgentNodeSerializationMap.Version:
                        ValueParser.deserialize(buffer, node.version = {});
                        break;
                    case AgentNodeSerializationMap.Start:
                        node.start = buffer.readUint32();
                        break;
                    case AgentNodeSerializationMap.End:
                        node.end = buffer.readUint32();
                        break;
                    default:
                        throw new Error(`Invalid property: ${prop}`);
                }
                prop = buffer.readUint8();
            }
        }
    }

    /**
     * @file Cosmetic rule separator finder and categorizer
     */
    /**
     * Utility class for cosmetic rule separators.
     */
    class CosmeticRuleSeparatorUtils {
        /**
         * Checks whether the specified separator is an exception.
         *
         * @param separator Separator to check
         * @returns `true` if the separator is an exception, `false` otherwise
         */
        static isException(separator) {
            // Simply check the second character
            return separator[1] === AT_SIGN;
        }
        /**
         * Checks whether the specified separator is marks an Extended CSS cosmetic rule.
         *
         * @param separator Separator to check
         * @returns `true` if the separator is marks an Extended CSS cosmetic rule, `false` otherwise
         */
        static isExtendedCssMarker(separator) {
            return (separator === CosmeticRuleSeparator.ExtendedElementHiding
                || separator === CosmeticRuleSeparator.ExtendedElementHidingException
                || separator === CosmeticRuleSeparator.AdgExtendedCssInjection
                || separator === CosmeticRuleSeparator.AdgExtendedCssInjectionException);
        }
        /**
         * Looks for the cosmetic rule separator in the rule. This is a simplified version that
         * masks the recursive function.
         *
         * @param rule Raw rule
         * @returns Separator result or null if no separator was found
         */
        static find(rule) {
            /**
             * Helper function to create results of the `find` method.
             *
             * @param start Start position
             * @param separator Separator type
             * @returns Cosmetic rule separator node
             */
            // eslint-disable-next-line max-len
            function createResult(start, separator) {
                return {
                    separator,
                    start,
                    end: start + separator.length,
                };
            }
            for (let i = 0; i < rule.length; i += 1) {
                if (rule[i] === '#') {
                    if (rule[i + 1] === '#' && rule[i - 1] !== SPACE) {
                        // ##
                        return createResult(i, CosmeticRuleSeparator.ElementHiding);
                    }
                    if (rule[i + 1] === '?' && rule[i + 2] === '#') {
                        // #?#
                        return createResult(i, CosmeticRuleSeparator.ExtendedElementHiding);
                    }
                    if (rule[i + 1] === '%' && rule[i + 2] === '#') {
                        // #%#
                        return createResult(i, CosmeticRuleSeparator.AdgJsInjection);
                    }
                    if (rule[i + 1] === '$') {
                        if (rule[i + 2] === '#') {
                            // #$#
                            return createResult(i, CosmeticRuleSeparator.AdgCssInjection);
                        }
                        if (rule[i + 2] === '?' && rule[i + 3] === '#') {
                            // #$?#
                            return createResult(i, CosmeticRuleSeparator.AdgExtendedCssInjection);
                        }
                    }
                    // Exceptions
                    if (rule[i + 1] === '@') {
                        if (rule[i + 2] === '#' && rule[i - 1] !== SPACE) {
                            // #@#
                            return createResult(i, CosmeticRuleSeparator.ElementHidingException);
                        }
                        if (rule[i + 2] === '?' && rule[i + 3] === '#') {
                            // #@?#
                            return createResult(i, CosmeticRuleSeparator.ExtendedElementHidingException);
                        }
                        if (rule[i + 2] === '%' && rule[i + 3] === '#') {
                            // #@%#
                            return createResult(i, CosmeticRuleSeparator.AdgJsInjectionException);
                        }
                        if (rule[i + 2] === '$') {
                            if (rule[i + 3] === '#') {
                                // #@$#
                                return createResult(i, CosmeticRuleSeparator.AdgCssInjectionException);
                            }
                            if (rule[i + 3] === '?' && rule[i + 4] === '#') {
                                // #@$?#
                                return createResult(i, CosmeticRuleSeparator.AdgExtendedCssInjectionException);
                            }
                        }
                    }
                }
                if (rule[i] === '$') {
                    if (rule[i + 1] === '$') {
                        // $$
                        return createResult(i, CosmeticRuleSeparator.AdgHtmlFiltering);
                    }
                    if (rule[i + 1] === '@' && rule[i + 2] === '$') {
                        // $@$
                        return createResult(i, CosmeticRuleSeparator.AdgHtmlFilteringException);
                    }
                }
            }
            return null;
        }
    }

    /* eslint-disable no-param-reassign */
    /**
     * Property map for binary serialization. This helps to reduce the size of the serialized data,
     * as it allows us to use a single byte to represent a property.
     *
     * ! IMPORTANT: If you change values here, please update the {@link BINARY_SCHEMA_VERSION}!
     *
     * @note Only 256 values can be represented this way.
     */
    var AgentRuleSerializationMap;
    (function (AgentRuleSerializationMap) {
        AgentRuleSerializationMap[AgentRuleSerializationMap["Children"] = 1] = "Children";
        AgentRuleSerializationMap[AgentRuleSerializationMap["Start"] = 2] = "Start";
        AgentRuleSerializationMap[AgentRuleSerializationMap["End"] = 3] = "End";
    })(AgentRuleSerializationMap || (AgentRuleSerializationMap = {}));
    /**
     * `AgentParser` is responsible for parsing an Adblock agent rules.
     * Adblock agent comment marks that the filter list is supposed to
     * be used by the specified ad blockers.
     *
     * @example
     *  - ```adblock
     *    [AdGuard]
     *    ```
     *  - ```adblock
     *    [Adblock Plus 2.0]
     *    ```
     *  - ```adblock
     *    [uBlock Origin]
     *    ```
     *  - ```adblock
     *    [uBlock Origin 1.45.3]
     *    ```
     *  - ```adblock
     *    [Adblock Plus 2.0; AdGuard]
     *    ```
     */
    class AgentCommentRuleParser extends ParserBase {
        /**
         * Checks if the raw rule is an adblock agent comment.
         *
         * @param raw Raw rule
         * @returns `true` if the rule is an adblock agent, `false` otherwise
         */
        static isAgentRule(raw) {
            const rawTrimmed = raw.trim();
            if (rawTrimmed.startsWith(OPEN_SQUARE_BRACKET) && rawTrimmed.endsWith(CLOSE_SQUARE_BRACKET)) {
                // Avoid this case: [$adg-modifier]##[class^="adg-"]
                return isNull$1(CosmeticRuleSeparatorUtils.find(rawTrimmed));
            }
            return false;
        }
        /**
         * Parses a raw rule as an adblock agent comment.
         *
         * @param raw Raw input to parse.
         * @param options Global parser options.
         * @param baseOffset Starting offset of the input. Node locations are calculated relative to this offset.
         * @returns Agent rule AST or null (if the raw rule cannot be parsed as an adblock agent comment)
         */
        static parse(raw, options = defaultParserOptions, baseOffset = 0) {
            // Ignore non-agent rules
            if (!AgentCommentRuleParser.isAgentRule(raw)) {
                return null;
            }
            let offset = 0;
            // Skip whitespace characters before the rule
            offset = StringUtils.skipWS(raw, offset);
            // Skip opening bracket
            offset += 1;
            // last character should be a closing bracket
            const closingBracketIndex = StringUtils.skipWSBack(raw, raw.length - 1);
            if (closingBracketIndex === -1 || raw[closingBracketIndex] !== CLOSE_SQUARE_BRACKET) {
                throw new AdblockSyntaxError('Missing closing bracket', offset, offset + raw.length);
            }
            // Initialize the agent list
            const result = {
                type: CommentRuleType.AgentCommentRule,
                syntax: AdblockSyntax.Common,
                category: RuleCategory.Comment,
                children: [],
            };
            if (options.includeRaws) {
                result.raws = {
                    text: raw,
                };
            }
            if (options.isLocIncluded) {
                result.start = baseOffset;
                result.end = baseOffset + raw.length;
            }
            while (offset < closingBracketIndex) {
                // Skip whitespace characters before the agent
                offset = StringUtils.skipWS(raw, offset);
                // Find the separator or the closing bracket
                let separatorIndex = raw.indexOf(SEMICOLON, offset);
                if (separatorIndex === -1) {
                    separatorIndex = closingBracketIndex;
                }
                // Find the last non-whitespace character of the agent
                // [AdGuard  ; Adblock Plus 2.0]
                //        ^
                // (if we have spaces between the agent name and the separator)
                const agentEndIndex = StringUtils.findLastNonWhitespaceCharacter(raw.slice(offset, separatorIndex)) + offset + 1;
                // Collect the agent
                result.children.push(AgentParser.parse(raw.slice(offset, agentEndIndex), options, baseOffset + offset));
                // Set the offset to the next agent or the end of the rule
                offset = separatorIndex + 1;
            }
            if (result.children.length === 0) {
                throw new AdblockSyntaxError('Empty agent list', baseOffset, baseOffset + raw.length);
            }
            return result;
        }
        /**
         * Converts an adblock agent AST to a string.
         *
         * @param ast Agent rule AST
         * @returns Raw string
         */
        static generate(ast) {
            let result = OPEN_SQUARE_BRACKET;
            result += ast.children
                .map(AgentParser.generate)
                .join(SEMICOLON + SPACE);
            result += CLOSE_SQUARE_BRACKET;
            return result;
        }
        /**
         * Serializes an adblock agent list node to binary format.
         *
         * @param node Node to serialize.
         * @param buffer ByteBuffer for writing binary data.
         */
        // TODO: add support for raws, if ever needed
        static serialize(node, buffer) {
            buffer.writeUint8(BinaryTypeMap.AgentRuleNode);
            const count = node.children.length;
            if (count) {
                buffer.writeUint8(AgentRuleSerializationMap.Children);
                // note: we store the count, because re-construction of the array is faster if we know the length
                // 8 bits is more than enough here
                if (count > UINT8_MAX) {
                    throw new Error(`Too many children: ${count}, the limit is ${UINT8_MAX}`);
                }
                buffer.writeUint8(count);
                for (let i = 0; i < count; i += 1) {
                    AgentParser.serialize(node.children[i], buffer);
                }
            }
            if (!isUndefined$1(node.start)) {
                buffer.writeUint8(AgentRuleSerializationMap.Start);
                buffer.writeUint32(node.start);
            }
            if (!isUndefined$1(node.end)) {
                buffer.writeUint8(AgentRuleSerializationMap.End);
                buffer.writeUint32(node.end);
            }
            buffer.writeUint8(NULL);
        }
        /**
         * Deserializes an agent list node from binary format.
         *
         * @param buffer ByteBuffer for reading binary data.
         * @param node Destination node.
         */
        static deserialize(buffer, node) {
            buffer.assertUint8(BinaryTypeMap.AgentRuleNode);
            node.type = CommentRuleType.AgentCommentRule;
            node.syntax = AdblockSyntax.Common;
            node.category = RuleCategory.Comment;
            let prop = buffer.readUint8();
            while (prop !== NULL) {
                switch (prop) {
                    case AgentRuleSerializationMap.Children:
                        node.children = new Array(buffer.readUint8());
                        // read children
                        for (let i = 0; i < node.children.length; i += 1) {
                            AgentParser.deserialize(buffer, node.children[i] = {});
                        }
                        break;
                    case AgentRuleSerializationMap.Start:
                        node.start = buffer.readUint32();
                        break;
                    case AgentRuleSerializationMap.End:
                        node.end = buffer.readUint32();
                        break;
                    default:
                        throw new Error(`Invalid property: ${prop}`);
                }
                prop = buffer.readUint8();
            }
        }
    }

    /* eslint-disable no-param-reassign */
    /**
     * Property map for binary serialization. This helps to reduce the size of the serialized data,
     * as it allows us to use a single byte to represent a property.
     *
     * ! IMPORTANT: If you change values here, please update the {@link BINARY_SCHEMA_VERSION}!
     *
     * @note Only 256 values can be represented this way.
     */
    var ParameterListNodeSerializationMap;
    (function (ParameterListNodeSerializationMap) {
        ParameterListNodeSerializationMap[ParameterListNodeSerializationMap["Children"] = 1] = "Children";
        ParameterListNodeSerializationMap[ParameterListNodeSerializationMap["Start"] = 2] = "Start";
        ParameterListNodeSerializationMap[ParameterListNodeSerializationMap["End"] = 3] = "End";
    })(ParameterListNodeSerializationMap || (ParameterListNodeSerializationMap = {}));
    class ParameterListParser extends ParserBase {
        /**
         * Parses a raw parameter list.
         *
         * @param raw Raw input to parse.
         * @param options Global parser options.
         * @param baseOffset Starting offset of the input. Node locations are calculated relative to this offset.
         * @param separator Separator character (default: comma)
         * @returns Parameter list AST
         */
        static parse(raw, options = defaultParserOptions, baseOffset = 0, separator = COMMA) {
            // Prepare the parameter list node
            const params = {
                type: 'ParameterList',
                children: [],
            };
            const { length } = raw;
            if (options.isLocIncluded) {
                params.start = baseOffset;
                params.end = baseOffset + length;
            }
            let offset = 0;
            // Parse parameters: skip whitespace before and after each parameter, and
            // split parameters by the separator character.
            while (offset < length) {
                // Skip whitespace before parameter
                offset = StringUtils.skipWS(raw, offset);
                // Parameter may only contain whitespace
                // In this case, we reached the end of the parameter list
                if (raw[offset] === separator || offset === length) {
                    // Add a null for empty parameter
                    params.children.push(null);
                    // Skip separator
                    offset += 1;
                }
                else {
                    // Get parameter start position
                    const paramStart = offset;
                    // Get next unescaped separator position
                    const nextSeparator = StringUtils.findUnescapedNonStringNonRegexChar(raw, separator, offset);
                    // Get parameter end position
                    const paramEnd = nextSeparator !== -1
                        ? StringUtils.skipWSBack(raw, nextSeparator - 1)
                        : StringUtils.skipWSBack(raw);
                    // Add parameter to the list
                    const param = ValueParser.parse(raw.slice(paramStart, paramEnd + 1), options, baseOffset + paramStart);
                    params.children.push(param);
                    // Set offset to the next separator position + 1
                    offset = nextSeparator !== -1 ? nextSeparator + 1 : length;
                }
            }
            // If the last character was a separator, add an additional null parameter
            if (raw[length - 1] === separator) {
                params.children.push(null);
            }
            return params;
        }
        /**
         * Converts a parameter list AST to a string.
         *
         * @param params Parameter list AST
         * @param separator Separator character (default: comma)
         * @returns String representation of the parameter list
         */
        static generate(params, separator = COMMA) {
            const collection = [];
            // add parameters
            let i = 0;
            for (; i < params.children.length; i += 1) {
                const param = params.children[i];
                if (param === null) {
                    collection.push(EMPTY);
                }
                else {
                    collection.push(ValueParser.generate(param));
                }
            }
            // join parameters with separator
            // if the separator is a space, join with a single space
            const result = collection.join(separator === SPACE ? separator : `${separator}${SPACE}`);
            return result;
        }
        /**
         * Serializes a parameter list node to binary format.
         *
         * @param node Node to serialize.
         * @param buffer ByteBuffer for writing binary data.
         * @param frequentValuesMap Optional map of frequent values.
         * @param toLower Whether to lowercase the value before the frequent value match (defaults to `false`).
         */
        static serialize(node, buffer, frequentValuesMap, toLower = false) {
            buffer.writeUint8(BinaryTypeMap.ParameterListNode);
            const count = node.children.length;
            buffer.writeUint8(ParameterListNodeSerializationMap.Children);
            // note: we store the count, because re-construction of the array is faster if we know the length
            buffer.writeUint32(count);
            for (let i = 0; i < count; i += 1) {
                const child = node.children[i];
                if (isNull$1(child)) {
                    buffer.writeUint8(BinaryTypeMap.Null);
                    continue;
                }
                ValueParser.serialize(child, buffer, frequentValuesMap, toLower);
            }
            if (!isUndefined$1(node.start)) {
                buffer.writeUint8(ParameterListNodeSerializationMap.Start);
                buffer.writeUint32(node.start);
            }
            if (!isUndefined$1(node.end)) {
                buffer.writeUint8(ParameterListNodeSerializationMap.End);
                buffer.writeUint32(node.end);
            }
            buffer.writeUint8(NULL);
        }
        /**
         * Deserializes a parameter list node from binary format.
         *
         * @param buffer ByteBuffer for reading binary data.
         * @param node Destination node.
         * @param frequentValuesMap Optional map of frequent values.
         * @throws If the binary data is malformed.
         */
        static deserialize(buffer, node, frequentValuesMap) {
            buffer.assertUint8(BinaryTypeMap.ParameterListNode);
            node.type = 'ParameterList';
            let prop = buffer.readUint8();
            while (prop !== NULL) {
                switch (prop) {
                    case ParameterListNodeSerializationMap.Children:
                        node.children = new Array(buffer.readUint32());
                        // read children
                        for (let i = 0; i < node.children.length; i += 1) {
                            switch (buffer.peekUint8()) {
                                case BinaryTypeMap.Null:
                                    buffer.readUint8();
                                    node.children[i] = null;
                                    break;
                                case BinaryTypeMap.ValueNode:
                                    ValueParser.deserialize(buffer, node.children[i] = {}, frequentValuesMap);
                                    break;
                                default:
                                    throw new Error(`Invalid child type: ${buffer.peekUint8()}`);
                            }
                        }
                        break;
                    case ParameterListNodeSerializationMap.Start:
                        node.start = buffer.readUint32();
                        break;
                    case ParameterListNodeSerializationMap.End:
                        node.end = buffer.readUint32();
                        break;
                    default:
                        throw new Error(`Invalid property: ${prop}`);
                }
                prop = buffer.readUint8();
            }
        }
    }

    /* eslint-disable no-param-reassign */
    /**
     * @file AGLint configuration comments. Inspired by ESLint inline configuration comments.
     * @see {@link https://eslint.org/docs/latest/user-guide/configuring/rules#using-configuration-comments}
     */
    /**
     * Property map for binary serialization. This helps to reduce the size of the serialized data,
     * as it allows us to use a single byte to represent a property.
     *
     * ! IMPORTANT: If you change values here, please update the {@link BINARY_SCHEMA_VERSION}!
     *
     * @note Only 256 values can be represented this way.
     */
    var ConfigCommentRuleSerializationMap;
    (function (ConfigCommentRuleSerializationMap) {
        ConfigCommentRuleSerializationMap[ConfigCommentRuleSerializationMap["Marker"] = 1] = "Marker";
        ConfigCommentRuleSerializationMap[ConfigCommentRuleSerializationMap["Command"] = 2] = "Command";
        ConfigCommentRuleSerializationMap[ConfigCommentRuleSerializationMap["Params"] = 3] = "Params";
        ConfigCommentRuleSerializationMap[ConfigCommentRuleSerializationMap["Comment"] = 4] = "Comment";
        ConfigCommentRuleSerializationMap[ConfigCommentRuleSerializationMap["Start"] = 5] = "Start";
        ConfigCommentRuleSerializationMap[ConfigCommentRuleSerializationMap["End"] = 6] = "End";
    })(ConfigCommentRuleSerializationMap || (ConfigCommentRuleSerializationMap = {}));
    /**
     * Property map for binary serialization. This helps to reduce the size of the serialized data,
     * as it allows us to use a single byte to represent a property.
     *
     * ! IMPORTANT: If you change values here, please update the {@link BINARY_SCHEMA_VERSION}!
     *
     * @note Only 256 values can be represented this way.
     */
    var ConfigNodeSerializationMap;
    (function (ConfigNodeSerializationMap) {
        ConfigNodeSerializationMap[ConfigNodeSerializationMap["Value"] = 1] = "Value";
        ConfigNodeSerializationMap[ConfigNodeSerializationMap["Start"] = 2] = "Start";
        ConfigNodeSerializationMap[ConfigNodeSerializationMap["End"] = 3] = "End";
    })(ConfigNodeSerializationMap || (ConfigNodeSerializationMap = {}));
    /**
     * Value map for binary serialization. This helps to reduce the size of the serialized data,
     * as it allows us to use a single byte to represent frequently used values.
     *
     * ! IMPORTANT: If you change values here, please update the {@link BINARY_SCHEMA_VERSION}!
     *
     * @note Only 256 values can be represented this way.
     *
     * @see {@link https://github.com/AdguardTeam/AGLint/blob/master/src/linter/inline-config.ts}
     */
    const FREQUENT_COMMANDS_SERIALIZATION_MAP = new Map([
        ['aglint', 0],
        ['aglint-disable', 1],
        ['aglint-enable', 2],
        ['aglint-disable-next-line', 3],
        ['aglint-enable-next-line', 4],
    ]);
    /**
     * Value map for binary deserialization. This helps to reduce the size of the serialized data,
     * as it allows us to use a single byte to represent frequently used values.
     */
    const FREQUENT_COMMANDS_DESERIALIZATION_MAP = new Map(Array.from(FREQUENT_COMMANDS_SERIALIZATION_MAP).map(([key, value]) => [value, key]));
    /**
     * `ConfigCommentParser` is responsible for parsing inline AGLint configuration rules.
     * Generally, the idea is inspired by ESLint inline configuration comments.
     *
     * @see {@link https://eslint.org/docs/latest/user-guide/configuring/rules#using-configuration-comments}
     */
    class ConfigCommentRuleParser extends ParserBase {
        /**
         * Checks if the raw rule is an inline configuration comment rule.
         *
         * @param raw Raw rule
         * @returns `true` if the rule is an inline configuration comment rule, otherwise `false`.
         */
        static isConfigComment(raw) {
            const trimmed = raw.trim();
            if (trimmed[0] === CommentMarker.Regular || trimmed[0] === CommentMarker.Hashmark) {
                // Skip comment marker and trim comment text (it is necessary because of "!     something")
                const text = raw.slice(1).trim();
                // The code below is "not pretty", but it runs fast, which is necessary, since it will run on EVERY comment
                // The essence of the indicator is that the control comment always starts with the "aglint" prefix
                return ((text[0] === 'a' || text[0] === 'A')
                    && (text[1] === 'g' || text[1] === 'G')
                    && (text[2] === 'l' || text[2] === 'L')
                    && (text[3] === 'i' || text[3] === 'I')
                    && (text[4] === 'n' || text[4] === 'N')
                    && (text[5] === 't' || text[5] === 'T'));
            }
            return false;
        }
        /**
         * Parses a raw rule as an inline configuration comment.
         *
         * @param raw Raw input to parse.
         * @param options Global parser options.
         * @param baseOffset Starting offset of the input. Node locations are calculated relative to this offset.
         * @returns
         * Inline configuration comment AST or null (if the raw rule cannot be parsed as configuration comment)
         */
        static parse(raw, options = defaultParserOptions, baseOffset = 0) {
            if (!ConfigCommentRuleParser.isConfigComment(raw)) {
                return null;
            }
            let offset = 0;
            // Skip leading whitespace (if any)
            offset = StringUtils.skipWS(raw, offset);
            // Get comment marker
            const marker = ValueParser.parse(raw[offset], options, baseOffset + offset);
            // Skip marker
            offset += 1;
            // Skip whitespace (if any)
            offset = StringUtils.skipWS(raw, offset);
            // Save the command start position
            const commandStart = offset;
            // Get comment text, for example: "aglint-disable-next-line"
            offset = StringUtils.findNextWhitespaceCharacter(raw, offset);
            const command = ValueParser.parse(raw.slice(commandStart, offset), options, baseOffset + commandStart);
            // Skip whitespace after command
            offset = StringUtils.skipWS(raw, offset);
            // Get comment (if any)
            const commentStart = raw.indexOf(AGLINT_CONFIG_COMMENT_MARKER, offset);
            const commentEnd = commentStart !== -1 ? StringUtils.skipWSBack(raw) + 1 : -1;
            let comment;
            // Check if there is a comment
            if (commentStart !== -1) {
                comment = ValueParser.parse(raw.slice(commentStart, commentEnd), options, baseOffset + commentStart);
            }
            // Get parameter
            const paramsStart = offset;
            const paramsEnd = commentStart !== -1
                ? StringUtils.skipWSBack(raw, commentStart - 1) + 1
                : StringUtils.skipWSBack(raw) + 1;
            let params;
            // `! aglint ...` config comment
            if (command.value === AGLINT_COMMAND_PREFIX) {
                params = {
                    type: 'ConfigNode',
                    // It is necessary to use JSON5.parse instead of JSON.parse because JSON5 allows unquoted keys.
                    // But don't forget to add { } to the beginning and end of the string,
                    // otherwise JSON5 will not be able to parse it.
                    // TODO: Better solution? ESLint uses "levn" package for parsing these comments.
                    value: lib.parse(`{${raw.slice(paramsStart, paramsEnd)}}`),
                };
                if (options.isLocIncluded) {
                    params.start = paramsStart;
                    params.end = paramsEnd;
                }
                // Throw error for empty config
                if (Object.keys(params.value).length === 0) {
                    throw new Error('Empty AGLint config');
                }
            }
            else if (paramsStart < paramsEnd) {
                params = ParameterListParser.parse(raw.slice(paramsStart, paramsEnd), options, baseOffset + paramsStart, COMMA);
            }
            const result = {
                type: CommentRuleType.ConfigCommentRule,
                category: RuleCategory.Comment,
                syntax: AdblockSyntax.Common,
                marker,
                command,
                params,
                comment,
            };
            if (options.includeRaws) {
                result.raws = {
                    text: raw,
                };
            }
            if (options.isLocIncluded) {
                result.start = baseOffset;
                result.end = baseOffset + raw.length;
            }
            return result;
        }
        /**
         * Converts an inline configuration comment node to a string.
         *
         * @param node Inline configuration comment node
         * @returns Raw string
         */
        static generate(node) {
            let result = EMPTY;
            result += node.marker.value;
            result += SPACE;
            result += node.command.value;
            if (node.params) {
                result += SPACE;
                if (node.params.type === 'ParameterList') {
                    result += ParameterListParser.generate(node.params, COMMA);
                }
                else {
                    // Trim JSON boundaries
                    result += JSON.stringify(node.params.value).slice(1, -1).trim();
                }
            }
            // Add comment within the config comment
            if (node.comment) {
                result += SPACE;
                result += node.comment.value;
            }
            return result;
        }
        /**
         * Serializes a config node to binary format.
         *
         * @param node Node to serialize.
         * @param buffer ByteBuffer for writing binary data.
         */
        static serializeConfigNode(node, buffer) {
            buffer.writeUint8(BinaryTypeMap.ConfigNode);
            buffer.writeUint8(ConfigNodeSerializationMap.Value);
            // note: we don't support serializing generic objects, only AGTree nodes
            // this is a very special case, so we just stringify the configuration object
            buffer.writeString(JSON.stringify(node.value));
            if (!isUndefined$1(node.start)) {
                buffer.writeUint8(ConfigNodeSerializationMap.Start);
                buffer.writeUint32(node.start);
            }
            if (!isUndefined$1(node.end)) {
                buffer.writeUint8(ConfigNodeSerializationMap.End);
                buffer.writeUint32(node.end);
            }
            buffer.writeUint8(NULL);
        }
        /**
         * Deserializes a metadata comment node from binary format.
         *
         * @param buffer ByteBuffer for reading binary data.
         * @param node Destination node.
         * @throws If the binary data is malformed.
         */
        static deserializeConfigNode(buffer, node) {
            buffer.assertUint8(BinaryTypeMap.ConfigNode);
            node.type = 'ConfigNode';
            let prop = buffer.readUint8();
            while (prop !== NULL) {
                switch (prop) {
                    case ConfigNodeSerializationMap.Value:
                        // note: it is safe to use JSON.parse here, because we serialized it with JSON.stringify
                        node.value = JSON.parse(buffer.readString());
                        break;
                    case ConfigNodeSerializationMap.Start:
                        node.start = buffer.readUint32();
                        break;
                    case ConfigNodeSerializationMap.End:
                        node.end = buffer.readUint32();
                        break;
                    default:
                        throw new Error(`Invalid property: ${prop}.`);
                }
                prop = buffer.readUint8();
            }
        }
        /**
         * Serializes a metadata comment node to binary format.
         *
         * @param node Node to serialize.
         * @param buffer ByteBuffer for writing binary data.
         */
        // TODO: add support for raws, if ever needed
        static serialize(node, buffer) {
            buffer.writeUint8(BinaryTypeMap.ConfigCommentRuleNode);
            buffer.writeUint8(ConfigCommentRuleSerializationMap.Marker);
            ValueParser.serialize(node.marker, buffer);
            buffer.writeUint8(ConfigCommentRuleSerializationMap.Command);
            ValueParser.serialize(node.command, buffer, FREQUENT_COMMANDS_SERIALIZATION_MAP, true);
            if (!isUndefined$1(node.params)) {
                buffer.writeUint8(ConfigCommentRuleSerializationMap.Params);
                if (node.params.type === 'ParameterList') {
                    ParameterListParser.serialize(node.params, buffer);
                }
                else {
                    ConfigCommentRuleParser.serializeConfigNode(node.params, buffer);
                }
            }
            if (!isUndefined$1(node.comment)) {
                buffer.writeUint8(ConfigCommentRuleSerializationMap.Comment);
                ValueParser.serialize(node.comment, buffer);
            }
            if (!isUndefined$1(node.start)) {
                buffer.writeUint8(ConfigCommentRuleSerializationMap.Start);
                buffer.writeUint32(node.start);
            }
            if (!isUndefined$1(node.end)) {
                buffer.writeUint8(ConfigCommentRuleSerializationMap.End);
                buffer.writeUint32(node.end);
            }
            buffer.writeUint8(NULL);
        }
        /**
         * Deserializes a metadata comment node from binary format.
         *
         * @param buffer ByteBuffer for reading binary data.
         * @param node Destination node.
         * @throws If the binary data is malformed.
         */
        static deserialize(buffer, node) {
            buffer.assertUint8(BinaryTypeMap.ConfigCommentRuleNode);
            node.type = CommentRuleType.ConfigCommentRule;
            node.category = RuleCategory.Comment;
            node.syntax = AdblockSyntax.Common;
            let prop = buffer.readUint8();
            while (prop !== NULL) {
                switch (prop) {
                    case ConfigCommentRuleSerializationMap.Marker:
                        ValueParser.deserialize(buffer, node.marker = {});
                        break;
                    case ConfigCommentRuleSerializationMap.Command:
                        ValueParser.deserialize(buffer, node.command = {}, FREQUENT_COMMANDS_DESERIALIZATION_MAP);
                        break;
                    case ConfigCommentRuleSerializationMap.Params:
                        if (buffer.peekUint8() === BinaryTypeMap.ConfigNode) {
                            ConfigCommentRuleParser.deserializeConfigNode(buffer, node.params = {});
                        }
                        else {
                            ParameterListParser.deserialize(buffer, node.params = {});
                        }
                        break;
                    case ConfigCommentRuleSerializationMap.Comment:
                        ValueParser.deserialize(buffer, node.comment = {});
                        break;
                    case ConfigCommentRuleSerializationMap.Start:
                        node.start = buffer.readUint32();
                        break;
                    case ConfigCommentRuleSerializationMap.End:
                        node.end = buffer.readUint32();
                        break;
                    default:
                        throw new Error(`Invalid property: ${prop}`);
                }
                prop = buffer.readUint8();
            }
        }
    }

    /* eslint-disable no-param-reassign */
    /**
     * @file AdGuard Hints
     * @see {@link https://kb.adguard.com/en/general/how-to-create-your-own-ad-filters#hints}
     */
    /**
     * Property map for binary serialization. This helps to reduce the size of the serialized data,
     * as it allows us to use a single byte to represent a property.
     *
     * ! IMPORTANT: If you change values here, please update the {@link BINARY_SCHEMA_VERSION}!
     *
     * @note Only 256 values can be represented this way.
     */
    var HintNodeSerializationMap;
    (function (HintNodeSerializationMap) {
        HintNodeSerializationMap[HintNodeSerializationMap["Name"] = 1] = "Name";
        HintNodeSerializationMap[HintNodeSerializationMap["Params"] = 2] = "Params";
        HintNodeSerializationMap[HintNodeSerializationMap["Start"] = 3] = "Start";
        HintNodeSerializationMap[HintNodeSerializationMap["End"] = 4] = "End";
    })(HintNodeSerializationMap || (HintNodeSerializationMap = {}));
    /**
     * Value map for binary serialization. This helps to reduce the size of the serialized data,
     * as it allows us to use a single byte to represent frequently used values.
     *
     * ! IMPORTANT: If you change values here, please update the {@link BINARY_SCHEMA_VERSION}!
     *
     * @note Only 256 values can be represented this way.
     */
    const FREQUENT_HINTS_SERIALIZATION_MAP = new Map([
        ['NOT_OPTIMIZED', 0],
        ['PLATFORM', 1],
        ['NOT_PLATFORM', 2],
    ]);
    /**
     * Value map for binary deserialization. This helps to reduce the size of the serialized data,
     * as it allows us to use a single byte to represent frequently used values.
     */
    const FREQUENT_HINTS_DESERIALIZATION_MAP = new Map(Array.from(FREQUENT_HINTS_SERIALIZATION_MAP).map(([key, value]) => [value, key]));
    /**
     * Value map for binary serialization. This helps to reduce the size of the serialized data,
     * as it allows us to use a single byte to represent frequently used values.
     *
     * ! IMPORTANT: If you change values here, please update the {@link BINARY_SCHEMA_VERSION}!
     *
     * @note Only 256 values can be represented this way.
     */
    const FREQUENT_PLATFORMS_SERIALIZATION_MAP = new Map([
        ['windows', 0],
        ['mac', 1],
        ['android', 2],
        ['ios', 3],
        ['ext_chromium', 4],
        ['ext_ff', 5],
        ['ext_edge', 6],
        ['ext_opera', 7],
        ['ext_safari', 8],
        ['ext_android_cb', 9],
        ['ext_ublock', 10],
    ]);
    /**
     * Value map for binary deserialization. This helps to reduce the size of the serialized data,
     * as it allows us to use a single byte to represent frequently used values.
     */
    const FREQUENT_PLATFORMS_DESERIALIZATION_MAP = new Map(Array.from(FREQUENT_PLATFORMS_SERIALIZATION_MAP).map(([key, value]) => [value, key]));
    /**
     * `HintParser` is responsible for parsing AdGuard hints.
     *
     * @example
     * If the hint rule is
     * ```adblock
     * !+ NOT_OPTIMIZED PLATFORM(windows)
     * ```
     * then the hints are `NOT_OPTIMIZED` and `PLATFORM(windows)`, and this
     * class is responsible for parsing them. The rule itself is parsed by
     * the `HintRuleParser`, which uses this class to parse single hints.
     */
    class HintParser extends ParserBase {
        /**
         * Parses a raw rule as a hint.
         *
         * @param raw Raw input to parse.
         * @param options Global parser options.
         * @param baseOffset Starting offset of the input. Node locations are calculated relative to this offset.
         * @returns Hint rule AST or null
         * @throws If the syntax is invalid
         */
        static parse(raw, options = defaultParserOptions, baseOffset = 0) {
            let offset = 0;
            // Skip whitespace characters before the hint
            offset = StringUtils.skipWS(raw);
            // Hint should start with the hint name in every case
            // Save the start offset of the hint name
            const nameStartIndex = offset;
            // Parse the hint name
            for (; offset < raw.length; offset += 1) {
                const char = raw[offset];
                // Abort consuming the hint name if we encounter a whitespace character
                // or an opening parenthesis, which means 'HIT_NAME(' case
                if (char === OPEN_PARENTHESIS || char === SPACE) {
                    break;
                }
                // Hint name should only contain letters, digits, and underscores
                if (!StringUtils.isAlphaNumeric(char) && char !== UNDERSCORE) {
                    throw new AdblockSyntaxError(`Invalid character "${char}" in hint name: "${char}"`, baseOffset + nameStartIndex, baseOffset + offset);
                }
            }
            // Save the end offset of the hint name
            const nameEndIndex = offset;
            // Save the hint name token
            const name = raw.slice(nameStartIndex, nameEndIndex);
            // Hint name cannot be empty
            if (name === EMPTY) {
                throw new AdblockSyntaxError('Empty hint name', baseOffset, baseOffset + nameEndIndex);
            }
            // Now we have two case:
            //  1. We have HINT_NAME and should return it
            //  2. We have HINT_NAME(PARAMS) and should continue parsing
            // Skip whitespace characters after the hint name
            offset = StringUtils.skipWS(raw, offset);
            // Throw error for 'HINT_NAME (' case
            if (offset > nameEndIndex && raw[offset] === OPEN_PARENTHESIS) {
                throw new AdblockSyntaxError('Unexpected whitespace(s) between hint name and opening parenthesis', baseOffset + nameEndIndex, baseOffset + offset);
            }
            // Create the hint name node (we can reuse it in the 'HINT_NAME' case, if needed)
            const nameNode = ValueParser.parse(name, options, baseOffset + nameStartIndex);
            // Just return the hint name if we have 'HINT_NAME' case (no params)
            if (raw[offset] !== OPEN_PARENTHESIS) {
                const result = {
                    type: 'Hint',
                    name: nameNode,
                };
                if (options.isLocIncluded) {
                    result.start = baseOffset;
                    result.end = baseOffset + offset;
                }
                return result;
            }
            // Skip the opening parenthesis
            offset += 1;
            // Find closing parenthesis
            const closeParenthesisIndex = raw.lastIndexOf(CLOSE_PARENTHESIS);
            // Throw error if we don't have closing parenthesis
            if (closeParenthesisIndex === -1) {
                throw new AdblockSyntaxError(`Missing closing parenthesis for hint "${name}"`, baseOffset + nameStartIndex, baseOffset + raw.length);
            }
            // Save the start and end index of the params
            const paramsStartIndex = offset;
            const paramsEndIndex = closeParenthesisIndex;
            // Parse the params
            const params = ParameterListParser.parse(raw.slice(paramsStartIndex, paramsEndIndex), options, baseOffset + paramsStartIndex, COMMA);
            offset = closeParenthesisIndex + 1;
            // Skip whitespace characters after the closing parenthesis
            offset = StringUtils.skipWS(raw, offset);
            // Throw error if we don't reach the end of the input
            if (offset !== raw.length) {
                throw new AdblockSyntaxError(
                // eslint-disable-next-line max-len
                `Unexpected input after closing parenthesis for hint "${name}": "${raw.slice(closeParenthesisIndex + 1, offset + 1)}"`, baseOffset + closeParenthesisIndex + 1, baseOffset + offset + 1);
            }
            // Return the HINT_NAME(PARAMS) case AST
            const result = {
                type: 'Hint',
                name: nameNode,
                params,
            };
            if (options.isLocIncluded) {
                result.start = baseOffset;
                result.end = baseOffset + offset;
            }
            return result;
        }
        /**
         * Converts a single hint AST to a string.
         *
         * @param hint Hint AST
         * @returns Hint string
         */
        static generate(hint) {
            let result = EMPTY;
            result += hint.name.value;
            if (hint.params && hint.params.children.length > 0) {
                result += OPEN_PARENTHESIS;
                result += ParameterListParser.generate(hint.params, COMMA);
                result += CLOSE_PARENTHESIS;
            }
            return result;
        }
        /**
         * Serializes a hint node to binary format.
         *
         * @param node Node to serialize.
         * @param buffer ByteBuffer for writing binary data.
         */
        static serialize(node, buffer) {
            buffer.writeUint8(BinaryTypeMap.HintNode);
            buffer.writeUint8(HintNodeSerializationMap.Name);
            ValueParser.serialize(node.name, buffer, FREQUENT_HINTS_SERIALIZATION_MAP);
            if (!isUndefined$1(node.params)) {
                buffer.writeUint8(HintNodeSerializationMap.Params);
                ParameterListParser.serialize(node.params, buffer, FREQUENT_PLATFORMS_SERIALIZATION_MAP);
            }
            if (!isUndefined$1(node.start)) {
                buffer.writeUint8(HintNodeSerializationMap.Start);
                buffer.writeUint32(node.start);
            }
            if (!isUndefined$1(node.end)) {
                buffer.writeUint8(HintNodeSerializationMap.End);
                buffer.writeUint32(node.end);
            }
            buffer.writeUint8(NULL);
        }
        /**
         * Deserializes a hint node from binary format.
         *
         * @param buffer ByteBuffer for reading binary data.
         * @param node Destination node.
         * @throws If the binary data is malformed.
         */
        static deserialize(buffer, node) {
            buffer.assertUint8(BinaryTypeMap.HintNode);
            node.type = 'Hint';
            let prop = buffer.readUint8();
            while (prop !== NULL) {
                switch (prop) {
                    case HintNodeSerializationMap.Name:
                        ValueParser.deserialize(buffer, node.name = {}, FREQUENT_HINTS_DESERIALIZATION_MAP);
                        break;
                    case HintNodeSerializationMap.Params:
                        // eslint-disable-next-line max-len
                        ParameterListParser.deserialize(buffer, node.params = {}, FREQUENT_PLATFORMS_DESERIALIZATION_MAP);
                        break;
                    case HintNodeSerializationMap.Start:
                        node.start = buffer.readUint32();
                        break;
                    case HintNodeSerializationMap.End:
                        node.end = buffer.readUint32();
                        break;
                    default:
                        throw new Error(`Invalid property: ${prop}`);
                }
                prop = buffer.readUint8();
            }
        }
    }

    /* eslint-disable no-param-reassign */
    /**
     * Property map for binary serialization. This helps to reduce the size of the serialized data,
     * as it allows us to use a single byte to represent a property.
     *
     * ! IMPORTANT: If you change values here, please update the {@link BINARY_SCHEMA_VERSION}!
     *
     * @note Only 256 values can be represented this way.
     */
    var HintRuleSerializationMap;
    (function (HintRuleSerializationMap) {
        HintRuleSerializationMap[HintRuleSerializationMap["Syntax"] = 1] = "Syntax";
        HintRuleSerializationMap[HintRuleSerializationMap["Children"] = 2] = "Children";
        HintRuleSerializationMap[HintRuleSerializationMap["Start"] = 3] = "Start";
        HintRuleSerializationMap[HintRuleSerializationMap["End"] = 4] = "End";
    })(HintRuleSerializationMap || (HintRuleSerializationMap = {}));
    /**
     * `HintRuleParser` is responsible for parsing AdGuard hint rules.
     *
     * @example
     * The following hint rule
     * ```adblock
     * !+ NOT_OPTIMIZED PLATFORM(windows)
     * ```
     * contains two hints: `NOT_OPTIMIZED` and `PLATFORM`.
     * @see {@link https://kb.adguard.com/en/general/how-to-create-your-own-ad-filters#hints}
     */
    class HintCommentRuleParser extends ParserBase {
        /**
         * Checks if the raw rule is a hint rule.
         *
         * @param raw Raw rule
         * @returns `true` if the rule is a hint rule, `false` otherwise
         */
        static isHintRule(raw) {
            return raw.trim().startsWith(HINT_MARKER);
        }
        /**
         * Parses a raw rule as a hint comment.
         *
         * @param raw Raw input to parse.
         * @param options Global parser options.
         * @param baseOffset Starting offset of the input. Node locations are calculated relative to this offset.
         * @returns Hint AST or null (if the raw rule cannot be parsed as a hint comment)
         * @throws If the input matches the HINT pattern but syntactically invalid
         * @see {@link https://kb.adguard.com/en/general/how-to-create-your-own-ad-filters#hints-1}
         */
        static parse(raw, options = defaultParserOptions, baseOffset = 0) {
            // Ignore non-hint rules
            if (!HintCommentRuleParser.isHintRule(raw)) {
                return null;
            }
            let offset = 0;
            // Skip whitespace characters before the rule
            offset = StringUtils.skipWS(raw);
            // Skip hint marker
            offset += HINT_MARKER_LEN;
            const hints = [];
            // Collect hints. Each hint is a string, optionally followed by a parameter list,
            // enclosed in parentheses. One rule can contain multiple hints.
            while (offset < raw.length) {
                // Split rule into raw hints (e.g. 'HINT_NAME' or 'HINT_NAME(PARAMS)')
                // Hints are separated by whitespace characters, but we should ignore
                // whitespace characters inside the parameter list
                // Ignore whitespace characters before the hint
                offset = StringUtils.skipWS(raw, offset);
                // Save the start index of the hint
                const hintStartIndex = offset;
                // Find the end of the hint
                let hintEndIndex = offset;
                let balance = 0;
                while (hintEndIndex < raw.length) {
                    if (raw[hintEndIndex] === OPEN_PARENTHESIS && raw[hintEndIndex - 1] !== BACKSLASH) {
                        balance += 1;
                        // Throw error for nesting
                        if (balance > 1) {
                            throw new AdblockSyntaxError('Invalid hint: nested parentheses are not allowed', baseOffset + hintStartIndex, baseOffset + hintEndIndex);
                        }
                    }
                    else if (raw[hintEndIndex] === CLOSE_PARENTHESIS && raw[hintEndIndex - 1] !== BACKSLASH) {
                        balance -= 1;
                    }
                    else if (StringUtils.isWhitespace(raw[hintEndIndex]) && balance === 0) {
                        break;
                    }
                    hintEndIndex += 1;
                }
                offset = hintEndIndex;
                // Skip whitespace characters after the hint
                offset = StringUtils.skipWS(raw, offset);
                // Parse the hint
                const hint = HintParser.parse(raw.slice(hintStartIndex, hintEndIndex), options, baseOffset + hintStartIndex);
                hints.push(hint);
            }
            // Throw error if no hints were found
            if (hints.length === 0) {
                throw new AdblockSyntaxError('Empty hint rule', baseOffset, baseOffset + offset);
            }
            const result = {
                type: CommentRuleType.HintCommentRule,
                category: RuleCategory.Comment,
                syntax: AdblockSyntax.Adg,
                children: hints,
            };
            if (options.includeRaws) {
                result.raws = {
                    text: raw,
                };
            }
            if (options.isLocIncluded) {
                result.start = baseOffset;
                result.end = baseOffset + offset;
            }
            return result;
        }
        /**
         * Converts a hint rule node to a raw string.
         *
         * @param node Hint rule node
         * @returns Raw string
         */
        static generate(node) {
            let result = HINT_MARKER + SPACE;
            result += node.children.map(HintParser.generate).join(SPACE);
            return result;
        }
        /**
         * Serializes a hint rule node to binary format.
         *
         * @param node Node to serialize.
         * @param buffer ByteBuffer for writing binary data.
         */
        // TODO: add support for raws, if ever needed
        static serialize(node, buffer) {
            buffer.writeUint8(BinaryTypeMap.HintRuleNode);
            if (node.syntax === AdblockSyntax.Adg) {
                buffer.writeUint8(HintRuleSerializationMap.Syntax);
                buffer.writeUint8(SYNTAX_SERIALIZATION_MAP.get(AdblockSyntax.Adg) ?? 0);
            }
            const count = node.children.length;
            if (count) {
                buffer.writeUint8(HintRuleSerializationMap.Children);
                // note: we store the count, because re-construction of the array is faster if we know the length
                buffer.writeUint8(count);
                for (let i = 0; i < count; i += 1) {
                    HintParser.serialize(node.children[i], buffer);
                }
            }
            if (!isUndefined$1(node.start)) {
                buffer.writeUint8(HintRuleSerializationMap.Start);
                buffer.writeUint32(node.start);
            }
            if (!isUndefined$1(node.end)) {
                buffer.writeUint8(HintRuleSerializationMap.End);
                buffer.writeUint32(node.end);
            }
            buffer.writeUint8(NULL);
        }
        /**
         * Deserializes a hint rule node from binary format.
         *
         * @param buffer ByteBuffer for reading binary data.
         * @param node Destination node.
         * @throws If the binary data is malformed.
         */
        static deserialize(buffer, node) {
            buffer.assertUint8(BinaryTypeMap.HintRuleNode);
            node.category = RuleCategory.Comment;
            node.type = CommentRuleType.HintCommentRule;
            let prop = buffer.readUint8();
            while (prop !== NULL) {
                switch (prop) {
                    case HintRuleSerializationMap.Syntax:
                        node.syntax = SYNTAX_DESERIALIZATION_MAP.get(buffer.readUint8()) ?? AdblockSyntax.Common;
                        break;
                    case HintRuleSerializationMap.Children:
                        node.children = new Array(buffer.readUint8());
                        // read children
                        for (let i = 0; i < node.children.length; i += 1) {
                            HintParser.deserialize(buffer, node.children[i] = {});
                        }
                        break;
                    case HintRuleSerializationMap.Start:
                        node.start = buffer.readUint32();
                        break;
                    case HintRuleSerializationMap.End:
                        node.end = buffer.readUint32();
                        break;
                    default:
                        throw new Error(`Invalid property: ${prop}`);
                }
                prop = buffer.readUint8();
            }
        }
    }

    /* eslint-disable no-param-reassign */
    /**
     * @file Metadata comments
     */
    /**
     * Property map for binary serialization. This helps to reduce the size of the serialized data,
     * as it allows us to use a single byte to represent a property.
     *
     * ! IMPORTANT: If you change values here, please update the {@link BINARY_SCHEMA_VERSION}!
     *
     * @note Only 256 values can be represented this way.
     */
    var MetadataCommentRuleSerializationMap;
    (function (MetadataCommentRuleSerializationMap) {
        MetadataCommentRuleSerializationMap[MetadataCommentRuleSerializationMap["Marker"] = 1] = "Marker";
        MetadataCommentRuleSerializationMap[MetadataCommentRuleSerializationMap["Header"] = 2] = "Header";
        MetadataCommentRuleSerializationMap[MetadataCommentRuleSerializationMap["Value"] = 3] = "Value";
        MetadataCommentRuleSerializationMap[MetadataCommentRuleSerializationMap["Start"] = 4] = "Start";
        MetadataCommentRuleSerializationMap[MetadataCommentRuleSerializationMap["End"] = 5] = "End";
    })(MetadataCommentRuleSerializationMap || (MetadataCommentRuleSerializationMap = {}));
    /**
     * Value map for binary deserialization. This helps to reduce the size of the serialized data,
     * as it allows us to use a single byte to represent frequently used values.
     */
    const FREQUENT_HEADERS_DESERIALIZATION_MAP = new Map([
        [1, 'Checksum'],
        [2, 'Description'],
        [3, 'Expires'],
        [4, 'Homepage'],
        [5, 'Last Modified'],
        [6, 'LastModified'],
        [7, 'Licence'],
        [8, 'License'],
        [9, 'Time Updated'],
        [10, 'TimeUpdated'],
        [11, 'Version'],
        [12, 'Title'],
    ]);
    /**
     * Value map for binary serialization. This helps to reduce the size of the serialized data,
     * as it allows us to use a single byte to represent frequently used values.
     *
     * ! IMPORTANT: If you change values here, please update the {@link BINARY_SCHEMA_VERSION}!
     *
     * @note Only 256 values can be represented this way.
     * @note This map is generated from `FREQUENT_HEADERS_DESERIALIZATION_MAP` to keep uppercase characters
     * while deserializing.
     */
    const FREQUENT_HEADERS_SERIALIZATION_MAP = new Map(Array.from(FREQUENT_HEADERS_DESERIALIZATION_MAP.entries()).map(([key, value]) => [value.toLowerCase(), key]));
    /**
     * Known metadata headers.
     */
    const KNOWN_METADATA_HEADERS = Array.from(FREQUENT_HEADERS_SERIALIZATION_MAP.keys());
    /**
     * `MetadataParser` is responsible for parsing metadata comments.
     * Metadata comments are special comments that specify some properties of the list.
     *
     * @example
     * For example, in the case of
     * ```adblock
     * ! Title: My List
     * ```
     * the name of the header is `Title`, and the value is `My List`, which means that
     * the list title is `My List`, and it can be used in the adblocker UI.
     * @see {@link https://help.eyeo.com/adblockplus/how-to-write-filters#special-comments}
     */
    class MetadataCommentRuleParser extends ParserBase {
        /**
         * Parses a raw rule as a metadata comment.
         *
         * @param raw Raw input to parse.
         * @param options Global parser options.
         * @param baseOffset Starting offset of the input. Node locations are calculated relative to this offset.
         * @returns Metadata comment AST or null (if the raw rule cannot be parsed as a metadata comment)
         */
        static parse(raw, options = defaultParserOptions, baseOffset = 0) {
            // Fast check to avoid unnecessary work
            if (raw.indexOf(COLON) === -1) {
                return null;
            }
            let offset = 0;
            // Skip leading spaces before the comment marker
            offset = StringUtils.skipWS(raw, offset);
            // Check if the rule starts with a comment marker (first non-space sequence)
            if (raw[offset] !== CommentMarker.Regular && raw[offset] !== CommentMarker.Hashmark) {
                return null;
            }
            // Consume the comment marker
            const marker = ValueParser.parse(raw[offset], options, baseOffset + offset);
            offset += 1;
            // Skip spaces
            offset = StringUtils.skipWS(raw, offset);
            // Save header start position
            const headerStart = offset;
            // Check if the comment text starts with a known header
            const text = raw.slice(offset);
            for (let i = 0; i < KNOWN_METADATA_HEADERS.length; i += 1) {
                // Check if the comment text starts with the header (case-insensitive)
                if (text.toLocaleLowerCase().startsWith(KNOWN_METADATA_HEADERS[i].toLocaleLowerCase())) {
                    // Skip the header
                    offset += KNOWN_METADATA_HEADERS[i].length;
                    // Save header
                    const header = ValueParser.parse(raw.slice(headerStart, offset), options, baseOffset + headerStart);
                    // Skip spaces after the header
                    offset = StringUtils.skipWS(raw, offset);
                    // Check if the rule contains a separator after the header
                    if (raw[offset] !== COLON) {
                        return null;
                    }
                    // Skip the separator
                    offset += 1;
                    // Skip spaces after the separator
                    offset = StringUtils.skipWS(raw, offset);
                    // Save the value start position
                    const valueStart = offset;
                    // Check if the rule contains a value
                    if (offset >= raw.length) {
                        return null;
                    }
                    const valueEnd = StringUtils.skipWSBack(raw, raw.length - 1) + 1;
                    // Save the value
                    const value = ValueParser.parse(raw.slice(valueStart, valueEnd), options, baseOffset + valueStart);
                    const result = {
                        type: CommentRuleType.MetadataCommentRule,
                        category: RuleCategory.Comment,
                        syntax: AdblockSyntax.Common,
                        marker,
                        header,
                        value,
                    };
                    if (options.includeRaws) {
                        result.raws = {
                            text: raw,
                        };
                    }
                    if (options.isLocIncluded) {
                        result.start = baseOffset;
                        result.end = baseOffset + raw.length;
                    }
                    return result;
                }
            }
            return null;
        }
        /**
         * Converts a metadata comment rule node to a string.
         *
         * @param node Metadata comment rule node.
         * @returns Raw string.
         */
        static generate(node) {
            let result = EMPTY;
            result += ValueParser.generate(node.marker);
            result += SPACE;
            result += ValueParser.generate(node.header);
            result += COLON;
            result += SPACE;
            result += ValueParser.generate(node.value);
            return result;
        }
        /**
         * Serializes a metadata comment node to binary format.
         *
         * @param node Node to serialize.
         * @param buffer ByteBuffer for writing binary data.
         */
        // TODO: add support for raws, if ever needed
        static serialize(node, buffer) {
            buffer.writeUint8(BinaryTypeMap.MetadataCommentRuleNode);
            buffer.writeUint8(MetadataCommentRuleSerializationMap.Marker);
            ValueParser.serialize(node.marker, buffer);
            buffer.writeUint8(MetadataCommentRuleSerializationMap.Header);
            ValueParser.serialize(node.header, buffer, FREQUENT_HEADERS_SERIALIZATION_MAP, true);
            buffer.writeUint8(MetadataCommentRuleSerializationMap.Value);
            ValueParser.serialize(node.value, buffer);
            if (!isUndefined$1(node.start)) {
                buffer.writeUint8(MetadataCommentRuleSerializationMap.Start);
                buffer.writeUint32(node.start);
            }
            if (!isUndefined$1(node.end)) {
                buffer.writeUint8(MetadataCommentRuleSerializationMap.End);
                buffer.writeUint32(node.end);
            }
            buffer.writeUint8(NULL);
        }
        /**
         * Deserializes a metadata comment node from binary format.
         *
         * @param buffer ByteBuffer for reading binary data.
         * @param node Destination node.
         * @throws If the binary data is malformed.
         */
        static deserialize(buffer, node) {
            buffer.assertUint8(BinaryTypeMap.MetadataCommentRuleNode);
            node.type = CommentRuleType.MetadataCommentRule;
            node.category = RuleCategory.Comment;
            node.syntax = AdblockSyntax.Common;
            let prop = buffer.readUint8();
            while (prop !== NULL) {
                switch (prop) {
                    case MetadataCommentRuleSerializationMap.Marker:
                        ValueParser.deserialize(buffer, node.marker = {});
                        break;
                    case MetadataCommentRuleSerializationMap.Header:
                        ValueParser.deserialize(buffer, node.header = {}, FREQUENT_HEADERS_DESERIALIZATION_MAP);
                        break;
                    case MetadataCommentRuleSerializationMap.Value:
                        ValueParser.deserialize(buffer, node.value = {});
                        break;
                    case MetadataCommentRuleSerializationMap.Start:
                        node.start = buffer.readUint32();
                        break;
                    case MetadataCommentRuleSerializationMap.End:
                        node.end = buffer.readUint32();
                        break;
                    default:
                        throw new Error(`Invalid property: ${prop}`);
                }
                prop = buffer.readUint8();
            }
        }
    }

    /* eslint-disable no-param-reassign */
    /* eslint-disable max-classes-per-file */
    /**
     * Property map for binary serialization.
     */
    var VariableNodeBinaryPropMap;
    (function (VariableNodeBinaryPropMap) {
        VariableNodeBinaryPropMap[VariableNodeBinaryPropMap["Name"] = 1] = "Name";
        VariableNodeBinaryPropMap[VariableNodeBinaryPropMap["FrequentName"] = 2] = "FrequentName";
        VariableNodeBinaryPropMap[VariableNodeBinaryPropMap["Start"] = 3] = "Start";
        VariableNodeBinaryPropMap[VariableNodeBinaryPropMap["End"] = 4] = "End";
    })(VariableNodeBinaryPropMap || (VariableNodeBinaryPropMap = {}));
    /**
     * Property map for binary serialization.
     */
    var OperatorNodeBinaryPropMap;
    (function (OperatorNodeBinaryPropMap) {
        OperatorNodeBinaryPropMap[OperatorNodeBinaryPropMap["Operator"] = 1] = "Operator";
        OperatorNodeBinaryPropMap[OperatorNodeBinaryPropMap["Left"] = 2] = "Left";
        OperatorNodeBinaryPropMap[OperatorNodeBinaryPropMap["Right"] = 3] = "Right";
        OperatorNodeBinaryPropMap[OperatorNodeBinaryPropMap["Start"] = 4] = "Start";
        OperatorNodeBinaryPropMap[OperatorNodeBinaryPropMap["End"] = 5] = "End";
    })(OperatorNodeBinaryPropMap || (OperatorNodeBinaryPropMap = {}));
    /**
     * Property map for binary serialization.
     */
    var ParenthesisNodeBinaryPropMap;
    (function (ParenthesisNodeBinaryPropMap) {
        ParenthesisNodeBinaryPropMap[ParenthesisNodeBinaryPropMap["Expression"] = 1] = "Expression";
        ParenthesisNodeBinaryPropMap[ParenthesisNodeBinaryPropMap["Start"] = 2] = "Start";
        ParenthesisNodeBinaryPropMap[ParenthesisNodeBinaryPropMap["End"] = 3] = "End";
    })(ParenthesisNodeBinaryPropMap || (ParenthesisNodeBinaryPropMap = {}));
    /**
     * Possible token types in the logical expression.
     */
    var TokenType;
    (function (TokenType) {
        TokenType[TokenType["Variable"] = 0] = "Variable";
        TokenType[TokenType["Operator"] = 1] = "Operator";
        TokenType[TokenType["Parenthesis"] = 2] = "Parenthesis";
    })(TokenType || (TokenType = {}));
    /**
     * Possible node types in the logical expression.
     */
    var NodeType;
    (function (NodeType) {
        NodeType["Variable"] = "Variable";
        NodeType["Operator"] = "Operator";
        NodeType["Parenthesis"] = "Parenthesis";
    })(NodeType || (NodeType = {}));
    /**
     * Precedence of the operators, larger number means higher precedence.
     */
    const OPERATOR_PRECEDENCE = {
        [OperatorValue.Not]: 3,
        [OperatorValue.And]: 2,
        [OperatorValue.Or]: 1,
    };
    const OPERATOR_BINARY_MAP = new Map([
        [OperatorValue.Not, 0],
        [OperatorValue.And, 1],
        [OperatorValue.Or, 2],
    ]);
    const OPERATOR_BINARY_MAP_REVERSE = new Map(Array.from(OPERATOR_BINARY_MAP).map(([key, value]) => [value, key]));
    /**
     * Gets the string representation of the operator from the binary representation.
     *
     * @param binary Binary representation of the operator
     * @returns String representation of the operator
     * @throws If the operator is unknown
     */
    const getOperatorOrFail = (binary) => {
        const operator = OPERATOR_BINARY_MAP_REVERSE.get(binary);
        if (isUndefined$1(operator)) {
            throw new Error(`Unknown operator: ${binary}`);
        }
        return operator;
    };
    /**
     * Serialization map for known variables.
     */
    const KNOWN_VARIABLES_MAP = new Map([
        ['ext_abp', 0],
        ['ext_ublock', 1],
        ['ext_ubol', 2],
        ['ext_devbuild', 3],
        ['env_chromium', 4],
        ['env_edge', 5],
        ['env_firefox', 6],
        ['env_mobile', 7],
        ['env_safari', 8],
        ['env_mv3', 9],
        ['false', 10],
        ['cap_html_filtering', 11],
        ['cap_user_stylesheet', 12],
        ['adguard', 13],
        ['adguard_app_windows', 14],
        ['adguard_app_mac', 15],
        ['adguard_app_android', 16],
        ['adguard_app_ios', 17],
        ['adguard_ext_safari', 18],
        ['adguard_ext_chromium', 19],
        ['adguard_ext_firefox', 20],
        ['adguard_ext_edge', 21],
        ['adguard_ext_opera', 22],
        ['adguard_ext_android_cb', 23],
        // TODO: Add 'adguard_ext_chromium_mv3' to the list
    ]);
    /**
     * Deserialization map for known variables.
     */
    const KNOWN_VARIABLES_MAP_REVERSE = new Map(Array.from(KNOWN_VARIABLES_MAP).map(([key, value]) => [value, key]));
    /**
     * Gets the frequent name of the variable from the binary representation.
     *
     * @param binary Binary representation of the variable
     * @returns Frequent name of the variable
     * @throws If the variable is unknown
     */
    const getFrequentNameOrFail = (binary) => {
        const name = KNOWN_VARIABLES_MAP_REVERSE.get(binary);
        if (isUndefined$1(name)) {
            throw new Error(`Unknown frequent name: ${binary}`);
        }
        return name;
    };
    /**
     * `LogicalExpressionParser` is responsible for parsing logical expressions.
     *
     * @example
     * From the following rule:
     * ```adblock
     * !#if (adguard_ext_android_cb || adguard_ext_safari)
     * ```
     * this parser will parse the expression `(adguard_ext_android_cb || adguard_ext_safari)`.
     */
    // TODO: Refactor this class
    class LogicalExpressionParser extends ParserBase {
        /**
         * Split the expression into tokens.
         *
         * @param raw Source code of the expression
         * @param baseOffset Starting offset of the input. Node locations are calculated relative to this offset.
         * @returns Token list
         * @throws {AdblockSyntaxError} If the expression is invalid
         */
        static tokenize(raw, baseOffset = 0) {
            const tokens = [];
            let offset = 0;
            while (offset < raw.length) {
                const char = raw[offset];
                if (StringUtils.isWhitespace(char)) {
                    // Ignore whitespace
                    offset += 1;
                }
                else if (StringUtils.isLetter(char)) {
                    // Save the start offset of the variable name
                    const nameStart = offset;
                    // Variable name shouldn't start with a number or underscore,
                    // but can contain them
                    while (offset + 1 < raw.length
                        && (StringUtils.isAlphaNumeric(raw[offset + 1]) || raw[offset + 1] === UNDERSCORE)) {
                        offset += 1;
                    }
                    tokens.push({
                        type: TokenType.Variable,
                        start: nameStart,
                        end: offset + 1,
                    });
                    offset += 1;
                }
                else if (char === OPEN_PARENTHESIS || char === CLOSE_PARENTHESIS) {
                    // Parenthesis
                    tokens.push({
                        type: TokenType.Parenthesis,
                        start: offset,
                        end: offset + 1,
                    });
                    offset += 1;
                }
                else if (char === AMPERSAND || char === PIPE) {
                    // Parse operator
                    if (offset + 1 < raw.length && raw[offset + 1] === char) {
                        tokens.push({
                            type: TokenType.Operator,
                            start: offset,
                            end: offset + 2,
                        });
                        offset += 2;
                    }
                    else {
                        throw new AdblockSyntaxError(`Unexpected character "${char}"`, baseOffset + offset, baseOffset + offset + 1);
                    }
                }
                else if (char === EXCLAMATION_MARK) {
                    tokens.push({
                        type: TokenType.Operator,
                        start: offset,
                        end: offset + 1,
                    });
                    offset += 1;
                }
                else {
                    throw new AdblockSyntaxError(`Unexpected character "${char}"`, baseOffset + offset, baseOffset + offset + 1);
                }
            }
            return tokens;
        }
        /**
         * Parses a logical expression.
         *
         * @param raw Raw input to parse.
         * @param options Global parser options.
         * @param baseOffset Starting offset of the input. Node locations are calculated relative to this offset.
         * @returns Parsed expression
         * @throws {AdblockSyntaxError} If the expression is invalid
         */
        // TODO: Create a separate TokenStream class
        static parse(raw, options = defaultParserOptions, baseOffset = 0) {
            // Tokenize the source (produces an array of tokens)
            const tokens = LogicalExpressionParser.tokenize(raw, baseOffset);
            // Current token index
            let tokenIndex = 0;
            /**
             * Consumes a token of the expected type.
             *
             * @param type Expected token type
             * @returns The consumed token
             */
            function consume(type) {
                const token = tokens[tokenIndex];
                if (!token) {
                    throw new AdblockSyntaxError(`Expected token of type "${type}", but reached end of input`, baseOffset, baseOffset + raw.length);
                }
                // We only use this function internally, so we can safely ignore this
                // from the coverage report
                // istanbul ignore next
                if (token.type !== type) {
                    throw new AdblockSyntaxError(`Expected token of type "${type}", but got "${token.type}"`, baseOffset + token.start, baseOffset + token.end);
                }
                tokenIndex += 1;
                return token;
            }
            /**
             * Parses a variable.
             *
             * @returns Variable node
             */
            function parseVariable() {
                const token = consume(TokenType.Variable);
                const result = {
                    type: NodeType.Variable,
                    name: raw.slice(token.start, token.end),
                };
                if (options.isLocIncluded) {
                    result.start = baseOffset + token.start;
                    result.end = baseOffset + token.end;
                }
                return result;
            }
            /**
             * Parses a binary expression.
             *
             * @param left Left-hand side of the expression
             * @param minPrecedence Minimum precedence of the operator
             * @returns Binary expression node
             */
            function parseBinaryExpression(left, minPrecedence = 0) {
                let node = left;
                let operatorToken;
                while (tokens[tokenIndex]) {
                    operatorToken = tokens[tokenIndex];
                    if (!operatorToken || operatorToken.type !== TokenType.Operator) {
                        break;
                    }
                    // It is safe to cast here, because we already checked the type
                    const operator = raw.slice(operatorToken.start, operatorToken.end);
                    const precedence = OPERATOR_PRECEDENCE[operator];
                    if (precedence < minPrecedence) {
                        break;
                    }
                    tokenIndex += 1;
                    // eslint-disable-next-line @typescript-eslint/no-use-before-define
                    const right = parseExpression(precedence + 1);
                    const newNode = {
                        type: NodeType.Operator,
                        operator,
                        left: node,
                        right,
                    };
                    if (options.isLocIncluded) {
                        newNode.start = node.start ?? baseOffset + operatorToken.start;
                        newNode.end = right.end ?? baseOffset + operatorToken.end;
                    }
                    node = newNode;
                }
                return node;
            }
            /**
             * Parses a parenthesized expression.
             *
             * @returns Parenthesized expression node
             */
            function parseParenthesizedExpression() {
                consume(TokenType.Parenthesis);
                // eslint-disable-next-line @typescript-eslint/no-use-before-define
                const expression = parseExpression();
                consume(TokenType.Parenthesis);
                const result = {
                    type: NodeType.Parenthesis,
                    expression,
                };
                if (options.isLocIncluded) {
                    result.start = expression.start;
                    result.end = expression.end;
                }
                return result;
            }
            /**
             * Parses an expression.
             *
             * @param minPrecedence Minimum precedence of the operator
             * @returns Expression node
             */
            function parseExpression(minPrecedence = 0) {
                let node;
                const token = tokens[tokenIndex];
                const value = raw.slice(token.start, token.end);
                if (token.type === TokenType.Variable) {
                    node = parseVariable();
                }
                else if (token.type === TokenType.Operator && value === OperatorValue.Not) {
                    tokenIndex += 1;
                    const expression = parseExpression(OPERATOR_PRECEDENCE[OperatorValue.Not]);
                    node = {
                        type: NodeType.Operator,
                        operator: OperatorValue.Not,
                        left: expression,
                    };
                    if (options.isLocIncluded) {
                        if (expression.end) {
                            node.start = baseOffset + token.start;
                            // no need to shift the node location, because it's already shifted
                            node.end = expression.end;
                        }
                        else {
                            node.start = baseOffset + token.start;
                            node.end = baseOffset + token.end;
                        }
                    }
                }
                else if (token.type === TokenType.Parenthesis && value === OPEN_PARENTHESIS) {
                    node = parseParenthesizedExpression();
                }
                else {
                    throw new AdblockSyntaxError(`Unexpected token "${value}"`, baseOffset + token.start, baseOffset + token.end);
                }
                return parseBinaryExpression(node, minPrecedence);
            }
            const expression = parseExpression();
            if (tokenIndex !== tokens.length) {
                throw new AdblockSyntaxError(`Unexpected token "${tokens[tokenIndex].type}"`, baseOffset + tokens[tokenIndex].start, baseOffset + tokens[tokenIndex].end);
            }
            return expression;
        }
        /**
         * Generates a string representation of the logical expression (serialization).
         *
         * @param node Expression node
         * @returns String representation of the logical expression
         */
        static generate(node) {
            if (node.type === NodeType.Variable) {
                return node.name;
            }
            if (node.type === NodeType.Operator) {
                const left = LogicalExpressionParser.generate(node.left);
                const right = node.right ? LogicalExpressionParser.generate(node.right) : undefined;
                const { operator } = node;
                // Special case for NOT operator
                if (operator === OperatorValue.Not) {
                    return `${operator}${left}`;
                }
                // Right operand is required for AND and OR operators
                if (!right) {
                    throw new Error('Expected right operand');
                }
                return `${left} ${operator} ${right}`;
            }
            if (node.type === NodeType.Parenthesis) {
                const expressionString = LogicalExpressionParser.generate(node.expression);
                return `(${expressionString})`;
            }
            // Theoretically, this shouldn't happen if the library is used correctly
            throw new Error('Unexpected node type');
        }
        /**
         * Serializes a variable node to binary format.
         *
         * @param node Node to serialize.
         * @param buffer ByteBuffer for writing binary data.
         */
        // TODO: create a common serialize / deserialize interface for such nodes (Variable, Value, Parameter, etc.)
        static serializeVariableNode(node, buffer) {
            buffer.writeUint8(BinaryTypeMap.ExpressionVariableNode);
            const frequentName = KNOWN_VARIABLES_MAP.get(node.name);
            if (!isUndefined$1(frequentName)) {
                buffer.writeUint8(VariableNodeBinaryPropMap.FrequentName);
                buffer.writeUint8(frequentName);
            }
            else {
                buffer.writeUint8(VariableNodeBinaryPropMap.Name);
                buffer.writeString(node.name);
            }
            if (!isUndefined$1(node.start)) {
                buffer.writeUint8(VariableNodeBinaryPropMap.Start);
                buffer.writeUint32(node.start);
            }
            if (!isUndefined$1(node.end)) {
                buffer.writeUint8(VariableNodeBinaryPropMap.End);
                buffer.writeUint32(node.end);
            }
            buffer.writeUint8(NULL);
        }
        /**
         * Serializes a parenthesis node to binary format.
         *
         * @param node Node to serialize.
         * @param buffer ByteBuffer for writing binary data.
         */
        static serializeParenthesisNode(node, buffer) {
            buffer.writeUint8(BinaryTypeMap.ExpressionParenthesisNode);
            buffer.writeUint8(ParenthesisNodeBinaryPropMap.Expression);
            LogicalExpressionParser.serialize(node.expression, buffer);
            if (!isUndefined$1(node.start)) {
                buffer.writeUint8(ParenthesisNodeBinaryPropMap.Start);
                buffer.writeUint32(node.start);
            }
            if (!isUndefined$1(node.end)) {
                buffer.writeUint8(ParenthesisNodeBinaryPropMap.End);
                buffer.writeUint32(node.end);
            }
            buffer.writeUint8(NULL);
        }
        /**
         * Serializes an operator node to binary format.
         *
         * @param node Node to serialize.
         * @param buffer ByteBuffer for writing binary data.
         */
        static serializeOperatorNode(node, buffer) {
            buffer.writeUint8(BinaryTypeMap.ExpressionOperatorNode);
            buffer.writeUint8(OperatorNodeBinaryPropMap.Operator);
            const operatorBinary = OPERATOR_BINARY_MAP.get(node.operator);
            if (isUndefined$1(operatorBinary)) {
                throw new Error(`Unknown operator: ${node.operator}`);
            }
            buffer.writeUint8(operatorBinary);
            buffer.writeUint8(OperatorNodeBinaryPropMap.Left);
            LogicalExpressionParser.serialize(node.left, buffer);
            if (node.right) {
                buffer.writeUint8(OperatorNodeBinaryPropMap.Right);
                LogicalExpressionParser.serialize(node.right, buffer);
            }
            if (!isUndefined$1(node.start)) {
                buffer.writeUint8(OperatorNodeBinaryPropMap.Start);
                buffer.writeUint32(node.start);
            }
            if (!isUndefined$1(node.end)) {
                buffer.writeUint8(OperatorNodeBinaryPropMap.End);
                buffer.writeUint32(node.end);
            }
            buffer.writeUint8(NULL);
        }
        /**
         * Serializes a logical expression node to binary format.
         *
         * @param node Node to serialize.
         * @param buffer ByteBuffer for writing binary data.
         */
        static serialize(node, buffer) {
            switch (node.type) {
                case NodeType.Variable:
                    LogicalExpressionParser.serializeVariableNode(node, buffer);
                    break;
                case NodeType.Operator:
                    LogicalExpressionParser.serializeOperatorNode(node, buffer);
                    break;
                case NodeType.Parenthesis:
                    LogicalExpressionParser.serializeParenthesisNode(node, buffer);
                    break;
                default:
                    throw new Error(`Unexpected node type: ${node.type}`);
            }
            buffer.writeUint8(NULL);
        }
        /**
         * Deserializes a variable node from binary format.
         *
         * @param buffer ByteBuffer for reading binary data.
         * @param node Destination node.
         * @throws If the binary data is malformed.
         */
        static deserializeVariableNode(buffer, node) {
            buffer.assertUint8(BinaryTypeMap.ExpressionVariableNode);
            node.type = NodeType.Variable;
            let prop = buffer.readUint8();
            while (prop !== NULL) {
                switch (prop) {
                    case VariableNodeBinaryPropMap.Name:
                        node.name = buffer.readString();
                        break;
                    case VariableNodeBinaryPropMap.FrequentName:
                        node.name = getFrequentNameOrFail(buffer.readUint8());
                        break;
                    case VariableNodeBinaryPropMap.Start:
                        node.start = buffer.readUint32();
                        break;
                    case VariableNodeBinaryPropMap.End:
                        node.end = buffer.readUint32();
                        break;
                    default:
                        throw new Error(`Invalid property: ${prop}`);
                }
                prop = buffer.readUint8();
            }
        }
        /**
         * Deserializes a parenthesis node from binary format.
         *
         * @param buffer ByteBuffer for reading binary data.
         * @param node Destination node.
         * @throws If the binary data is malformed.
         */
        static deserializeParenthesisNode(buffer, node) {
            buffer.assertUint8(BinaryTypeMap.ExpressionParenthesisNode);
            node.type = NodeType.Parenthesis;
            let prop = buffer.readUint8();
            while (prop !== NULL) {
                switch (prop) {
                    case ParenthesisNodeBinaryPropMap.Expression:
                        LogicalExpressionParser.deserialize(buffer, node.expression = {});
                        break;
                    case ParenthesisNodeBinaryPropMap.Start:
                        node.start = buffer.readUint32();
                        break;
                    case ParenthesisNodeBinaryPropMap.End:
                        node.end = buffer.readUint32();
                        break;
                    default:
                        throw new Error(`Invalid property: ${prop}`);
                }
                prop = buffer.readUint8();
            }
        }
        /**
         * Deserializes an operator node from binary format.
         *
         * @param buffer ByteBuffer for reading binary data.
         * @param node Destination node.
         * @throws If the binary data is malformed.
         */
        static deserializeOperatorNode(buffer, node) {
            buffer.assertUint8(BinaryTypeMap.ExpressionOperatorNode);
            node.type = NodeType.Operator;
            let prop = buffer.readUint8();
            while (prop !== NULL) {
                switch (prop) {
                    case OperatorNodeBinaryPropMap.Operator:
                        node.operator = getOperatorOrFail(buffer.readUint8());
                        break;
                    case OperatorNodeBinaryPropMap.Left:
                        LogicalExpressionParser.deserialize(buffer, node.left = {});
                        break;
                    case OperatorNodeBinaryPropMap.Right:
                        LogicalExpressionParser.deserialize(buffer, node.right = {});
                        break;
                    case OperatorNodeBinaryPropMap.Start:
                        node.start = buffer.readUint32();
                        break;
                    case OperatorNodeBinaryPropMap.End:
                        node.end = buffer.readUint32();
                        break;
                    default:
                        throw new Error(`Invalid property: ${prop}`);
                }
                prop = buffer.readUint8();
            }
        }
        /**
         * Deserializes a logical expression node from binary format.
         *
         * @param buffer ByteBuffer for reading binary data.
         * @param node Destination node.
         * @throws If the binary data is malformed.
         */
        static deserialize(buffer, node) {
            // note: we just do a simple lookahead here, because advancing the buffer is done in the
            // 'sub-deserialize' methods
            let type = buffer.peekUint8();
            while (type !== NULL) {
                switch (type) {
                    case BinaryTypeMap.ExpressionVariableNode:
                        LogicalExpressionParser.deserializeVariableNode(buffer, node);
                        break;
                    case BinaryTypeMap.ExpressionOperatorNode:
                        LogicalExpressionParser.deserializeOperatorNode(buffer, node);
                        break;
                    case BinaryTypeMap.ExpressionParenthesisNode:
                        // eslint-disable-next-line max-len
                        LogicalExpressionParser.deserializeParenthesisNode(buffer, node);
                        break;
                    default:
                        throw new Error(`Unexpected node type: ${type}`);
                }
                type = buffer.peekUint8();
            }
            // consume NULL
            buffer.readUint8();
        }
    }

    /* eslint-disable no-param-reassign */
    /**
     * Pre-processor directives
     *
     * @see {@link https://kb.adguard.com/en/general/how-to-create-your-own-ad-filters#pre-processor-directives}
     * @see {@link https://github.com/gorhill/uBlock/wiki/Static-filter-syntax#pre-parsing-directives}
     */
    /**
     * Property map for binary serialization. This helps to reduce the size of the serialized data,
     * as it allows us to use a single byte to represent a property.
     *
     * ! IMPORTANT: If you change values here, please update the {@link BINARY_SCHEMA_VERSION}!
     *
     * @note Only 256 values can be represented this way.
     */
    var PreProcessorRuleSerializationMap;
    (function (PreProcessorRuleSerializationMap) {
        PreProcessorRuleSerializationMap[PreProcessorRuleSerializationMap["Name"] = 1] = "Name";
        PreProcessorRuleSerializationMap[PreProcessorRuleSerializationMap["Params"] = 2] = "Params";
        PreProcessorRuleSerializationMap[PreProcessorRuleSerializationMap["Syntax"] = 3] = "Syntax";
        PreProcessorRuleSerializationMap[PreProcessorRuleSerializationMap["Start"] = 4] = "Start";
        PreProcessorRuleSerializationMap[PreProcessorRuleSerializationMap["End"] = 5] = "End";
    })(PreProcessorRuleSerializationMap || (PreProcessorRuleSerializationMap = {}));
    /**
     * Value map for binary serialization. This helps to reduce the size of the serialized data,
     * as it allows us to use a single byte to represent frequently used values.
     *
     * ! IMPORTANT: If you change values here, please update the {@link BINARY_SCHEMA_VERSION}!
     *
     * @note Only 256 values can be represented this way.
     *
     * @see {@link https://adguard.com/kb/general/ad-filtering/create-own-filters/#preprocessor-directives}
     * @see {@link https://github.com/gorhill/uBlock/wiki/Static-filter-syntax#pre-parsing-directives}
     */
    const FREQUENT_DIRECTIVES_SERIALIZATION_MAP = new Map([
        ['if', 0],
        ['else', 1],
        ['endif', 2],
        ['include', 3],
        ['safari_cb_affinity', 4],
    ]);
    /**
     * Value map for binary deserialization. This helps to reduce the size of the serialized data,
     * as it allows us to use a single byte to represent frequently used values.
     */
    const FREQUENT_DIRECTIVES_DESERIALIZATION_MAP = new Map(Array.from(FREQUENT_DIRECTIVES_SERIALIZATION_MAP).map(([key, value]) => [value, key]));
    /**
     * Value map for binary serialization. This helps to reduce the size of the serialized data,
     * as it allows us to use a single byte to represent frequently used values.
     *
     * ! IMPORTANT: If you change values here, please update the {@link BINARY_SCHEMA_VERSION}!
     *
     * @note Only 256 values can be represented this way.
     */
    const FREQUENT_PARAMS_SERIALIZATION_MAP = new Map([
        // safari_cb_affinity parameters
        ['general', 0],
        ['privacy', 1],
        ['social', 2],
        ['security', 3],
        ['other', 4],
        ['custom', 5],
        ['all', 6],
    ]);
    /**
     * Value map for binary deserialization. This helps to reduce the size of the serialized data,
     * as it allows us to use a single byte to represent frequently used values.
     */
    const FREQUENT_PARAMS_DESERIALIZATION_MAP = new Map(Array.from(FREQUENT_PARAMS_SERIALIZATION_MAP).map(([key, value]) => [value, key]));
    /**
     * `PreProcessorParser` is responsible for parsing preprocessor rules.
     * Pre-processor comments are special comments that are used to control the behavior of the filter list processor.
     * Please note that this parser only handles general syntax for now, and does not validate the parameters at
     * the parsing stage.
     *
     * @example
     * If your rule is
     * ```adblock
     * !#if (adguard)
     * ```
     * then the directive's name is `if` and its value is `(adguard)`, but the parameter list
     * is not parsed / validated further.
     * @see {@link https://kb.adguard.com/en/general/how-to-create-your-own-ad-filters#pre-processor-directives}
     * @see {@link https://github.com/gorhill/uBlock/wiki/Static-filter-syntax#pre-parsing-directives}
     */
    class PreProcessorCommentRuleParser extends ParserBase {
        /**
         * Determines whether the rule is a pre-processor rule.
         *
         * @param raw Raw rule
         * @returns `true` if the rule is a pre-processor rule, `false` otherwise
         */
        static isPreProcessorRule(raw) {
            const trimmed = raw.trim();
            // Avoid this case: !##... (commonly used in AdGuard filters)
            return trimmed.startsWith(PREPROCESSOR_MARKER) && trimmed[PREPROCESSOR_MARKER_LEN] !== HASHMARK;
        }
        /**
         * Parses a raw rule as a pre-processor comment.
         *
         * @param raw Raw input to parse.
         * @param options Global parser options.
         * @param baseOffset Starting offset of the input. Node locations are calculated relative to this offset.
         * @returns
         * Pre-processor comment AST or null (if the raw rule cannot be parsed as a pre-processor comment)
         */
        static parse(raw, options = defaultParserOptions, baseOffset = 0) {
            // Ignore non-pre-processor rules
            if (!PreProcessorCommentRuleParser.isPreProcessorRule(raw)) {
                return null;
            }
            let offset = 0;
            // Ignore whitespace characters before the rule (if any)
            offset = StringUtils.skipWS(raw, offset);
            // Ignore the pre-processor marker
            offset += PREPROCESSOR_MARKER_LEN;
            // Ignore whitespace characters after the pre-processor marker (if any)
            // Note: this is incorrect according to the spec, but we do it for tolerance
            offset = StringUtils.skipWS(raw, offset);
            // Directive name should start at this offset, so we save this offset now
            const nameStart = offset;
            // Consume directive name, so parse the sequence until the first
            // whitespace / opening parenthesis / end of string
            while (offset < raw.length) {
                const ch = raw[offset];
                if (ch === PREPROCESSOR_SEPARATOR || ch === OPEN_PARENTHESIS) {
                    break;
                }
                offset += 1;
            }
            // Save name end offset
            const nameEnd = offset;
            // Create name node
            const name = ValueParser.parse(raw.slice(nameStart, nameEnd), options, baseOffset + nameStart);
            // Ignore whitespace characters after the directive name (if any)
            // Note: this may incorrect according to the spec, but we do it for tolerance
            offset = StringUtils.skipWS(raw, offset);
            // If the directive name is "safari_cb_affinity", then we have a special case
            if (name.value === SAFARI_CB_AFFINITY) {
                // Throw error if there are spaces after the directive name
                if (offset > nameEnd) {
                    throw new AdblockSyntaxError(`Unexpected whitespace after "${SAFARI_CB_AFFINITY}" directive name`, baseOffset + nameEnd, baseOffset + offset);
                }
                // safari_cb_affinity directive optionally accepts a parameter list
                // So at this point we should check if there are parameters or not
                // (cb_affinity directive followed by an opening parenthesis or if we
                // skip the whitespace we reach the end of the string)
                if (StringUtils.skipWS(raw, offset) !== raw.length) {
                    if (raw[offset] !== OPEN_PARENTHESIS) {
                        throw new AdblockSyntaxError(`Unexpected character '${raw[offset]}' after '${SAFARI_CB_AFFINITY}' directive name`, baseOffset + offset, baseOffset + offset + 1);
                    }
                    // If we have parameters, then we should parse them
                    // Note: we don't validate the parameters at this stage
                    // Ignore opening parenthesis
                    offset += 1;
                    // Save parameter list start offset
                    const parameterListStart = offset;
                    // Check for closing parenthesis
                    const closingParenthesesIndex = StringUtils.skipWSBack(raw);
                    if (closingParenthesesIndex === -1 || raw[closingParenthesesIndex] !== CLOSE_PARENTHESIS) {
                        throw new AdblockSyntaxError(`Missing closing parenthesis for '${SAFARI_CB_AFFINITY}' directive`, baseOffset + offset, baseOffset + raw.length);
                    }
                    // Save parameter list end offset
                    const parameterListEnd = closingParenthesesIndex;
                    // Parse parameters between the opening and closing parentheses
                    const result = {
                        type: CommentRuleType.PreProcessorCommentRule,
                        category: RuleCategory.Comment,
                        syntax: AdblockSyntax.Adg,
                        name,
                        // comma separated list of parameters
                        params: ParameterListParser.parse(raw.slice(parameterListStart, parameterListEnd), options, baseOffset + parameterListStart, COMMA),
                    };
                    if (options.includeRaws) {
                        result.raws = {
                            text: raw,
                        };
                    }
                    if (options.isLocIncluded) {
                        result.start = baseOffset;
                        result.end = baseOffset + raw.length;
                    }
                    return result;
                }
            }
            // If we reached the end of the string, then we have a directive without parameters
            // (e.g. "!#safari_cb_affinity" or "!#endif")
            // No need to continue parsing in this case.
            if (offset === raw.length) {
                // Throw error if the directive name is "if" or "include", because these directives
                // should have parameters
                if (name.value === IF || name.value === INCLUDE) {
                    throw new AdblockSyntaxError(`Directive "${name.value}" requires parameters`, baseOffset, baseOffset + raw.length);
                }
                const result = {
                    type: CommentRuleType.PreProcessorCommentRule,
                    category: RuleCategory.Comment,
                    syntax: AdblockSyntax.Common,
                    name,
                };
                if (options.includeRaws) {
                    result.raws = {
                        text: raw,
                    };
                }
                if (options.isLocIncluded) {
                    result.start = baseOffset;
                    result.end = baseOffset + raw.length;
                }
                return result;
            }
            // Get start and end offsets of the directive parameters
            const paramsStart = offset;
            const paramsEnd = StringUtils.skipWSBack(raw) + 1;
            // Prepare parameters node
            let params;
            // Parse parameters. Handle "if" and "safari_cb_affinity" directives
            // separately.
            if (name.value === IF) {
                params = LogicalExpressionParser.parse(raw.slice(paramsStart, paramsEnd), options, baseOffset + paramsStart);
            }
            else {
                params = ValueParser.parse(raw.slice(paramsStart, paramsEnd), options, baseOffset + paramsStart);
            }
            const result = {
                type: CommentRuleType.PreProcessorCommentRule,
                category: RuleCategory.Comment,
                syntax: AdblockSyntax.Common,
                name,
                params,
            };
            if (options.includeRaws) {
                result.raws = {
                    text: raw,
                };
            }
            if (options.isLocIncluded) {
                result.start = baseOffset;
                result.end = baseOffset + raw.length;
            }
            return result;
        }
        /**
         * Converts a pre-processor comment node to a string.
         *
         * @param node Pre-processor comment node
         * @returns Raw string
         */
        static generate(node) {
            let result = EMPTY;
            result += PREPROCESSOR_MARKER;
            result += node.name.value;
            if (node.params) {
                // Space is not allowed after "safari_cb_affinity" directive, so we need to handle it separately.
                if (node.name.value !== SAFARI_CB_AFFINITY) {
                    result += SPACE;
                }
                if (node.params.type === 'Value') {
                    result += ValueParser.generate(node.params);
                }
                else if (node.params.type === 'ParameterList') {
                    result += OPEN_PARENTHESIS;
                    result += ParameterListParser.generate(node.params);
                    result += CLOSE_PARENTHESIS;
                }
                else {
                    result += LogicalExpressionParser.generate(node.params);
                }
            }
            return result;
        }
        /**
         * Serializes a pre-processor comment node to binary format.
         *
         * @param node Node to serialize.
         * @param buffer ByteBuffer for writing binary data.
         */
        // TODO: add support for raws, if ever needed
        static serialize(node, buffer) {
            buffer.writeUint8(BinaryTypeMap.PreProcessorCommentRuleNode);
            buffer.writeUint8(PreProcessorRuleSerializationMap.Name);
            ValueParser.serialize(node.name, buffer, FREQUENT_DIRECTIVES_SERIALIZATION_MAP);
            buffer.writeUint8(PreProcessorRuleSerializationMap.Syntax);
            buffer.writeUint8(SYNTAX_SERIALIZATION_MAP.get(node.syntax) ?? 0);
            if (!isUndefined$1(node.params)) {
                buffer.writeUint8(PreProcessorRuleSerializationMap.Params);
                if (node.params.type === 'Value') {
                    ValueParser.serialize(node.params, buffer);
                }
                else if (node.params.type === 'ParameterList') {
                    ParameterListParser.serialize(node.params, buffer, FREQUENT_PARAMS_SERIALIZATION_MAP, true);
                }
                else {
                    LogicalExpressionParser.serialize(node.params, buffer);
                }
            }
            if (!isUndefined$1(node.start)) {
                buffer.writeUint8(PreProcessorRuleSerializationMap.Start);
                buffer.writeUint32(node.start);
            }
            if (!isUndefined$1(node.end)) {
                buffer.writeUint8(PreProcessorRuleSerializationMap.End);
                buffer.writeUint32(node.end);
            }
            buffer.writeUint8(NULL);
        }
        /**
         * Deserializes a pre-processor comment node from binary format.
         *
         * @param buffer ByteBuffer for reading binary data.
         * @param node Destination node.
         * @throws If the binary data is malformed.
         */
        static deserialize(buffer, node) {
            buffer.assertUint8(BinaryTypeMap.PreProcessorCommentRuleNode);
            node.type = CommentRuleType.PreProcessorCommentRule;
            node.category = RuleCategory.Comment;
            node.syntax = AdblockSyntax.Common;
            let prop = buffer.readUint8();
            while (prop !== NULL) {
                switch (prop) {
                    case PreProcessorRuleSerializationMap.Name:
                        ValueParser.deserialize(buffer, node.name = {}, FREQUENT_DIRECTIVES_DESERIALIZATION_MAP);
                        break;
                    case PreProcessorRuleSerializationMap.Syntax:
                        node.syntax = SYNTAX_DESERIALIZATION_MAP.get(buffer.readUint8()) ?? AdblockSyntax.Common;
                        break;
                    case PreProcessorRuleSerializationMap.Params:
                        switch (buffer.peekUint8()) {
                            case BinaryTypeMap.ValueNode:
                                ValueParser.deserialize(buffer, node.params = {});
                                break;
                            case BinaryTypeMap.ParameterListNode:
                                // eslint-disable-next-line max-len
                                ParameterListParser.deserialize(buffer, node.params = {}, FREQUENT_PARAMS_DESERIALIZATION_MAP);
                                break;
                            case BinaryTypeMap.ExpressionOperatorNode:
                            case BinaryTypeMap.ExpressionParenthesisNode:
                            case BinaryTypeMap.ExpressionVariableNode:
                                LogicalExpressionParser.deserialize(buffer, node.params = {});
                                break;
                            default:
                                throw new Error(`Invalid binary type: ${prop}`);
                        }
                        break;
                    case PreProcessorRuleSerializationMap.Start:
                        node.start = buffer.readUint32();
                        break;
                    case PreProcessorRuleSerializationMap.End:
                        node.end = buffer.readUint32();
                        break;
                    default:
                        throw new Error(`Invalid property: ${prop}`);
                }
                prop = buffer.readUint8();
            }
        }
    }

    /* eslint-disable no-param-reassign */
    /**
     * Property map for binary serialization. This helps to reduce the size of the serialized data,
     * as it allows us to use a single byte to represent a property.
     *
     * ! IMPORTANT: If you change values here, please update the {@link BINARY_SCHEMA_VERSION}!
     *
     * @note Only 256 values can be represented this way.
     */
    var SimpleCommentRuleSerializationMap;
    (function (SimpleCommentRuleSerializationMap) {
        SimpleCommentRuleSerializationMap[SimpleCommentRuleSerializationMap["Marker"] = 1] = "Marker";
        SimpleCommentRuleSerializationMap[SimpleCommentRuleSerializationMap["Text"] = 2] = "Text";
        SimpleCommentRuleSerializationMap[SimpleCommentRuleSerializationMap["Start"] = 3] = "Start";
        SimpleCommentRuleSerializationMap[SimpleCommentRuleSerializationMap["End"] = 4] = "End";
    })(SimpleCommentRuleSerializationMap || (SimpleCommentRuleSerializationMap = {}));
    /**
     * `SimpleCommentParser` is responsible for parsing simple comments.
     * Some comments have a special meaning in adblock syntax, like agent comments or hints,
     * but this parser is only responsible for parsing regular comments,
     * whose only purpose is to provide some human-readable information.
     *
     * @example
     * ```adblock
     * ! This is a simple comment
     * # This is a simple comment, but in host-like syntax
     * ```
     */
    class SimpleCommentParser extends ParserBase {
        /**
         * Checks if the raw rule is a simple comment.
         *
         * @param raw Raw input to check.
         * @returns `true` if the input is a simple comment, `false` otherwise.
         * @note This method does not check for adblock agent comments.
         */
        static isSimpleComment(raw) {
            const trimmed = raw.trim();
            // Exclamation mark based comments
            if (trimmed.startsWith(CommentMarker.Regular)) {
                return true;
            }
            // Hashmark based comments
            // Note: in this case, we must be sure that we do not mistakenly parse a cosmetic rule as a #-like comment,
            // since most cosmetic rule separators also start with #
            if (trimmed.startsWith(CommentMarker.Hashmark)) {
                const result = CosmeticRuleSeparatorUtils.find(trimmed);
                // If we cannot find a separator, it means that the rule is definitely a comment
                if (result === null) {
                    return true;
                }
                // Otherwise, we must check if the separator is followed by a valid selector
                const { end } = result;
                // No valid selector
                if (!trimmed[end + 1]
                    || StringUtils.isWhitespace(trimmed[end + 1])
                    || (trimmed[end + 1] === CommentMarker.Hashmark && trimmed[end + 2] === CommentMarker.Hashmark)) {
                    return true;
                }
            }
            return false;
        }
        /**
         * Parses a raw rule as a simple comment.
         *
         * @param raw Raw input to parse.
         * @param options Global parser options.
         * @param baseOffset Starting offset of the input. Node locations are calculated relative to this offset.
         * @returns Comment rule node or null (if the raw rule cannot be parsed as a simple comment).
         */
        static parse(raw, options = defaultParserOptions, baseOffset = 0) {
            // Ignore non-comment rules
            if (!this.isSimpleComment(raw)) {
                return null;
            }
            // If we are here, it means that the rule is a regular comment
            let offset = 0;
            // Skip leading whitespace (if any)
            offset = StringUtils.skipWS(raw, offset);
            // Get comment marker
            const marker = ValueParser.parse(raw[offset], options, baseOffset + offset);
            // Skip marker
            offset += 1;
            // Get comment text
            const text = ValueParser.parse(raw.slice(offset), options, baseOffset + offset);
            // Regular comment rule
            const result = {
                category: RuleCategory.Comment,
                type: CommentRuleType.CommentRule,
                // TODO: Change syntax when hashmark is used
                syntax: AdblockSyntax.Common,
                marker,
                text,
            };
            if (options.includeRaws) {
                result.raws = {
                    text: raw,
                };
            }
            if (options.isLocIncluded) {
                result.start = baseOffset;
                result.end = baseOffset + raw.length;
            }
            return result;
        }
        /**
         * Converts a comment rule node to a string.
         *
         * @param node Comment rule node.
         * @returns Raw string.
         */
        static generate(node) {
            let result = EMPTY;
            result += ValueParser.generate(node.marker);
            result += ValueParser.generate(node.text);
            return result;
        }
        /**
         * Serializes a simple comment rule node to binary format.
         *
         * @param node Node to serialize.
         * @param buffer ByteBuffer for writing binary data.
         */
        // TODO: add support for raws, if ever needed
        static serialize(node, buffer) {
            buffer.writeUint8(BinaryTypeMap.CommentRuleNode);
            buffer.writeUint8(SimpleCommentRuleSerializationMap.Marker);
            ValueParser.serialize(node.marker, buffer);
            buffer.writeUint8(SimpleCommentRuleSerializationMap.Text);
            ValueParser.serialize(node.text, buffer);
            if (!isUndefined$1(node.start)) {
                buffer.writeUint8(SimpleCommentRuleSerializationMap.Start);
                buffer.writeUint32(node.start);
            }
            if (!isUndefined$1(node.end)) {
                buffer.writeUint8(SimpleCommentRuleSerializationMap.End);
                buffer.writeUint32(node.end);
            }
            buffer.writeUint8(NULL);
        }
        /**
         * Deserializes a simple comment node from binary format.
         *
         * @param buffer ByteBuffer for reading binary data.
         * @param node Destination node.
         * @throws If the binary data is malformed.
         */
        static deserialize(buffer, node) {
            buffer.assertUint8(BinaryTypeMap.CommentRuleNode);
            node.type = CommentRuleType.CommentRule;
            node.category = RuleCategory.Comment;
            node.syntax = AdblockSyntax.Common;
            let prop = buffer.readUint8();
            while (prop !== NULL) {
                switch (prop) {
                    case SimpleCommentRuleSerializationMap.Marker:
                        ValueParser.deserialize(buffer, node.marker = {});
                        break;
                    case SimpleCommentRuleSerializationMap.Text:
                        ValueParser.deserialize(buffer, node.text = {});
                        break;
                    case SimpleCommentRuleSerializationMap.Start:
                        node.start = buffer.readUint32();
                        break;
                    case SimpleCommentRuleSerializationMap.End:
                        node.end = buffer.readUint32();
                        break;
                    default:
                        throw new Error(`Invalid property: ${prop}`);
                }
                prop = buffer.readUint8();
            }
        }
    }

    /* eslint-disable no-param-reassign */
    /**
     * `CommentParser` is responsible for parsing any comment-like adblock rules.
     *
     * @example
     * Example rules:
     *  - Adblock agent rules:
     *      - ```adblock
     *        [AdGuard]
     *        ```
     *      - ```adblock
     *        [Adblock Plus 2.0]
     *        ```
     *      - etc.
     *  - AdGuard hint rules:
     *      - ```adblock
     *        !+ NOT_OPTIMIZED
     *        ```
     *      - ```adblock
     *        !+ NOT_OPTIMIZED PLATFORM(windows)
     *        ```
     *      - etc.
     *  - Pre-processor rules:
     *      - ```adblock
     *        !#if (adguard)
     *        ```
     *      - ```adblock
     *        !#endif
     *        ```
     *      - etc.
     *  - Metadata rules:
     *      - ```adblock
     *        ! Title: My List
     *        ```
     *      - ```adblock
     *        ! Version: 2.0.150
     *        ```
     *      - etc.
     *  - AGLint inline config rules:
     *      - ```adblock
     *        ! aglint-enable some-rule
     *        ```
     *      - ```adblock
     *        ! aglint-disable some-rule
     *        ```
     *      - etc.
     *  - Simple comments:
     *      - Regular version:
     *        ```adblock
     *        ! This is just a comment
     *        ```
     *      - uBlock Origin / "hostlist" version:
     *        ```adblock
     *        # This is just a comment
     *        ```
     *      - etc.
     */
    class CommentRuleParser extends ParserBase {
        /**
         * Checks whether a rule is a comment.
         *
         * @param raw Raw rule
         * @returns `true` if the rule is a comment, `false` otherwise
         */
        static isCommentRule(raw) {
            const trimmed = raw.trim();
            return SimpleCommentParser.isSimpleComment(trimmed) || AgentCommentRuleParser.isAgentRule(trimmed);
        }
        /**
         * Parses a raw rule as comment.
         *
         * @param raw Raw input to parse.
         * @param options Global parser options.
         * @param baseOffset Starting offset of the input. Node locations are calculated relative to this offset.
         * @returns Comment AST or null (if the raw rule cannot be parsed as comment)
         */
        static parse(raw, options = defaultParserOptions, baseOffset = 0) {
            // Ignore non-comment rules
            if (!CommentRuleParser.isCommentRule(raw)) {
                return null;
            }
            // Note: we parse non-functional comments at the end,
            // if the input does not match any of the previous, more specific comment patterns
            return AgentCommentRuleParser.parse(raw, options, baseOffset)
                || HintCommentRuleParser.parse(raw, options, baseOffset)
                || PreProcessorCommentRuleParser.parse(raw, options, baseOffset)
                || MetadataCommentRuleParser.parse(raw, options, baseOffset)
                || ConfigCommentRuleParser.parse(raw, options, baseOffset)
                || SimpleCommentParser.parse(raw, options, baseOffset);
        }
        /**
         * Converts a comment rule node to a string.
         *
         * @param node Comment rule node
         * @returns Raw string
         */
        static generate(node) {
            switch (node.type) {
                case CommentRuleType.AgentCommentRule:
                    return AgentCommentRuleParser.generate(node);
                case CommentRuleType.HintCommentRule:
                    return HintCommentRuleParser.generate(node);
                case CommentRuleType.PreProcessorCommentRule:
                    return PreProcessorCommentRuleParser.generate(node);
                case CommentRuleType.MetadataCommentRule:
                    return MetadataCommentRuleParser.generate(node);
                case CommentRuleType.ConfigCommentRule:
                    return ConfigCommentRuleParser.generate(node);
                case CommentRuleType.CommentRule:
                    return SimpleCommentParser.generate(node);
                default:
                    throw new Error('Unknown comment rule type');
            }
        }
        /**
         * Serializes a comment rule node to binary format.
         *
         * @param node Node to serialize.
         * @param buffer ByteBuffer for writing binary data.
         */
        static serialize(node, buffer) {
            switch (node.type) {
                case CommentRuleType.AgentCommentRule:
                    AgentCommentRuleParser.serialize(node, buffer);
                    return;
                case CommentRuleType.HintCommentRule:
                    HintCommentRuleParser.serialize(node, buffer);
                    return;
                case CommentRuleType.PreProcessorCommentRule:
                    PreProcessorCommentRuleParser.serialize(node, buffer);
                    return;
                case CommentRuleType.MetadataCommentRule:
                    MetadataCommentRuleParser.serialize(node, buffer);
                    return;
                case CommentRuleType.ConfigCommentRule:
                    ConfigCommentRuleParser.serialize(node, buffer);
                    return;
                case CommentRuleType.CommentRule:
                    SimpleCommentParser.serialize(node, buffer);
                    break;
                default:
                    throw new Error('Unknown comment rule type');
            }
        }
        /**
         * Deserializes a comment rule node from binary format.
         *
         * @param buffer ByteBuffer for reading binary data.
         * @param node Destination node.
         * @throws If the binary data is malformed.
         */
        static deserialize(buffer, node) {
            const type = buffer.peekUint8();
            switch (type) {
                case BinaryTypeMap.AgentRuleNode:
                    AgentCommentRuleParser.deserialize(buffer, node);
                    return;
                case BinaryTypeMap.HintRuleNode:
                    HintCommentRuleParser.deserialize(buffer, node);
                    return;
                case BinaryTypeMap.PreProcessorCommentRuleNode:
                    PreProcessorCommentRuleParser.deserialize(buffer, node);
                    return;
                case BinaryTypeMap.MetadataCommentRuleNode:
                    MetadataCommentRuleParser.deserialize(buffer, node);
                    return;
                case BinaryTypeMap.ConfigCommentRuleNode:
                    ConfigCommentRuleParser.deserialize(buffer, node);
                    return;
                case BinaryTypeMap.CommentRuleNode:
                    SimpleCommentParser.deserialize(buffer, node);
                    return;
                default:
                    throw new Error(`Unknown comment rule type: ${type}`);
            }
        }
    }

    /* eslint-disable no-param-reassign */
    /**
     * Property map for binary serialization. This helps to reduce the size of the serialized data,
     * as it allows us to use a single byte to represent a property.
     *
     * ! IMPORTANT: If you change values here, please update the binary schema version
     *
     * @note Only 256 values can be represented this way.
     */
    var ListItemSerializationMap;
    (function (ListItemSerializationMap) {
        ListItemSerializationMap[ListItemSerializationMap["Exception"] = 1] = "Exception";
        ListItemSerializationMap[ListItemSerializationMap["Value"] = 2] = "Value";
        ListItemSerializationMap[ListItemSerializationMap["Start"] = 3] = "Start";
        ListItemSerializationMap[ListItemSerializationMap["End"] = 4] = "End";
    })(ListItemSerializationMap || (ListItemSerializationMap = {}));
    /**
     * Prefixes for error messages which are used for parsing of value lists.
     */
    const LIST_PARSE_ERROR_PREFIX = {
        EMPTY_ITEM: 'Empty value specified in the list',
        NO_MULTIPLE_NEGATION: 'Exception marker cannot be followed by another exception marker',
        NO_SEPARATOR_AFTER_NEGATION: 'Exception marker cannot be followed by a separator',
        NO_SEPARATOR_AT_THE_BEGINNING: 'Value list cannot start with a separator',
        NO_SEPARATOR_AT_THE_END: 'Value list cannot end with a separator',
        NO_WHITESPACE_AFTER_NEGATION: 'Exception marker cannot be followed by whitespace',
    };
    /**
     * Parses a `raw` modifier value which may be represented as a list of items separated by `separator`.
     * Needed for $app, $denyallow, $domain, $method.
     *
     * @param raw Raw input to parse.
     * @param options Global parser options.
     * @param baseOffset Starting offset of the input. Node locations are calculated relative to this offset.
     * @param separator Separator character (default: comma)
     * @param type Type of the list items (default: {@link ListItemNodeType.Domain}).
     * @template T Type of the list items.
     *
     * @returns List of parsed items.
     * @throws An {@link AdblockSyntaxError} if the list is syntactically invalid
     *
     * @example
     * - parses an app list — `com.example.app|Example.exe`
     * - parses a domain list — `example.com,example.org,~example.org` or `example.com|~example.org`
     * - parses a method list — `~post|~put`
     */
    const parseListItems = (raw, options = defaultParserOptions, baseOffset = 0, separator = COMMA, type = ListItemNodeType.Unknown) => {
        // Function body here
        const rawListItems = [];
        let offset = 0;
        // Skip whitespace before the list
        offset = StringUtils.skipWS(raw, offset);
        // If the first character is a separator, then the list is invalid
        // and no need to continue parsing
        if (raw[offset] === separator) {
            throw new AdblockSyntaxError(LIST_PARSE_ERROR_PREFIX.NO_SEPARATOR_AT_THE_BEGINNING, baseOffset + offset, baseOffset + raw.length);
        }
        // If the last character is a separator, then the list item is invalid
        // and no need to continue parsing
        const realEndIndex = StringUtils.skipWSBack(raw);
        if (raw[realEndIndex] === separator) {
            throw new AdblockSyntaxError(LIST_PARSE_ERROR_PREFIX.NO_SEPARATOR_AT_THE_END, baseOffset + realEndIndex, baseOffset + realEndIndex + 1);
        }
        // Split list items by unescaped separators
        while (offset < raw.length) {
            // Skip whitespace before the list item
            offset = StringUtils.skipWS(raw, offset);
            let itemStart = offset;
            // Find the index of the first unescaped separator character
            const separatorStartIndex = StringUtils.findNextUnescapedCharacter(raw, separator, offset);
            const itemEnd = separatorStartIndex === -1
                ? StringUtils.skipWSBack(raw) + 1
                : StringUtils.skipWSBack(raw, separatorStartIndex - 1) + 1;
            const exception = raw[itemStart] === NEGATION_MARKER;
            // Skip the exception marker
            if (exception) {
                itemStart += 1;
                const item = raw[itemStart];
                // Exception marker cannot be followed by another exception marker
                if (item === NEGATION_MARKER) {
                    throw new AdblockSyntaxError(LIST_PARSE_ERROR_PREFIX.NO_MULTIPLE_NEGATION, baseOffset + itemStart, baseOffset + itemStart + 1);
                }
                // Exception marker cannot be followed by a separator
                if (item === separator) {
                    throw new AdblockSyntaxError(LIST_PARSE_ERROR_PREFIX.NO_SEPARATOR_AFTER_NEGATION, baseOffset + itemStart, baseOffset + itemStart + 1);
                }
                // Exception marker cannot be followed by whitespace
                if (StringUtils.isWhitespace(item)) {
                    throw new AdblockSyntaxError(LIST_PARSE_ERROR_PREFIX.NO_WHITESPACE_AFTER_NEGATION, baseOffset + itemStart, baseOffset + itemStart + 1);
                }
            }
            // List item can't be empty
            // Note we use '<=' instead of '===' because we have bidirectional trim
            // This is needed to handle cases like 'example.com, ,example.org'
            if (itemEnd <= itemStart) {
                throw new AdblockSyntaxError(LIST_PARSE_ERROR_PREFIX.EMPTY_ITEM, baseOffset + itemStart, baseOffset + raw.length);
            }
            const listItem = {
                type,
                value: raw.slice(itemStart, itemEnd),
                exception,
            };
            if (options.isLocIncluded) {
                listItem.start = baseOffset + itemStart;
                listItem.end = baseOffset + itemEnd;
            }
            // Collect list item
            rawListItems.push(listItem);
            // Increment the offset to the next list item (or the end of the string)
            offset = separatorStartIndex === -1 ? raw.length : separatorStartIndex + 1;
        }
        return rawListItems;
    };
    /**
     * Generates a string representation of a list item.
     *
     * @param item List item to generate.
     * @template T Type of the list item.
     *
     * @returns String representation of the list item.
     */
    const generateListItem = (item) => {
        return `${item.exception ? NEGATION_MARKER : EMPTY}${item.value}`;
    };
    /**
     * Generates a string representation of a list of items.
     *
     * @param items List of items to generate.
     * @param separator Separator character.
     * @template T Type of the list items.
     *
     * @returns String representation of the list of items.
     */
    const generateListItems = (items, separator) => {
        return items.map(generateListItem).join(separator);
    };
    /**
     * Serializes a list item to binary format.
     *
     * @param item List item to serialize.
     * @param buffer Output byte buffer.
     * @template T Type of the list item.
     */
    const serializeListItem = (item, buffer) => {
        switch (item.type) {
            case ListItemNodeType.App:
                buffer.writeUint8(BinaryTypeMap.AppNode);
                break;
            case ListItemNodeType.Domain:
                buffer.writeUint8(BinaryTypeMap.DomainNode);
                break;
            case ListItemNodeType.Method:
                buffer.writeUint8(BinaryTypeMap.MethodNode);
                break;
            case ListItemNodeType.StealthOption:
                buffer.writeUint8(BinaryTypeMap.StealthOptionNode);
                break;
            default:
                throw new Error(`Invalid list item type: ${item.type}`);
        }
        buffer.writeUint8(ListItemSerializationMap.Exception);
        buffer.writeUint8(item.exception ? 1 : 0);
        buffer.writeUint8(ListItemSerializationMap.Value);
        buffer.writeString(item.value);
        if (!isUndefined$1(item.start)) {
            buffer.writeUint8(ListItemSerializationMap.Start);
            buffer.writeUint32(item.start);
        }
        if (!isUndefined$1(item.end)) {
            buffer.writeUint8(ListItemSerializationMap.End);
            buffer.writeUint32(item.end);
        }
        buffer.writeUint8(NULL);
    };
    /**
     * Deserializes a list item from binary format.
     *
     * @param buffer Input byte buffer.
     * @param node Partial list item to deserialize.
     * @template T Type of the list item.
     */
    const deserializeListItem = (buffer, node) => {
        const type = buffer.readUint8();
        switch (type) {
            case BinaryTypeMap.AppNode:
                node.type = ListItemNodeType.App;
                break;
            case BinaryTypeMap.DomainNode:
                node.type = ListItemNodeType.Domain;
                break;
            case BinaryTypeMap.MethodNode:
                node.type = ListItemNodeType.Method;
                break;
            case BinaryTypeMap.StealthOptionNode:
                node.type = ListItemNodeType.StealthOption;
                break;
            default:
                throw new Error(`Invalid list item type: ${type}`);
        }
        let prop = buffer.readUint8();
        while (prop !== NULL) {
            switch (prop) {
                case ListItemSerializationMap.Exception:
                    node.exception = buffer.readUint8() === 1;
                    break;
                case ListItemSerializationMap.Value:
                    node.value = buffer.readString();
                    break;
                case ListItemSerializationMap.Start:
                    node.start = buffer.readUint32();
                    break;
                case ListItemSerializationMap.End:
                    node.end = buffer.readUint32();
                    break;
                default:
                    throw new Error(`Invalid property: ${type}`);
            }
            prop = buffer.readUint8();
        }
    };
    /**
     * Serializes a list of items to binary format.
     *
     * @param items List of items to serialize.
     * @param buffer Output byte buffer.
     * @template T Type of the list items.
     */
    const serializeListItems = (items, buffer) => {
        const { length } = items;
        buffer.writeUint16(length);
        for (let i = 0; i < length; i += 1) {
            serializeListItem(items[i], buffer);
        }
    };
    /**
     * Deserializes a list of items from binary format.
     *
     * @param buffer Input byte buffer.
     * @param items Partial list of items to deserialize.
     * @template T Type of the list items.
     */
    const deserializeListItems = (buffer, items) => {
        const length = buffer.readUint16();
        items.length = length;
        for (let i = 0; i < length; i += 1) {
            deserializeListItem(buffer, items[i] = {});
        }
    };

    /* eslint-disable no-param-reassign */
    /**
     * Property map for binary serialization. This helps to reduce the size of the serialized data,
     * as it allows us to use a single byte to represent a property.
     *
     * ! IMPORTANT: If you change values here, please update the binary schema version
     *
     * @note Only 256 values can be represented this way.
     */
    var DomainListSerializationMap;
    (function (DomainListSerializationMap) {
        DomainListSerializationMap[DomainListSerializationMap["Separator"] = 1] = "Separator";
        DomainListSerializationMap[DomainListSerializationMap["Children"] = 2] = "Children";
        DomainListSerializationMap[DomainListSerializationMap["Start"] = 3] = "Start";
        DomainListSerializationMap[DomainListSerializationMap["End"] = 4] = "End";
    })(DomainListSerializationMap || (DomainListSerializationMap = {}));
    /**
     * Value map for binary serialization. This helps to reduce the size of the serialized data,
     * as it allows us to use a single byte to represent frequently used values.
     *
     * ! IMPORTANT: If you change values here, please update the {@link BINARY_SCHEMA_VERSION}!
     *
     * @note Only 256 values can be represented this way.
     */
    const SEPARATOR_SERIALIZATION_MAP$1 = new Map([
        [COMMA, 0],
        [PIPE, 1],
    ]);
    /**
     * Value map for binary deserialization. This helps to reduce the size of the serialized data,
     * as it allows us to use a single byte to represent frequently used values.
     */
    const SEPARATOR_DESERIALIZATION_MAP$1 = new Map(Array.from(SEPARATOR_SERIALIZATION_MAP$1).map(([key, value]) => [value, key]));
    /**
     * `DomainListParser` is responsible for parsing a domain list.
     *
     * @example
     * - If the rule is `example.com,~example.net##.ads`, the domain list is `example.com,~example.net`.
     * - If the rule is `ads.js^$script,domains=example.com|~example.org`, the domain list is `example.com|~example.org`.
     * This parser is responsible for parsing these domain lists.
     * @see {@link https://help.eyeo.com/adblockplus/how-to-write-filters#elemhide_domains}
     */
    class DomainListParser extends ParserBase {
        /**
         * Parses a domain list, eg. `example.com,example.org,~example.org`
         *
         * @param raw Raw input to parse.
         * @param options Global parser options.
         * @param baseOffset Starting offset of the input. Node locations are calculated relative to this offset.
         * @param separator Separator character (default: comma)
         *
         * @returns Domain list AST.
         * @throws An {@link AdblockSyntaxError} if the domain list is syntactically invalid.
         * @throws An {@link Error} if the options are invalid.
         */
        static parse(raw, options = defaultParserOptions, baseOffset = 0, separator = COMMA) {
            if (separator !== COMMA && separator !== PIPE) {
                throw new Error(`Invalid separator: ${separator}`);
            }
            const result = {
                type: ListNodeType.DomainList,
                separator,
                children: parseListItems(raw, options, baseOffset, separator, ListItemNodeType.Domain),
            };
            if (options.isLocIncluded) {
                result.start = baseOffset;
                result.end = baseOffset + raw.length;
            }
            return result;
        }
        /**
         * Converts a domain list node to a string.
         *
         * @param node Domain list node.
         *
         * @returns Raw string.
         */
        static generate(node) {
            return generateListItems(node.children, node.separator);
        }
        /**
         * Serializes a domain list node to binary format.
         *
         * @param node Node to serialize.
         * @param buffer ByteBuffer for writing binary data.
         */
        static serialize(node, buffer) {
            buffer.writeUint8(BinaryTypeMap.DomainListNode);
            const separator = SEPARATOR_SERIALIZATION_MAP$1.get(node.separator);
            if (isUndefined$1(separator)) {
                throw new Error(`Invalid separator: ${node.separator}`);
            }
            buffer.writeUint8(DomainListSerializationMap.Separator);
            buffer.writeUint8(separator);
            buffer.writeUint8(DomainListSerializationMap.Children);
            serializeListItems(node.children, buffer);
            if (!isUndefined$1(node.start)) {
                buffer.writeUint8(DomainListSerializationMap.Start);
                buffer.writeUint32(node.start);
            }
            if (!isUndefined$1(node.end)) {
                buffer.writeUint8(DomainListSerializationMap.End);
                buffer.writeUint32(node.end);
            }
            buffer.writeUint8(NULL);
        }
        /**
         * Deserializes a modifier list node from binary format.
         *
         * @param buffer ByteBuffer for reading binary data.
         * @param node Destination node.
         */
        static deserialize(buffer, node) {
            buffer.assertUint8(BinaryTypeMap.DomainListNode);
            node.type = ListNodeType.DomainList;
            let prop = buffer.readUint8();
            while (prop !== NULL) {
                switch (prop) {
                    case DomainListSerializationMap.Separator:
                        // eslint-disable-next-line max-len
                        node.separator = (SEPARATOR_DESERIALIZATION_MAP$1.get(buffer.readUint8()) ?? COMMA);
                        break;
                    case DomainListSerializationMap.Children:
                        deserializeListItems(buffer, node.children = []);
                        break;
                    case DomainListSerializationMap.Start:
                        node.start = buffer.readUint32();
                        break;
                    case DomainListSerializationMap.End:
                        node.end = buffer.readUint32();
                        break;
                    default:
                        throw new Error(`Invalid property: ${prop}.`);
                }
                prop = buffer.readUint8();
            }
        }
    }

    /* eslint-disable no-param-reassign */
    /**
     * Property map for binary serialization. This helps to reduce the size of the serialized data,
     * as it allows us to use a single byte to represent a property.
     *
     * ! IMPORTANT: If you change values here, please update the {@link BINARY_SCHEMA_VERSION}!
     *
     * @note Only 256 values can be represented this way.
     */
    var ModifierNodeSerializationMap;
    (function (ModifierNodeSerializationMap) {
        ModifierNodeSerializationMap[ModifierNodeSerializationMap["Name"] = 1] = "Name";
        ModifierNodeSerializationMap[ModifierNodeSerializationMap["Value"] = 2] = "Value";
        ModifierNodeSerializationMap[ModifierNodeSerializationMap["Exception"] = 3] = "Exception";
        ModifierNodeSerializationMap[ModifierNodeSerializationMap["Start"] = 4] = "Start";
        ModifierNodeSerializationMap[ModifierNodeSerializationMap["End"] = 5] = "End";
    })(ModifierNodeSerializationMap || (ModifierNodeSerializationMap = {}));
    /**
     * Value map for binary serialization. This helps to reduce the size of the serialized data,
     * as it allows us to use a single byte to represent frequently used values.
     *
     * ! IMPORTANT: If you change values here, please update the {@link BINARY_SCHEMA_VERSION}!
     *
     * @note Only 256 values can be represented this way.
     */
    const FREQUENT_MODIFIERS_SERIALIZATION_MAP = new Map([
        ['_', 0],
        ['all', 1],
        ['app', 2],
        ['badfilter', 3],
        ['cname', 4],
        ['content', 5],
        ['cookie', 6],
        ['csp', 7],
        ['denyallow', 8],
        ['document', 9],
        ['doc', 10],
        ['domain', 11],
        ['from', 12],
        ['elemhide', 13],
        ['ehide', 14],
        ['empty', 15],
        ['first-party', 16],
        ['1p', 17],
        ['extension', 18],
        ['font', 19],
        ['genericblock', 20],
        ['generichide', 21],
        ['ghide', 22],
        ['header', 23],
        ['hls', 24],
        ['image', 25],
        ['important', 26],
        ['inline-font', 27],
        ['inline-script', 28],
        ['jsinject', 29],
        ['jsonprune', 30],
        ['match-case', 31],
        ['media', 32],
        ['method', 33],
        ['mp4', 34],
        ['network', 35],
        ['object-subrequest', 36],
        ['object', 37],
        ['other', 38],
        ['permissions', 39],
        ['ping', 40],
        ['popunder', 41],
        ['popup', 42],
        ['redirect-rule', 43],
        ['redirect', 44],
        ['rewrite', 45],
        ['referrerpolicy', 46],
        ['removeheader', 47],
        ['removeparam', 48],
        ['replace', 49],
        ['script', 50],
        ['specifichide', 51],
        ['shide', 52],
        ['stealth', 53],
        ['strict1p', 54],
        ['strict3p', 55],
        ['stylesheet', 56],
        ['css', 57],
        ['subdocument', 58],
        ['frame', 59],
        ['third-party', 60],
        ['3p', 61],
        ['to', 62],
        ['urlblock', 63],
        ['webrtc', 64],
        ['websocket', 65],
        ['xmlhttprequest', 66],
        ['xhr', 67],
        // TODO: add new modifiers here
    ]);
    /**
     * Value map for binary deserialization. This helps to reduce the size of the serialized data,
     * as it allows us to use a single byte to represent frequently used values.
     *
     * @note Only 256 values can be represented this way.
     */
    const FREQUENT_MODIFIERS_DESERIALIZATION_MAP = new Map(Array.from(FREQUENT_MODIFIERS_SERIALIZATION_MAP, ([key, value]) => [value, key]));
    /**
     * Value map for binary serialization. This helps to reduce the size of the serialized data,
     * as it allows us to use a single byte to represent frequently used values.
     *
     * ! IMPORTANT: If you change values here, please update the binary schema version
     *
     * @note Only 256 values can be represented this way.
     */
    const FREQUENT_REDIRECT_VALUES_SERIALIZATION_MAP = new Map([
        // AdGuard
        ['1x1-transparent.gif', 0],
        ['2x2-transparent.png', 1],
        ['3x2-transparent.png', 2],
        ['32x32-transparent.png', 3],
        ['amazon-apstag', 4],
        ['ati-smarttag', 5],
        ['didomi-loader', 6],
        ['click2load.html', 7],
        ['fingerprintjs2', 8],
        ['fingerprintjs3', 9],
        ['google-analytics', 10],
        ['google-analytics-ga', 11],
        ['googlesyndication-adsbygoogle', 12],
        ['googlesyndication-adsbygoogle', 13],
        ['googletagmanager-gtm', 14],
        ['googletagmanager-gtm', 15],
        ['googletagservices-gpt', 16],
        ['google-ima3', 17],
        ['gemius', 18],
        ['matomo', 19],
        ['metrika-yandex-watch', 20],
        ['metrika-yandex-tag', 21],
        ['naver-wcslog', 22],
        ['noeval', 23],
        ['noopcss', 24],
        ['noopframe', 25],
        ['noopjs', 26],
        ['noopjson', 27],
        ['nooptext', 28],
        ['noopmp3-0.1s', 29],
        ['noopmp4-1s', 30],
        ['noopvmap-1.0', 31],
        ['noopvast-2.0', 32],
        ['noopvast-3.0', 33],
        ['noopvast-4.0', 34],
        ['prebid', 35],
        ['pardot-1.0', 36],
        ['prevent-bab', 37],
        ['prevent-bab2', 38],
        ['prevent-fab-3.2.0', 39],
        ['prevent-fab-3.2.0', 40],
        ['prevent-popads-net', 41],
        ['scorecardresearch-beacon', 42],
        ['set-popads-dummy', 43],
        ['empty', 44],
        ['prebid-ads', 45],
        // empty slots for future use
        // uBlock Origin
        ['1x1.gif', 60],
        ['2x2.png', 61],
        ['3x2.png', 62],
        ['32x32.png', 63],
        ['amazon_apstag.js', 64],
        ['click2load.html', 65],
        ['fingerprint2.js', 66],
        ['fingerprint3.js', 67],
        ['google-analytics_analytics.js', 68],
        ['google-analytics_ga.js', 69],
        ['googlesyndication_adsbygoogle.js', 70],
        ['googlesyndication.com/adsbygoogle.js', 71],
        ['google-analytics_ga.js', 72],
        ['googletagmanager_gtm.js', 73],
        ['googletagservices_gpt.js', 74],
        ['google-ima.js', 75],
        ['noeval-silent.js', 76],
        ['noop.css', 77],
        ['noop.html', 78],
        ['noop.js', 79],
        ['noop.json', 80],
        ['noop.txt', 81],
        ['noop-0.1s.mp3', 82],
        ['noop-1s.mp4', 83],
        ['noop-vmap1.0.xml', 84],
        ['nobab.js', 85],
        ['nobab2.js', 86],
        ['nofab.js', 87],
        ['fuckadblock.js-3.2.0', 88],
        ['popads.js', 89],
        ['scorecardresearch_beacon.js', 90],
        ['popads-dummy.js', 91],
        ['empty', 92],
        ['prebid-ads.js', 93],
        // empty slots for future use
        // Adblock Plus
        ['1x1-transparent-gif', 105],
        ['2x2-transparent-png', 106],
        ['3x2-transparent-png', 107],
        ['32x32-transparent-png', 108],
        ['blank-css', 109],
        ['blank-html', 110],
        ['blank-js', 111],
        ['blank-text', 112],
        ['blank-mp3', 113],
        ['blank-mp4', 114],
        // empty slots for future use
        ['abp-resource:1x1-transparent-gif', 120],
        ['abp-resource:2x2-transparent-png', 121],
        ['abp-resource:3x2-transparent-png', 122],
        ['abp-resource:32x32-transparent-png', 123],
        ['abp-resource:blank-css', 124],
        ['abp-resource:blank-html', 125],
        ['abp-resource:blank-js', 126],
        ['abp-resource:blank-text', 127],
        ['abp-resource:blank-mp3', 128],
        ['abp-resource:blank-mp4', 129],
        // TODO: add other common values
    ]);
    /**
     * Value map for binary serialization. This helps to reduce the size of the serialized data,
     * as it allows us to use a single byte to represent frequently used values.
     *
     * @note This is a special map which allows us to use different value maps for different modifiers.
     */
    const FREQUENT_VALUES_SERIALIZATION_MAPS = new Map([
        ['redirect', FREQUENT_REDIRECT_VALUES_SERIALIZATION_MAP],
        ['redirect-rule', FREQUENT_REDIRECT_VALUES_SERIALIZATION_MAP],
        ['rewrite', FREQUENT_REDIRECT_VALUES_SERIALIZATION_MAP],
        // TODO: Add other modifiers here
    ]);
    /**
     * Value map for binary deserialization. This helps to reduce the size of the serialized data,
     * as it allows us to use a single byte to represent frequently used values.
     */
    const FREQUENT_VALUES_DESERIALIZATION_MAPS = new Map(Array.from(FREQUENT_VALUES_SERIALIZATION_MAPS, ([modifier, valueMap]) => [modifier, new Map(Array.from(valueMap, ([key, value]) => [value, key]))]));
    /**
     * `ModifierParser` is responsible for parsing modifiers.
     *
     * @example
     * `match-case`, `~third-party`, `domain=example.com|~example.org`
     */
    class ModifierParser extends ParserBase {
        /**
         * Parses a modifier.
         *
         * @param raw Raw input to parse.
         * @param options Global parser options.
         * @param baseOffset Starting offset of the input. Node locations are calculated relative to this offset.
         *
         * @returns Parsed modifier
         * @throws An error if modifier name or value is empty.
         */
        static parse(raw, options = defaultParserOptions, baseOffset = 0) {
            let offset = 0;
            // Skip leading whitespace
            offset = StringUtils.skipWS(raw, offset);
            // Save the offset of the first character of the modifier (whole modifier)
            const modifierStart = offset;
            // Check if the modifier is an exception
            let exception = false;
            if (raw[offset] === NEGATION_MARKER) {
                offset += NEGATION_MARKER.length;
                exception = true;
            }
            // Skip whitespace after the exception marker (if any)
            offset = StringUtils.skipWS(raw, offset);
            // Save the offset of the first character of the modifier name
            const modifierNameStart = offset;
            // Find assignment operator
            const assignmentIndex = StringUtils.findNextUnescapedCharacter(raw, MODIFIER_ASSIGN_OPERATOR);
            // Find the end of the modifier
            const modifierEnd = Math.max(StringUtils.skipWSBack(raw) + 1, modifierNameStart);
            // Modifier name can't be empty
            if (modifierNameStart === modifierEnd) {
                throw new AdblockSyntaxError('Modifier name cannot be empty', baseOffset, baseOffset + raw.length);
            }
            let modifier;
            let value;
            // If there is no assignment operator, the whole modifier is the name
            // without a value
            if (assignmentIndex === -1) {
                modifier = ValueParser.parse(raw.slice(modifierNameStart, modifierEnd), options, baseOffset + modifierNameStart);
            }
            else {
                // If there is an assignment operator, first we need to find the
                // end of the modifier name, then we can parse the value
                const modifierNameEnd = StringUtils.skipWSBack(raw, assignmentIndex - 1) + 1;
                modifier = ValueParser.parse(raw.slice(modifierNameStart, modifierNameEnd), options, baseOffset + modifierNameStart);
                // Value can't be empty
                if (assignmentIndex + 1 === modifierEnd) {
                    throw new AdblockSyntaxError('Modifier value cannot be empty', baseOffset, baseOffset + raw.length);
                }
                // Skip whitespace after the assignment operator
                const valueStart = StringUtils.skipWS(raw, assignmentIndex + MODIFIER_ASSIGN_OPERATOR.length);
                value = ValueParser.parse(raw.slice(valueStart, modifierEnd), options, baseOffset + valueStart);
            }
            const result = {
                type: 'Modifier',
                name: modifier,
                value,
                exception,
            };
            if (options.isLocIncluded) {
                result.start = baseOffset + modifierStart;
                result.end = baseOffset + modifierEnd;
            }
            return result;
        }
        /**
         * Generates a string from a modifier (serializes it).
         *
         * @param modifier Modifier to generate string from
         * @returns String representation of the modifier
         */
        static generate(modifier) {
            let result = EMPTY;
            if (modifier.exception) {
                result += NEGATION_MARKER;
            }
            result += modifier.name.value;
            if (modifier.value !== undefined) {
                result += MODIFIER_ASSIGN_OPERATOR;
                result += modifier.value.value;
            }
            return result;
        }
        /**
         * Serializes a modifier node to binary format.
         *
         * @param node Node to serialize.
         * @param buffer ByteBuffer for writing binary data.
         */
        static serialize(node, buffer) {
            buffer.writeUint8(BinaryTypeMap.ModifierNode);
            buffer.writeUint8(ModifierNodeSerializationMap.Name);
            ValueParser.serialize(node.name, buffer, FREQUENT_MODIFIERS_SERIALIZATION_MAP);
            if (!isUndefined$1(node.value)) {
                buffer.writeUint8(ModifierNodeSerializationMap.Value);
                ValueParser.serialize(node.value, buffer, FREQUENT_VALUES_SERIALIZATION_MAPS.get(node.name.value));
            }
            buffer.writeUint8(ModifierNodeSerializationMap.Exception);
            buffer.writeUint8(node.exception ? 1 : 0);
            if (!isUndefined$1(node.start)) {
                buffer.writeUint8(ModifierNodeSerializationMap.Start);
                buffer.writeUint32(node.start);
            }
            if (!isUndefined$1(node.end)) {
                buffer.writeUint8(ModifierNodeSerializationMap.End);
                buffer.writeUint32(node.end);
            }
            buffer.writeUint8(NULL);
        }
        /**
         * Deserializes a modifier node from binary format.
         *
         * @param buffer ByteBuffer for reading binary data.
         * @param node Destination node.
         */
        static deserialize(buffer, node) {
            buffer.assertUint8(BinaryTypeMap.ModifierNode);
            node.type = 'Modifier';
            let prop = buffer.readUint8();
            while (prop !== NULL) {
                switch (prop) {
                    case ModifierNodeSerializationMap.Name:
                        ValueParser.deserialize(buffer, node.name = {}, FREQUENT_MODIFIERS_DESERIALIZATION_MAP);
                        break;
                    case ModifierNodeSerializationMap.Value:
                        if (node.name) {
                            // eslint-disable-next-line max-len
                            ValueParser.deserialize(buffer, node.value = {}, FREQUENT_VALUES_DESERIALIZATION_MAPS.get(node.name.value));
                        }
                        else {
                            ValueParser.deserialize(buffer, node.value = {});
                        }
                        break;
                    case ModifierNodeSerializationMap.Exception:
                        node.exception = buffer.readUint8() === 1;
                        break;
                    case ModifierNodeSerializationMap.Start:
                        node.start = buffer.readUint32();
                        break;
                    case ModifierNodeSerializationMap.End:
                        node.end = buffer.readUint32();
                        break;
                    default:
                        throw new Error(`Invalid property: ${prop}.`);
                }
                prop = buffer.readUint8();
            }
        }
    }

    /* eslint-disable no-param-reassign */
    /**
     * Property map for binary serialization. This helps to reduce the size of the serialized data,
     * as it allows us to use a single byte to represent a property.
     *
     * ! IMPORTANT: If you change values here, please update the {@link BINARY_SCHEMA_VERSION}!
     *
     * @note Only 256 values can be represented this way.
     */
    var ModifierListNodeSerializationMap;
    (function (ModifierListNodeSerializationMap) {
        ModifierListNodeSerializationMap[ModifierListNodeSerializationMap["Children"] = 1] = "Children";
        ModifierListNodeSerializationMap[ModifierListNodeSerializationMap["Start"] = 2] = "Start";
        ModifierListNodeSerializationMap[ModifierListNodeSerializationMap["End"] = 3] = "End";
    })(ModifierListNodeSerializationMap || (ModifierListNodeSerializationMap = {}));
    /**
     * `ModifierListParser` is responsible for parsing modifier lists. Please note that the name is not
     * uniform, "modifiers" are also known as "options".
     *
     * @see {@link https://kb.adguard.com/en/general/how-to-create-your-own-ad-filters#basic-rules-modifiers}
     * @see {@link https://kb.adguard.com/en/general/how-to-create-your-own-ad-filters#non-basic-rules-modifiers}
     * @see {@link https://help.eyeo.com/adblockplus/how-to-write-filters#options}
     */
    class ModifierListParser extends ParserBase {
        /**
         * Parses the cosmetic rule modifiers, eg. `third-party,domain=example.com|~example.org`.
         *
         * _Note:_ you should remove `$` separator before passing the raw modifiers to this function,
         *  or it will be parsed in the first modifier.
         *
         * @param raw Raw input to parse.
         * @param options Global parser options.
         * @param baseOffset Starting offset of the input. Node locations are calculated relative to this offset.
         * @returns Parsed modifiers interface
         */
        static parse(raw, options = defaultParserOptions, baseOffset = 0) {
            const result = {
                type: 'ModifierList',
                children: [],
            };
            if (options.isLocIncluded) {
                result.start = baseOffset;
                result.end = baseOffset + raw.length;
            }
            let offset = StringUtils.skipWS(raw);
            let separatorIndex = -1;
            // Split modifiers by unescaped commas
            while (offset < raw.length) {
                // Skip whitespace before the modifier
                offset = StringUtils.skipWS(raw, offset);
                const modifierStart = offset;
                // Find the index of the first unescaped comma
                separatorIndex = StringUtils.findNextUnescapedCharacter(raw, MODIFIERS_SEPARATOR, offset);
                const modifierEnd = separatorIndex === -1
                    ? raw.length
                    : StringUtils.skipWSBack(raw, separatorIndex - 1) + 1;
                // Parse the modifier
                const modifier = ModifierParser.parse(raw.slice(modifierStart, modifierEnd), options, baseOffset + modifierStart);
                result.children.push(modifier);
                // Increment the offset to the next modifier (or the end of the string)
                offset = separatorIndex === -1 ? raw.length : separatorIndex + 1;
            }
            // Check if there are any modifiers after the last separator
            if (separatorIndex !== -1) {
                const modifierStart = StringUtils.skipWS(raw, separatorIndex + 1);
                result.children.push(ModifierParser.parse(raw.slice(modifierStart, raw.length), options, baseOffset + modifierStart));
            }
            return result;
        }
        /**
         * Converts a modifier list AST to a string.
         *
         * @param ast Modifier list AST
         * @returns Raw string
         */
        static generate(ast) {
            const result = ast.children
                .map(ModifierParser.generate)
                .join(MODIFIERS_SEPARATOR);
            return result;
        }
        /**
         * Serializes a modifier list node to binary format.
         *
         * @param node Node to serialize.
         * @param buffer ByteBuffer for writing binary data.
         */
        static serialize(node, buffer) {
            buffer.writeUint8(BinaryTypeMap.ModifierListNode);
            const count = node.children.length;
            if (count) {
                buffer.writeUint8(ModifierListNodeSerializationMap.Children);
                // note: we store the count, because re-construction of the array is faster if we know the length
                if (count > UINT16_MAX) {
                    throw new Error(`Too many modifiers: ${count}, the limit is ${UINT16_MAX}`);
                }
                buffer.writeUint16(count);
                for (let i = 0; i < count; i += 1) {
                    ModifierParser.serialize(node.children[i], buffer);
                }
            }
            if (!isUndefined$1(node.start)) {
                buffer.writeUint8(ModifierListNodeSerializationMap.Start);
                buffer.writeUint32(node.start);
            }
            if (!isUndefined$1(node.end)) {
                buffer.writeUint8(ModifierListNodeSerializationMap.End);
                buffer.writeUint32(node.end);
            }
            buffer.writeUint8(NULL);
        }
        /**
         * Deserializes a modifier list node from binary format.
         *
         * @param buffer ByteBuffer for reading binary data.
         * @param node Destination node.
         */
        static deserialize(buffer, node) {
            buffer.assertUint8(BinaryTypeMap.ModifierListNode);
            node.type = 'ModifierList';
            let prop = buffer.readUint8();
            while (prop !== NULL) {
                switch (prop) {
                    case ModifierListNodeSerializationMap.Children:
                        node.children = new Array(buffer.readUint16());
                        // read children
                        for (let i = 0; i < node.children.length; i += 1) {
                            ModifierParser.deserialize(buffer, node.children[i] = {});
                        }
                        break;
                    case ModifierListNodeSerializationMap.Start:
                        node.start = buffer.readUint32();
                        break;
                    case ModifierListNodeSerializationMap.End:
                        node.end = buffer.readUint32();
                        break;
                    default:
                        throw new Error(`Invalid property: ${prop}.`);
                }
                prop = buffer.readUint8();
            }
        }
    }

    /**
     * @file Error messages for CSS token stream and balancer.
     */
    const END_OF_INPUT = 'end of input';
    const ERROR_MESSAGES$6 = {
        EXPECTED_ANY_TOKEN_BUT_GOT: "Expected a token, but got '%s'",
        EXPECTED_TOKEN_BUT_GOT: "Expected '%s', but got '%s'",
        EXPECTED_TOKEN_WITH_BALANCE_BUT_GOT: "Expected '%s' with balance '%d', but got '%d'",
        EXPECTED_TOKEN_WITH_VALUE_BUT_GOT: "Expected '%s' with value '%s', but got '%s'",
    };

    /**
     * @file Tokenizer helpers for balanced pairs.
     */
    /**
     * Map of opening tokens to their corresponding closing tokens.
     */
    const standardTokenPairs = new Map([
        [TokenType$1.Function, TokenType$1.CloseParenthesis],
        [TokenType$1.OpenParenthesis, TokenType$1.CloseParenthesis],
        [TokenType$1.OpenSquareBracket, TokenType$1.CloseSquareBracket],
        [TokenType$1.OpenCurlyBracket, TokenType$1.CloseCurlyBracket],
    ]);
    /**
     * Map of opening tokens to their corresponding closing tokens just for function calls. This makes possible a more
     * lightweight and tolerant check for balanced pairs in some cases.
     */
    const functionTokenPairs = new Map([
        [TokenType$1.Function, TokenType$1.CloseParenthesis],
        [TokenType$1.OpenParenthesis, TokenType$1.CloseParenthesis],
    ]);
    /**
     * Helper function to tokenize and ensure balanced pairs.
     *
     * @param raw Raw CSS string to tokenize
     * @param onToken Callback which will be invoked for each token, extended with a `balance` parameter
     * @param onError Error callback which is called when a parsing error is found (optional)
     * @param functionHandlers Custom function handlers (optional)
     * @param tokenPairs Map of opening tokens to their corresponding closing tokens
     * @throws If the input is not balanced
     * @todo Consider adding a `tolerant` flag if error throwing seems too aggressive in the future
     */
    const tokenizeWithBalancedPairs = (raw, onToken, onError = () => { }, functionHandlers, tokenPairs = standardTokenPairs) => {
        const stack = [];
        const values = new Set(tokenPairs.values());
        tokenizeExtended(raw, (type, start, end, props) => {
            if (tokenPairs.has(type)) {
                // If the token is an opening token, push its corresponding closing token to the stack.
                // It is safe to use non-null assertion here, because we have checked that the token exists in the map.
                // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
                stack.push(tokenPairs.get(type));
            }
            else if (values.has(type)) {
                // If the token is a closing token, check if it matches the last opening token, and if so, pop it.
                if (stack[stack.length - 1] === type) {
                    stack.pop();
                }
                else {
                    throw new AdblockSyntaxError(sprintf.sprintf(ERROR_MESSAGES$6.EXPECTED_TOKEN_BUT_GOT, getFormattedTokenName(stack[stack.length - 1]), getFormattedTokenName(type)), start, raw.length);
                }
            }
            onToken(type, start, end, props, stack.length);
        }, onError, functionHandlers);
        // If the stack is not empty, then there are some opening tokens that were not closed.
        if (stack.length > 0) {
            throw new AdblockSyntaxError(sprintf.sprintf(ERROR_MESSAGES$6.EXPECTED_TOKEN_BUT_GOT, getFormattedTokenName(stack[stack.length - 1]), END_OF_INPUT), raw.length - 1, raw.length);
        }
    };
    /**
     * Tokenize and ensure balanced pairs for standard CSS.
     *
     * @param raw Raw CSS string to tokenize
     * @param onToken Callback which will be invoked for each token, extended with a `balance` parameter
     * @param onError Error callback which is called when a parsing error is found (optional)
     * @param functionHandlers Custom function handlers (optional)
     * @throws If the input is not balanced
     */
    const tokenizeBalanced = (raw, onToken, onError = () => { }, functionHandlers) => {
        tokenizeWithBalancedPairs(raw, onToken, onError, functionHandlers);
    };
    /**
     * Tokenize and ensure balanced pairs for function calls.
     *
     * @param raw Raw CSS string to tokenize
     * @param onToken Callback which will be invoked for each token, extended with a `balance` parameter
     * @param onError Error callback which is called when a parsing error is found (optional)
     * @param functionHandlers Custom function handlers (optional)
     * @throws If the input is not balanced
     */
    const tokenizeFnBalanced = (raw, onToken, onError = () => { }, functionHandlers) => {
        tokenizeWithBalancedPairs(raw, onToken, onError, functionHandlers, functionTokenPairs);
    };

    /**
     * @file Parser for special uBO selectors.
     */
    /**
     * Possible error messages for uBO selectors. Formatted with {@link sprintf}.
     */
    const ERROR_MESSAGES$5 = {
        DUPLICATED_UBO_MODIFIER: "uBO modifier '%s' cannot be used more than once",
        EXPECTED_BUT_GOT_BEFORE: "Expected '%s' but got '%s' before '%s'",
        // eslint-disable-next-line max-len
        NEGATED_UBO_MODIFIER_CANNOT_BE_FOLLOWED_BY: "Negated uBO modifier '%s' cannot be followed by anything else than a closing parenthesis or a whitespace",
        NEGATED_UBO_MODIFIER_CANNOT_BE_PRECEDED_BY: "Negated uBO modifier '%s' cannot be preceded by '%s'",
        PSEUDO_CANNOT_BE_NESTED: "uBO modifier '%s' cannot be nested inside '%s', only '%s' is allowed as a wrapper",
        UBO_MODIFIER_CANNOT_BE_NESTED: "uBO modifier '%s' cannot be nested",
        UBO_STYLE_CANNOT_BE_FOLLOWED: 'uBO style injection cannot be followed by anything else than a whitespace',
    };
    /**
     * Dummy parameter for uBO modifiers in error messages.
     */
    const DUMMY_PARAM = '...';
    /**
     * Known uBO modifiers.
     */
    var UboPseudoName;
    (function (UboPseudoName) {
        UboPseudoName["MatchesMedia"] = "matches-media";
        UboPseudoName["MatchesPath"] = "matches-path";
        UboPseudoName["Remove"] = "remove";
        UboPseudoName["Style"] = "style";
    })(UboPseudoName || (UboPseudoName = {}));
    /**
     * Set of known uBO modifiers.
     *
     * @note We use `string` instead of `UboPseudoName` because we use this set for checking if a modifier is a known uBO,
     * and an unknown sequence is just a string.
     */
    const KNOWN_UBO_MODIFIERS = new Set([
        UboPseudoName.MatchesMedia,
        UboPseudoName.MatchesPath,
        UboPseudoName.Remove,
        UboPseudoName.Style,
    ]);
    /**
     * Helper function to check if the given selector has any uBO modifier. This function should be fast, because it's used
     * in the hot path of the parser.
     *
     * @param raw Raw selector string.
     * @returns `true` if the selector has any uBO modifier, `false` otherwise.
     */
    const hasAnyUboModifier = (raw) => {
        // Find the first colon
        let colonIndex = raw.indexOf(COLON);
        while (colonIndex !== -1) {
            // Find next opening parenthesis
            const openingParenthesisIndex = raw.indexOf(OPEN_PARENTHESIS, colonIndex + 1);
            // If there is no opening parenthesis, then the selector doesn't contain any uBO modifier
            if (openingParenthesisIndex === -1) {
                return false;
            }
            // Check if the modifier is a known uBO modifier
            if (KNOWN_UBO_MODIFIERS.has(raw.slice(colonIndex + 1, openingParenthesisIndex))) {
                return true;
            }
            // Find next colon
            colonIndex = raw.indexOf(COLON, openingParenthesisIndex + 1);
        }
        return false;
    };
    /**
     * A simple helper function to format a pseudo name for error messages.
     *
     * @param name Pseudo name.
     * @param wrapper Wrapper pseudo name (eg. `not`) (optional, defaults to `undefined`).
     * @returns Formatted pseudo name.
     * @example
     * ```ts
     * formatPseudoName('matches-path', 'not'); // => ':not(:matches-path(...))'
     * formatPseudoName('matches-media'); // => ':matches-media(...)'
     * ```
     */
    const formatPseudoName = (name, wrapper) => {
        const result = [];
        if (wrapper) {
            result.push(COLON, wrapper, OPEN_PARENTHESIS);
        }
        result.push(COLON, name, OPEN_PARENTHESIS, DUMMY_PARAM, CLOSE_PARENTHESIS);
        if (wrapper) {
            result.push(CLOSE_PARENTHESIS);
        }
        return result.join(EMPTY);
    };
    /**
     * Parser for uBO selectors.
     */
    class UboSelectorParser extends ParserBase {
        /**
         * Parses a uBO selector list, eg. `div:matches-path(/path)`.
         *
         * @param raw Raw input to parse.
         * @param options Global parser options.
         * @param baseOffset Starting offset of the input. Node locations are calculated relative to this offset.
         *
         * @returns Parsed uBO selector {@link UboSelector}.
         * @throws An {@link AdblockSyntaxError} if the selector list is syntactically invalid.
         */
        static parse(raw, options = defaultParserOptions, baseOffset = 0) {
            // Prepare helper variables
            const modifiers = {
                type: 'ModifierList',
                children: [],
            };
            if (options.isLocIncluded) {
                modifiers.start = baseOffset;
                modifiers.end = baseOffset + raw.length;
            }
            // Do not perform any parsing if the selector doesn't contain any uBO modifier
            // Parsing is a relatively expensive operation, but this check is cheap, so we can avoid unnecessary work
            // TODO: Move this check to the cosmetic parser (adjustable syntaxes - if uBO syntax is disabled, then we don't
            // need to check for uBO modifiers)
            if (!hasAnyUboModifier(raw)) {
                const selector = {
                    type: 'Value',
                    value: raw,
                };
                if (options.isLocIncluded) {
                    selector.start = baseOffset;
                    selector.end = baseOffset + raw.length;
                }
                const result = {
                    type: 'UboSelector',
                    selector,
                    modifiers,
                };
                if (options.isLocIncluded) {
                    result.start = baseOffset;
                    result.end = baseOffset + raw.length;
                }
                return result;
            }
            // Simple way to check if a modifier is already processed to avoid duplicate modifiers
            const processedModifiers = new Set();
            // We need to keep track of the tokens for handling negations properly
            const tokens = [];
            // This array is used to mark the character slots in the selector string that are occupied by uBO modifiers
            const uboIndexes = new Array(raw.length);
            const uboModifierStack = [];
            let i = 0;
            // Helper function to stack a uBO modifier
            const stackModifier = (modifier) => {
                if (processedModifiers.has(modifier.name)) {
                    throw new AdblockSyntaxError(sprintf.sprintf(ERROR_MESSAGES$5.DUPLICATED_UBO_MODIFIER, formatPseudoName(modifier.name)), baseOffset + modifier.modifierStart, baseOffset + raw.length);
                }
                uboModifierStack.push(modifier);
            };
            // Tokenize the selector, calculate the balance
            tokenizeFnBalanced(raw, (type, start, end, _, balance) => {
                // Special case: style injection (`:style(...)` and `:remove()`) can only be used at the end of the
                // selector, like
                //  - `div:style(...)`,
                //  - `div:matches-media(...):style(...)`,
                //  - `div:remove()`,
                // etc.
                //
                // But not like
                //  - `:style(...) div`,
                //  - `:matches-media(...):style(...) div`,
                //  - `:remove() div`,
                // etc.
                //
                // The one exception is whitespace, which is allowed after style injection, like
                //  - `div:style(...) `,
                //  - `div:matches-media(...):style(...) `,
                //  - `div:remove() `,
                // etc.
                if ((processedModifiers.has(UboPseudoName.Style)
                    || processedModifiers.has(UboPseudoName.Remove))
                    && type !== TokenType$1.Whitespace) {
                    throw new AdblockSyntaxError(ERROR_MESSAGES$5.UBO_STYLE_CANNOT_BE_FOLLOWED, baseOffset + start, baseOffset + raw.length);
                }
                // Check for pseudo classes (colon followed by a function)
                if (tokens[i - 1]?.type === TokenType$1.Colon && type === TokenType$1.Function) {
                    // Since closing parenthesis is always included in the function token, but we only need the function
                    // name, we need to cut off the last character, this is why we use `end - 1` here
                    const fn = raw.slice(start, end - 1);
                    // Check if the pseudo class is a known uBO modifier
                    if (KNOWN_UBO_MODIFIERS.has(fn)) {
                        // Generally, uBO modifiers cannot be nested, like
                        //  - `:any(:matches-media(...))`,
                        //  - `:matches-media(:matches-media(...))`,
                        //  - `:not(style(...))`,
                        //  etc.
                        if (balance > 1) {
                            // However, we have one exception: `:matches-path()` can be nested inside `:not()`s, like:
                            //  - `:not(:matches-path(...))`,
                            //  - `:not(:not(:matches-path(...)))`,
                            //  etc.
                            //
                            // But it can't be nested inside any other pseudo class, like:
                            //  - `:anything(:matches-path(...))`,
                            //  etc.
                            //
                            // Moreover, :not() can't contain any other data, like
                            //  - `:not(div:matches-path(...))`,
                            //  - `:not(:matches-path(...):matches-path(...))`,
                            //  - `:not(:matches-path(...) div)`,
                            // etc.
                            if (fn === UboPseudoName.MatchesPath) {
                                if (uboModifierStack.length > 0) {
                                    throw new AdblockSyntaxError(sprintf.sprintf(ERROR_MESSAGES$5.PSEUDO_CANNOT_BE_NESTED, formatPseudoName(UboPseudoName.MatchesPath), formatPseudoName(uboModifierStack[uboModifierStack.length - 1].name), formatPseudoName(CSS_NOT_PSEUDO)), baseOffset + start - 1, baseOffset + raw.length);
                                }
                                let isException = false;
                                let modifierBalance = balance;
                                let modifierStart = start;
                                for (let j = i - 1; j >= 0; j -= 1) {
                                    // If we have reached the root level, then we should check if the `not` function is
                                    // preceded by a colon (which means that it's a pseudo class)
                                    if (tokens[j].balance === 0) {
                                        modifierStart = tokens[j].start;
                                        modifierBalance = tokens[j].balance;
                                        break;
                                    }
                                    else if (tokens[j].type === TokenType$1.Colon
                                        || tokens[j].type === TokenType$1.Whitespace) {
                                        continue;
                                    }
                                    else if (tokens[j].type === TokenType$1.Function) {
                                        const wrapperFnName = raw.slice(tokens[j].start, tokens[j].end - 1);
                                        if (wrapperFnName !== CSS_NOT_PSEUDO) {
                                            throw new AdblockSyntaxError(sprintf.sprintf(ERROR_MESSAGES$5.PSEUDO_CANNOT_BE_NESTED, formatPseudoName(UboPseudoName.MatchesPath), formatPseudoName(wrapperFnName), formatPseudoName(CSS_NOT_PSEUDO)), baseOffset + tokens[j].start - 1, baseOffset + raw.length);
                                        }
                                        if (tokens[j - 1]?.type !== TokenType$1.Colon) {
                                            const got = tokens[j - 1]?.type
                                                ? getFormattedTokenName(tokens[j - 1]?.type)
                                                : 'nothing';
                                            throw new AdblockSyntaxError(sprintf.sprintf(ERROR_MESSAGES$5.EXPECTED_BUT_GOT_BEFORE, getFormattedTokenName(TokenType$1.Colon), got, formatPseudoName(UboPseudoName.MatchesPath, CSS_NOT_PSEUDO)), 
                                            // eslint-disable-next-line no-unsafe-optional-chaining
                                            baseOffset + tokens[j - 1]?.start || 0, baseOffset + raw.length);
                                        }
                                        isException = !isException;
                                        continue;
                                    }
                                    else {
                                        throw new AdblockSyntaxError(sprintf.sprintf(ERROR_MESSAGES$5.NEGATED_UBO_MODIFIER_CANNOT_BE_PRECEDED_BY, formatPseudoName(UboPseudoName.MatchesPath), getFormattedTokenName(tokens[j].type)), baseOffset + tokens[j].start, baseOffset + raw.length);
                                    }
                                }
                                stackModifier({
                                    name: fn,
                                    modifierStart,
                                    modifierBalance,
                                    nameStart: start,
                                    nameEnd: end - 1, // ignore opening parenthesis
                                    valueStart: end,
                                    valueBalance: balance,
                                    isException,
                                });
                            }
                            else {
                                throw new AdblockSyntaxError(sprintf.sprintf(ERROR_MESSAGES$5.UBO_MODIFIER_CANNOT_BE_NESTED, formatPseudoName(fn)), baseOffset + start - 1, baseOffset + raw.length);
                            }
                        }
                        else {
                            stackModifier({
                                name: fn,
                                modifierStart: start - 1, // Include the colon
                                modifierBalance: balance,
                                nameStart: start,
                                nameEnd: end - 1, // ignore opening parenthesis
                                valueStart: end,
                                valueBalance: balance,
                                isException: false,
                            });
                        }
                    }
                }
                else {
                    // Get the last stacked modifier
                    const lastStackedModifier = uboModifierStack[uboModifierStack.length - 1];
                    // Do not allow any other token after `:matches-path(...)` inside `:not(...)`
                    if (lastStackedModifier?.name === UboPseudoName.MatchesPath && lastStackedModifier?.isException) {
                        if (!(type === TokenType$1.CloseParenthesis || type === TokenType$1.Whitespace)
                            && balance < lastStackedModifier.valueBalance) {
                            throw new AdblockSyntaxError(sprintf.sprintf(ERROR_MESSAGES$5.NEGATED_UBO_MODIFIER_CANNOT_BE_FOLLOWED_BY, formatPseudoName(UboPseudoName.MatchesPath), getFormattedTokenName(type)), baseOffset + start, baseOffset + raw.length);
                        }
                    }
                    // If we have reached a closing parenthesis, then we should check if it closes the last stacked modifier
                    // and if so, pop it from the stack
                    if (type === TokenType$1.CloseParenthesis && lastStackedModifier) {
                        if (balance === Math.max(0, lastStackedModifier.valueBalance - 1)) {
                            lastStackedModifier.valueEnd = start;
                        }
                        if (balance === Math.max(0, lastStackedModifier.modifierBalance - 1)) {
                            const modifierName = {
                                type: 'Value',
                                value: lastStackedModifier.name,
                            };
                            if (options.isLocIncluded) {
                                // TODO: Refactor
                                modifierName.start = baseOffset + lastStackedModifier.nameStart;
                                modifierName.end = baseOffset + lastStackedModifier.nameEnd;
                            }
                            const value = {
                                type: 'Value',
                                value: raw.slice(lastStackedModifier.valueStart, lastStackedModifier.valueEnd),
                            };
                            if (options.isLocIncluded) {
                                value.start = baseOffset + lastStackedModifier.valueStart;
                                // It's safe to use `!` here, because we determined the value end index in the
                                // previous `if` statement
                                // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
                                value.end = baseOffset + lastStackedModifier.valueEnd;
                            }
                            const modifier = {
                                type: 'Modifier',
                                name: modifierName,
                                value,
                                exception: lastStackedModifier.isException,
                            };
                            if (options.isLocIncluded) {
                                modifier.start = baseOffset + lastStackedModifier.modifierStart;
                                modifier.end = baseOffset + end;
                            }
                            modifiers.children.push(modifier);
                            processedModifiers.add(lastStackedModifier.name);
                            uboModifierStack.pop();
                            // Mark the character slots in the selector string that are occupied by uBO modifiers
                            uboIndexes.fill(true, lastStackedModifier.modifierStart, end);
                        }
                    }
                }
                // Save the token to the history and increase the index
                tokens.push({
                    type,
                    start,
                    end,
                    balance,
                });
                i += 1;
            });
            const selector = {
                type: 'Value',
                value: raw
                    .split(EMPTY)
                    .map((char, p) => (uboIndexes[p] ? EMPTY : char))
                    .join(EMPTY)
                    .trim(),
            };
            if (options.isLocIncluded) {
                selector.start = baseOffset;
                selector.end = baseOffset + raw.length;
            }
            const result = {
                type: 'UboSelector',
                selector,
                modifiers,
            };
            if (options.isLocIncluded) {
                result.start = baseOffset;
                result.end = baseOffset + raw.length;
            }
            return result;
        }
        /**
         * Serializes a uBO selector node to a string.
         *
         * @param node UBO selector node
         * @returns Raw string
         */
        static generate(node) {
            const prefix = []; // List of leading modifiers
            const suffix = []; // List of trailing modifiers, typically style injection
            if (node.modifiers) {
                for (const modifier of node.modifiers.children) {
                    switch (modifier.name.value) {
                        case UboPseudoName.Remove:
                        case UboPseudoName.Style:
                            // eslint-disable-next-line max-len
                            suffix.push(COLON, modifier.name.value, OPEN_PARENTHESIS, modifier.value?.value || EMPTY, CLOSE_PARENTHESIS);
                            break;
                        default:
                            // Wrap exceptions in `:not()`
                            if (modifier.exception) {
                                prefix.push(COLON, CSS_NOT_PSEUDO, OPEN_PARENTHESIS);
                            }
                            // :modifier-name(value)
                            // eslint-disable-next-line max-len
                            prefix.push(COLON, modifier.name.value, OPEN_PARENTHESIS, modifier.value?.value || EMPTY, CLOSE_PARENTHESIS);
                            // Close the `:not()` if we are in an exception
                            if (modifier.exception) {
                                prefix.push(CLOSE_PARENTHESIS);
                            }
                            break;
                    }
                }
            }
            // Prepare the result
            let result = EMPTY;
            if (prefix.length > 0) {
                result += prefix.join(EMPTY);
                // Add a space between the selector and the leading modifier(s)
                if (node.selector?.value) {
                    result += SPACE;
                }
            }
            result += node.selector?.value || EMPTY;
            result += suffix.join(EMPTY);
            return result;
        }
    }

    /**
     * @file Known CSS elements and attributes.
     * TODO: Implement a compatibility table for Extended CSS
     */
    /**
     * Legacy Extended CSS attribute prefix.
     *
     * @example
     * ```css
     * [-ext-<name>=...]
     * ```
     */
    const LEGACY_EXT_CSS_ATTRIBUTE_PREFIX = '-ext-';
    /**
     * ABP Extended CSS prefix.
     *
     * @example
     * ```css
     * [-abp-<name>=...]
     * -abp-<name>(...)
     * ```
     */
    const ABP_EXT_CSS_PREFIX = '-abp';
    /**
     * Known _strict_ Extended CSS pseudo-classes. Please, keep this list sorted.
     * Strict means that these pseudo-classes are not supported by any browser natively,
     * and they always require Extended CSS libraries to work.
     */
    const EXT_CSS_PSEUDO_CLASSES_STRICT = new Set([
        // AdGuard
        // https://github.com/AdguardTeam/ExtendedCss
        'contains',
        'if-not',
        'matches-attr',
        'matches-css',
        'matches-property',
        'nth-ancestor',
        'remove',
        'upward',
        'xpath',
        // uBlock Origin
        // https://github.com/gorhill/uBlock/wiki/Static-filter-syntax#procedural-cosmetic-filters
        'has-text',
        'matches-css-after',
        'matches-css-before',
        'matches-path',
        'min-text-length',
        'watch-attr',
        // Adblock Plus
        // https://help.eyeo.com/adblockplus/how-to-write-filters#elemhide-emulation
        '-abp-contains',
        '-abp-has',
        '-abp-properties',
    ]);
    /**
     * _ALL_ known Extended CSS pseudo-classes. Please, keep this list sorted.
     * It includes strict pseudo-classes and additional pseudo-classes that may be
     * supported by some browsers natively.
     */
    const EXT_CSS_PSEUDO_CLASSES = new Set([
        ...EXT_CSS_PSEUDO_CLASSES_STRICT,
        /**
         * https://developer.mozilla.org/en-US/docs/Web/CSS/:has
         */
        'has',
        /**
         * https://developer.mozilla.org/en-US/docs/Web/CSS/:is
         */
        'is',
    ]);

    /**
     * @file CSS token stream.
     */
    /**
     * Represents a stream of CSS tokens.
     */
    class CssTokenStream {
        /**
         * The tokens in the stream.
         */
        tokens = [];
        /**
         * The source string.
         */
        source = EMPTY;
        /**
         * The current index in the stream.
         */
        index = 0;
        /**
         * The base offset of the source string.
         */
        baseOffset;
        /**
         * Initializes a new instance of the TokenStream class.
         *
         * @param source The source string to tokenize.
         * @param baseOffset The base offset of the source string.
         */
        constructor(source, baseOffset = 0) {
            this.source = source;
            // Tokenize the source string with the CSS tokenizer and add balance level to each token.
            // 'onToken' callback is invoked when a token is found in the source string.
            // Passed parameters:
            // - type: type of the token
            // - start: start index of the token
            // - end: end index of the token
            // - props: additional properties of the token, if any (we don't use it here, this is why we use underscore)
            // - balance: balance level of the token
            tokenizeBalanced(source, (type, start, end, _, balance) => {
                this.tokens.push({
                    type,
                    start,
                    end,
                    balance,
                });
            });
            this.index = 0;
            this.baseOffset = baseOffset;
        }
        /**
         * Gets the number of tokens in the stream.
         *
         * @returns The number of tokens in the stream.
         */
        get length() {
            return this.tokens.length;
        }
        /**
         * Checks if the end of the token stream is reached.
         *
         * @returns True if the end of the stream is reached, otherwise false.
         */
        isEof() {
            return this.index >= this.tokens.length;
        }
        /**
         * Gets the token at the specified index.
         *
         * @param index The index of the token to retrieve.
         * @returns The token at the specified index or undefined if the index is out of bounds.
         */
        get(index = this.index) {
            return this.tokens[index];
        }
        /**
         * Gets the token at the specified index or throws if no token is found at the specified index.
         *
         * @param index The index of the token to retrieve.
         * @returns The token at the specified index or undefined if the index is out of bounds.
         * @throws If no token is found at the specified index.
         */
        getOrFail(index = this.index) {
            const token = this.get(index);
            if (!token) {
                throw new AdblockSyntaxError(sprintf.sprintf(ERROR_MESSAGES$6.EXPECTED_ANY_TOKEN_BUT_GOT, END_OF_INPUT), this.baseOffset + this.source.length - 1, this.baseOffset + this.source.length);
            }
            return token;
        }
        /**
         * Gets the source fragment of the token at the specified index.
         *
         * @param index The index of the token to retrieve the fragment for.
         * @returns The source fragment of the token or an empty string if the index is out of bounds.
         */
        fragment(index = this.index) {
            const token = this.get(index);
            if (token) {
                return this.source.slice(token.start, token.end);
            }
            return EMPTY;
        }
        /**
         * Moves the index to the next token and returns it.
         *
         * @returns The next token or undefined if the end of the stream is reached.
         */
        advance() {
            if (this.isEof()) {
                return undefined;
            }
            this.index += 1;
            return this.tokens[this.index];
        }
        /**
         * Looks ahead in the stream without changing the index.
         *
         * @param index The relative index to look ahead to, starting from the current index.
         * @returns The next token or undefined if the end of the stream is reached.
         */
        lookahead(index = 1) {
            return this.tokens[this.index + Math.max(1, index)];
        }
        /**
         * Looks behind in the stream without changing the index.
         *
         * @param index The relative index to look behind to, starting from the current index.
         * @returns The previous token or undefined if the current token is the first in the stream.
         */
        lookbehind(index = 1) {
            if (this.index === 0) {
                return undefined;
            }
            return this.tokens[this.index - Math.max(1, index)];
        }
        /**
         * Looks behind in the stream for the previous non-whitespace token without changing the index.
         *
         * @returns The previous non-whitespace token or undefined if it could not be found.
         */
        lookbehindForNonWs() {
            for (let i = this.index - 1; i >= 0; i -= 1) {
                if (this.tokens[i].type !== TokenType$1.Whitespace) {
                    return this.tokens[i];
                }
            }
            return undefined;
        }
        /**
         * Skips whitespace tokens in the stream.
         */
        skipWhitespace() {
            while (this.get()?.type === TokenType$1.Whitespace) {
                this.index += 1;
            }
        }
        /**
         * Skips tokens until the current balance level is reached.
         *
         * @returns The number of tokens skipped.
         */
        skipUntilBalanced() {
            if (this.isEof()) {
                return 0;
            }
            // It is safe to use ! here, because we check for EOF above
            // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
            const currentBalance = this.get().balance;
            // If the current balance is 0, do nothing
            if (currentBalance === 0) {
                return 0;
            }
            // Otherwise, skip tokens until the balance is the current balance - 1
            let skipped = 0;
            while (!this.isEof() && this.get()?.balance !== currentBalance - 1) {
                this.index += 1;
                skipped += 1;
            }
            return skipped;
        }
        /**
         * Skips tokens until a token with the specified type or the end of the stream is reached.
         *
         * @param type The type of token to skip until.
         * @param balance The balance level of the token to skip until.
         * @returns The number of tokens skipped.
         */
        skipUntil(type, balance) {
            let skipped = 0;
            while (!this.isEof()
                && (this.get()?.type !== type || (balance !== undefined && this.get()?.balance !== balance))) {
                this.index += 1;
                skipped += 1;
            }
            return skipped;
        }
        /**
         * Skips tokens until a token with the specified type or the end of the stream is reached. This is an extended
         * version of skipUntil that also returns the number of tokens skipped without calculating leading and trailing
         * whitespace tokens.
         *
         * @param type The type of token to skip until.
         * @param balance The balance level of the token to skip until.
         * @returns An array containing the number of tokens skipped and the number of tokens skipped without leading and
         * trailing whitespace tokens.
         */
        skipUntilExt(type, balance) {
            let i = this.index;
            let firstNonWsToken = -1; // -1 means no non-whitespace token found yet
            let lastNonWsToken = -1; // -1 means no non-whitespace token found yet
            while (i < this.tokens.length) {
                const currentToken = this.tokens[i];
                if (currentToken.type === TokenType$1.Whitespace) {
                    i += 1;
                    continue;
                }
                else if (currentToken.type === type && currentToken.balance === balance) {
                    break;
                }
                if (firstNonWsToken === -1) {
                    firstNonWsToken = i;
                }
                lastNonWsToken = i;
                i += 1;
            }
            const skipped = i - this.index;
            this.index = i;
            return {
                skipped,
                // if firstNonWsToken is -1, then lastNonWsToken is also -1
                skippedTrimmed: firstNonWsToken === -1 ? 0 : lastNonWsToken - firstNonWsToken + 1,
            };
        }
        /**
         * Expects that the end of the stream is not reached.
         */
        expectNotEof() {
            if (this.isEof()) {
                throw new AdblockSyntaxError('Unexpected end of input', this.baseOffset + this.source.length - 1, this.baseOffset + this.source.length);
            }
        }
        /**
         * Expects the current token to have a specific type and optional value and balance level.
         *
         * @param type The expected token type.
         * @param data Optional expectation data.
         * @throws If the end of the stream is reached or if the token type or expectation data does not match.
         */
        expect(type, data) {
            const token = this.get();
            if (!token) {
                throw new AdblockSyntaxError(sprintf.sprintf(ERROR_MESSAGES$6.EXPECTED_TOKEN_BUT_GOT, getFormattedTokenName(type), END_OF_INPUT), this.baseOffset + this.source.length - 1, this.baseOffset + this.source.length);
            }
            if (token.type !== type) {
                throw new AdblockSyntaxError(sprintf.sprintf(ERROR_MESSAGES$6.EXPECTED_TOKEN_BUT_GOT, getFormattedTokenName(type), getFormattedTokenName(token.type)), this.baseOffset + token.start, this.baseOffset + token.end);
            }
            if (data?.balance !== undefined && token.balance !== data.balance) {
                throw new AdblockSyntaxError(sprintf.sprintf(ERROR_MESSAGES$6.EXPECTED_TOKEN_WITH_BALANCE_BUT_GOT, getFormattedTokenName(type), data.balance, token.balance), this.baseOffset + token.start, this.baseOffset + token.end);
            }
            if (data?.value && this.fragment() !== data.value) {
                throw new AdblockSyntaxError(sprintf.sprintf(ERROR_MESSAGES$6.EXPECTED_TOKEN_WITH_VALUE_BUT_GOT, getFormattedTokenName(type), data.value, this.fragment()), this.baseOffset + token.start, this.baseOffset + token.end);
            }
        }
        /**
         * Gets the balance level of the token at the specified index.
         *
         * @param index The index of the token to retrieve the balance level for.
         * @returns The balance level of the token or 0 if the index is out of bounds.
         */
        getBalance(index = this.index) {
            return this.tokens[index]?.balance || 0;
        }
        /**
         * Checks whether the token stream contains any Extended CSS elements, such as `:contains()`, etc.
         *
         * @returns `true` if the stream contains any Extended CSS elements, otherwise `false`.
         */
        hasAnySelectorExtendedCssNode() {
            return this.hasAnySelectorExtendedCssNodeInternal(EXT_CSS_PSEUDO_CLASSES);
        }
        /**
         * Strictly checks whether the token stream contains any Extended CSS elements, such as `:contains()`.
         * Some Extended CSS elements are natively supported by browsers, like `:has()`.
         * This method is used to check for Extended CSS elements that are not natively supported by browsers,
         * this is why it called "strict", because it strictly checks for Extended CSS elements.
         *
         * @returns `true` if the stream contains any Extended CSS elements, otherwise `false`.
         */
        hasAnySelectorExtendedCssNodeStrict() {
            return this.hasAnySelectorExtendedCssNodeInternal(EXT_CSS_PSEUDO_CLASSES_STRICT);
        }
        /**
         * Checks whether the token stream contains any Extended CSS elements, such as `:has()`, `:contains()`, etc.
         *
         * @param pseudos Set of pseudo-classes to check for.
         *
         * @returns `true` if the stream contains any Extended CSS elements, otherwise `false`.
         */
        hasAnySelectorExtendedCssNodeInternal(pseudos) {
            for (let i = 0; i < this.tokens.length; i += 1) {
                const token = this.tokens[i];
                if (token.type === TokenType$1.Function) {
                    const name = this.source.slice(token.start, token.end - 1); // omit the last parenthesis
                    if (pseudos.has(name)) {
                        return true;
                    }
                }
                else if (token.type === TokenType$1.OpenSquareBracket) {
                    let j = i + 1;
                    // skip whitespace
                    while (j < this.tokens.length && this.tokens[j].type === TokenType$1.Whitespace) {
                        j += 1;
                    }
                    if (j < this.tokens.length && this.tokens[j].type === TokenType$1.Ident) {
                        const attr = this.source.slice(this.tokens[j].start, this.tokens[j].end);
                        // [-ext-<name>=...] or [-abp-<name>=...]
                        if (attr.startsWith(LEGACY_EXT_CSS_ATTRIBUTE_PREFIX) || attr.startsWith(ABP_EXT_CSS_PREFIX)) {
                            return true;
                        }
                    }
                    // do not check these tokens again
                    i = j;
                }
            }
            return false;
        }
    }

    /**
     * @file Parser for AdGuard CSS injections.
     */
    const REMOVE_PROPERTY = 'remove';
    const REMOVE_VALUE = 'true';
    const removeDeclaration = `${REMOVE_PROPERTY}${COLON}${SPACE}${REMOVE_VALUE}${SEMICOLON}`;
    const ERROR_MESSAGES$4 = {
        MEDIA_QUERY_LIST_IS_EMPTY: 'Media query list is empty',
        SELECTOR_LIST_IS_EMPTY: 'Selector list is empty',
        DECLARATION_LIST_IS_EMPTY: 'Declaration list is empty',
    };
    /**
     * Parser for AdGuard CSS injection.
     */
    class AdgCssInjectionParser extends ParserBase {
        /**
         * Parses an AdGuard CSS injection.
         *
         * @param raw Raw input to parse.
         * @param options Global parser options.
         * @param baseOffset Starting offset of the input. Node locations are calculated relative to this offset.
         *
         * @returns Parsed AdGuard CSS injection {@link CssInjectionRuleBody}.
         * @throws An {@link AdblockSyntaxError} if the selector list is syntactically invalid.
         */
        static parse(raw, options = defaultParserOptions, baseOffset = 0) {
            let mediaQueryList;
            const selectorList = { type: 'Value', value: EMPTY };
            const declarationList = { type: 'Value', value: EMPTY };
            const stream = new CssTokenStream(raw, baseOffset);
            // Skip leading whitespace characters
            stream.skipWhitespace();
            // We have two possible CSS injection formats:
            // 1. @media (media-query-list) { selector list { declarations separated by semicolons } }
            // 2. selector list { declarations separated by semicolons }
            // Handle '@media' case:
            let balanceShift = 0;
            if (stream.getOrFail().type === TokenType$1.AtKeyword) {
                // Currently only '@media' is supported, we should throw an error if we encounter anything else,
                // like '@supports' or '@charset', etc.
                stream.expect(TokenType$1.AtKeyword, { value: CSS_MEDIA_MARKER, balance: 0 });
                stream.advance();
                // Skip whitespace characters after @media keyword, if any
                // @media (media-query-list) { ...
                //       ↑
                //       └ this one (if any)
                stream.skipWhitespace();
                const mediaQueryListStart = stream.getOrFail().start;
                // Skip everything until we found the opening curly bracket of the declaration block
                // @media media-query-list { ...
                //                         ↑
                //                         └ this one
                let lastNonWsIndex = -1;
                while (!stream.isEof()) {
                    const token = stream.getOrFail();
                    if (token.type === TokenType$1.OpenCurlyBracket && token.balance === 1) {
                        break;
                    }
                    if (token.type !== TokenType$1.Whitespace) {
                        lastNonWsIndex = token.end;
                    }
                    stream.advance();
                }
                // If the skipped tokens count is 0 without leading and trailing whitespace characters, then the media query
                // list is empty
                if (lastNonWsIndex === -1) {
                    throw new AdblockSyntaxError(ERROR_MESSAGES$4.MEDIA_QUERY_LIST_IS_EMPTY, baseOffset + mediaQueryListStart, baseOffset + raw.length);
                }
                // It is safe to use non-null assertion here, because we have already checked previous tokens.
                // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
                const mediaQueryListEnd = lastNonWsIndex;
                mediaQueryList = {
                    type: 'Value',
                    value: raw.slice(mediaQueryListStart, mediaQueryListEnd),
                };
                if (options.isLocIncluded) {
                    mediaQueryList.start = baseOffset + mediaQueryListStart;
                    mediaQueryList.end = baseOffset + mediaQueryListEnd;
                }
                // Next token should be an open curly bracket
                // @media (media-query-list) { ...
                //                           ↑
                //                           └ this one
                stream.expect(TokenType$1.OpenCurlyBracket);
                stream.advance();
                // '@media' at-rule wrap increases the balance level by 1 for the rule within the at-rule, because it
                // has its own { ... } block
                balanceShift = 1;
            }
            // Skip leading whitespace before the rule, if any
            // Note: rule = selector list { declarations separated by semicolons }
            stream.skipWhitespace();
            const selectorStart = stream.getOrFail().start;
            // Jump to the opening curly bracket of the declaration block, based on the balance level
            // .selector { padding-top: 10px; padding-bottom: 10px; }
            //           ↑
            //           └ this one
            const { skippedTrimmed: selectorTokensLength } = stream.skipUntilExt(TokenType$1.OpenCurlyBracket, balanceShift + 1);
            stream.expect(TokenType$1.OpenCurlyBracket);
            // If the skipped tokens count is 0 without leading and trailing whitespace characters, then the selector list
            // is empty
            if (selectorTokensLength === 0) {
                throw new AdblockSyntaxError(ERROR_MESSAGES$4.SELECTOR_LIST_IS_EMPTY, baseOffset + selectorStart, baseOffset + raw.length);
            }
            // It is safe to use non-null assertion here, because we have already checked previous tokens.
            // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
            const selectorEnd = stream.lookbehindForNonWs().end;
            selectorList.value = raw.slice(selectorStart, selectorEnd);
            if (options.isLocIncluded) {
                selectorList.start = baseOffset + selectorStart;
                selectorList.end = baseOffset + selectorEnd;
            }
            // Jump to the next token after the opening curly bracket of the declaration block
            // .selector { padding-top: 10px; padding-bottom: 10px; }
            //            ↑
            //            └ this one
            stream.advance();
            // Skip whitespace characters after the opening curly bracket of the declaration block, if any
            stream.skipWhitespace();
            // Jump to the closing curly bracket of the declaration block, based on the balance level
            // .selector { padding-top: 10px; padding-bottom: 10px; }
            //                                                      ↑
            //                                                      └ this one
            const declarationsStart = stream.getOrFail().start;
            const declarations = new Set();
            let declarationsEnd = -1;
            let remove = false;
            let lastNonWsIndex = -1;
            while (!stream.isEof()) {
                const token = stream.getOrFail();
                if (token.type === TokenType$1.CloseCurlyBracket && stream.getBalance() === balanceShift) {
                    declarationsEnd = lastNonWsIndex;
                    break;
                }
                if (token.type !== TokenType$1.Whitespace) {
                    lastNonWsIndex = token.end;
                }
                if (token.type === TokenType$1.Ident && stream.lookahead()?.type === TokenType$1.Colon) {
                    const ident = raw.slice(token.start, token.end);
                    declarations.add(ident);
                    // Consume ident and colon
                    stream.advance();
                    stream.advance();
                    // only 'remove: true' is allowed
                    if (ident === REMOVE_PROPERTY) {
                        // Skip whitespace after colon, if any
                        stream.skipWhitespace();
                        // Next token should be an ident, with value 'true'
                        stream.expect(TokenType$1.Ident, { value: REMOVE_VALUE });
                        stream.advance();
                        remove = true;
                    }
                }
                else {
                    stream.advance();
                }
            }
            if (declarationsEnd === -1) {
                throw new AdblockSyntaxError(ERROR_MESSAGES$4.DECLARATION_LIST_IS_EMPTY, baseOffset + declarationsStart, baseOffset + raw.length);
            }
            declarationList.value = raw.slice(declarationsStart, declarationsEnd);
            if (options.isLocIncluded) {
                declarationList.start = baseOffset + declarationsStart;
                declarationList.end = baseOffset + declarationsEnd;
            }
            // Eat the close curly bracket of the declaration block
            // .selector { padding-top: 10px; padding-bottom: 10px; }
            //                                                      ↑
            //                                                      └ this one
            stream.expect(TokenType$1.CloseCurlyBracket);
            stream.advance();
            // Skip whitespace after the rule, if any
            stream.skipWhitespace();
            // If we have a media query, we should have an extra close curly bracket
            if (balanceShift === 1) {
                stream.expect(TokenType$1.CloseCurlyBracket);
                stream.advance();
            }
            const result = {
                type: 'CssInjectionRuleBody',
                selectorList,
                declarationList,
                remove,
            };
            if (options.isLocIncluded) {
                result.start = baseOffset;
                result.end = baseOffset + raw.length;
            }
            if (mediaQueryList) {
                result.mediaQueryList = mediaQueryList;
            }
            return result;
        }
        /**
         * Serializes an AdGuard CSS injection node into a raw string.
         *
         * @param node Node to serialize.
         * @returns Raw string.
         */
        static generate(node) {
            const result = [];
            if (node.mediaQueryList) {
                result.push(CSS_MEDIA_MARKER, SPACE, node.mediaQueryList.value, SPACE, OPEN_CURLY_BRACKET, SPACE);
            }
            result.push(node.selectorList.value, SPACE, OPEN_CURLY_BRACKET, SPACE);
            if (node.remove) {
                result.push(removeDeclaration);
            }
            else if (node.declarationList?.value) {
                result.push(node.declarationList.value);
            }
            result.push(SPACE, CLOSE_CURLY_BRACKET);
            if (node.mediaQueryList) {
                result.push(SPACE, CLOSE_CURLY_BRACKET);
            }
            return result.join(EMPTY);
        }
    }

    /* eslint-disable no-param-reassign */
    /**
     * @file Helpers for serializing scriptlet injection body nodes to binary format.
     * We keep the core logic here, because it can be reused for each scriptlet body parser.
     */
    /**
     * Property map for binary serialization. This helps to reduce the size of the serialized data,
     * as it allows us to use a single byte to represent a property.
     *
     * ! IMPORTANT: If you change values here, please update the {@link BINARY_SCHEMA_VERSION}!
     *
     * @note Only 256 values can be represented this way.
     */
    var AbpSnippetBodySerializationMap;
    (function (AbpSnippetBodySerializationMap) {
        AbpSnippetBodySerializationMap[AbpSnippetBodySerializationMap["Children"] = 1] = "Children";
        AbpSnippetBodySerializationMap[AbpSnippetBodySerializationMap["Start"] = 2] = "Start";
        AbpSnippetBodySerializationMap[AbpSnippetBodySerializationMap["End"] = 3] = "End";
    })(AbpSnippetBodySerializationMap || (AbpSnippetBodySerializationMap = {}));
    /**
     * Serializes a hint rule node to binary format.
     *
     * @param node Node to serialize.
     * @param buffer ByteBuffer for writing binary data.
     * @param frequentScriptletArgs Map of frequently used scriptlet names / arguments
     * and their serialization index (optional).
     */
    const serializeScriptletBody = (node, buffer, frequentScriptletArgs) => {
        buffer.writeUint8(BinaryTypeMap.ScriptletInjectionRuleBodyNode);
        const { length } = node.children;
        buffer.writeUint8(AbpSnippetBodySerializationMap.Children);
        // note: we store the count, because re-construction of the array is faster if we know the length
        if (length > UINT8_MAX) {
            throw new Error(`Too many scriptlet children: ${length}, the limit is ${UINT8_MAX}`);
        }
        buffer.writeUint8(length);
        for (let i = 0; i < length; i += 1) {
            ParameterListParser.serialize(node.children[i], buffer, frequentScriptletArgs);
        }
        if (!isUndefined$1(node.start)) {
            buffer.writeUint8(AbpSnippetBodySerializationMap.Start);
            buffer.writeUint32(node.start);
        }
        if (!isUndefined$1(node.end)) {
            buffer.writeUint8(AbpSnippetBodySerializationMap.End);
            buffer.writeUint32(node.end);
        }
        buffer.writeUint8(NULL);
    };
    /**
     * Deserializes a hint rule node from binary format.
     *
     * @param buffer ByteBuffer for reading binary data.
     * @param node Destination node.
     * @param frequentScriptletArgs Map of frequently used scriptlet names / arguments
     * and their serialization index (optional).
     * @throws If the binary data is malformed.
     */
    const deserializeScriptletBody = (buffer, node, frequentScriptletArgs) => {
        buffer.assertUint8(BinaryTypeMap.ScriptletInjectionRuleBodyNode);
        node.type = 'ScriptletInjectionRuleBody';
        let prop = buffer.readUint8();
        while (prop !== NULL) {
            switch (prop) {
                case AbpSnippetBodySerializationMap.Children:
                    node.children = new Array(buffer.readUint8());
                    // read children
                    for (let i = 0; i < node.children.length; i += 1) {
                        // eslint-disable-next-line max-len
                        ParameterListParser.deserialize(buffer, node.children[i] = {}, frequentScriptletArgs);
                    }
                    break;
                case AbpSnippetBodySerializationMap.Start:
                    node.start = buffer.readUint32();
                    break;
                case AbpSnippetBodySerializationMap.End:
                    node.end = buffer.readUint32();
                    break;
                default:
                    throw new Error(`Invalid property: ${prop}`);
            }
            prop = buffer.readUint8();
        }
    };

    /**
     * @file uBlock scriptlet injection body parser
     */
    /**
     * `AbpSnippetInjectionBodyParser` is responsible for parsing the body of an Adblock Plus-style snippet rule.
     *
     * Please note that the parser will parse any scriptlet rule if it is syntactically correct.
     * For example, it will parse this:
     * ```adblock
     * example.com#$#snippet0 arg0
     * ```
     *
     * but it didn't check if the scriptlet `snippet0` actually supported by any adblocker.
     *
     * @see {@link https://help.eyeo.com/adblockplus/snippet-filters-tutorial}
     */
    class AbpSnippetInjectionBodyParser extends ParserBase {
        /**
         * Error messages used by the parser.
         */
        static ERROR_MESSAGES = {
            EMPTY_SCRIPTLET_CALL: 'Empty ABP snippet call',
        };
        /**
         * Value map for binary serialization. This helps to reduce the size of the serialized data,
         * as it allows us to use a single byte to represent frequently used values.
         *
         * ! IMPORTANT: If you change values here, please update the {@link BINARY_SCHEMA_VERSION}!
         *
         * @note Only 256 values can be represented this way.
         */
        // TODO: Update this map with the actual values
        static FREQUENT_ARGS_SERIALIZATION_MAP = new Map([
            ['abort-current-inline-script', 0],
            ['abort-on-property-read', 1],
            ['abort-on-property-write', 2],
            ['json-prune', 3],
            ['log', 4],
            ['prevent-listener', 5],
            ['cookie-remover', 6],
            ['override-property-read', 7],
            ['abort-on-iframe-property-read', 8],
            ['abort-on-iframe-property-write', 9],
            ['freeze-element', 10],
            ['json-override', 11],
            ['simulate-mouse-event', 12],
            ['strip-fetch-query-parameter', 13],
            ['hide-if-contains', 14],
            ['hide-if-contains-image', 15],
            ['hide-if-contains-image-hash', 16],
            ['hide-if-contains-similar-text', 17],
            ['hide-if-contains-visible-text', 18],
            ['hide-if-contains-and-matches-style', 19],
            ['hide-if-graph-matches', 20],
            ['hide-if-has-and-matches-style', 21],
            ['hide-if-labelled-by', 22],
            ['hide-if-matches-xpath', 23],
            ['hide-if-matches-computed-xpath', 24],
            ['hide-if-shadow-contains', 25],
            ['debug', 26],
            ['trace', 27],
            ['race', 28],
        ]);
        /**
         * Value map for binary deserialization. This helps to reduce the size of the serialized data,
         * as it allows us to use a single byte to represent frequently used values.
         */
        static FREQUENT_ARGS_DESERIALIZATION_MAP = new Map(Array.from(this.FREQUENT_ARGS_SERIALIZATION_MAP).map(([key, value]) => [value, key]));
        /**
         * Parses the body of an Adblock Plus-style snippet rule.
         *
         * @param raw Raw input to parse.
         * @param options Global parser options.
         * @param baseOffset Starting offset of the input. Node locations are calculated relative to this offset.
         * @returns Node of the parsed scriptlet call body
         * @throws If the body is syntactically incorrect
         * @example
         * ```
         * #$#snippet0 arg0
         * ```
         */
        static parse(raw, options = defaultParserOptions, baseOffset = 0) {
            const result = {
                type: 'ScriptletInjectionRuleBody',
                children: [],
            };
            if (options.isLocIncluded) {
                result.start = baseOffset;
                result.end = baseOffset + raw.length;
            }
            let offset = 0;
            // Skip leading spaces
            offset = StringUtils.skipWS(raw, offset);
            while (offset < raw.length) {
                offset = StringUtils.skipWS(raw, offset);
                const scriptletCallStart = offset;
                // Find the next semicolon or the end of the string
                let semicolonIndex = StringUtils.findUnescapedNonStringNonRegexChar(raw, SEMICOLON, offset);
                if (semicolonIndex === -1) {
                    semicolonIndex = raw.length;
                }
                const scriptletCallEnd = Math.max(StringUtils.skipWSBack(raw, semicolonIndex - 1) + 1, scriptletCallStart);
                const params = ParameterListParser.parse(raw.slice(scriptletCallStart, scriptletCallEnd), options, baseOffset + scriptletCallStart, SPACE);
                // Parse the scriptlet call
                result.children.push(params);
                // Skip the semicolon
                offset = semicolonIndex + 1;
            }
            if (result.children.length === 0) {
                throw new AdblockSyntaxError(this.ERROR_MESSAGES.EMPTY_SCRIPTLET_CALL, baseOffset, baseOffset + raw.length);
            }
            return result;
        }
        /**
         * Generates a string representation of the Adblock Plus-style snippet call body.
         *
         * @param node Scriptlet injection rule body
         * @returns String representation of the rule body
         */
        static generate(node) {
            const result = [];
            if (node.children.length === 0) {
                throw new Error(this.ERROR_MESSAGES.EMPTY_SCRIPTLET_CALL);
            }
            for (const scriptletCall of node.children) {
                if (scriptletCall.children.length === 0) {
                    throw new Error(this.ERROR_MESSAGES.EMPTY_SCRIPTLET_CALL);
                }
                result.push(ParameterListParser.generate(scriptletCall, SPACE));
            }
            return result.join(SEMICOLON + SPACE);
        }
        /**
         * Serializes a scriptlet call body node to binary format.
         *
         * @param node Node to serialize.
         * @param buffer ByteBuffer for writing binary data.
         */
        static serialize(node, buffer) {
            serializeScriptletBody(node, buffer, this.FREQUENT_ARGS_SERIALIZATION_MAP);
        }
        /**
         * Deserializes a scriptlet call body node from binary format.
         *
         * @param buffer ByteBuffer for reading binary data.
         * @param node Destination node.
         * @throws If the binary data is malformed.
         */
        static deserialize(buffer, node) {
            deserializeScriptletBody(buffer, node, this.FREQUENT_ARGS_DESERIALIZATION_MAP);
        }
    }

    /**
     * @file Utility functions for working with quotes
     */
    /**
     * Set of all possible quote characters supported by the library
     */
    const QUOTE_SET = new Set([
        SINGLE_QUOTE,
        DOUBLE_QUOTE,
        BACKTICK_QUOTE,
    ]);
    /**
     * Possible quote types for scriptlet parameters
     */
    var QuoteType;
    (function (QuoteType) {
        /**
         * No quotes at all
         */
        QuoteType["None"] = "none";
        /**
         * Single quotes (`'`)
         */
        QuoteType["Single"] = "single";
        /**
         * Double quotes (`"`)
         */
        QuoteType["Double"] = "double";
        /**
         * Backtick quotes (`` ` ``)
         */
        QuoteType["Backtick"] = "backtick";
    })(QuoteType || (QuoteType = {}));
    /**
     * Utility functions for working with quotes
     */
    class QuoteUtils {
        /**
         * Escape all unescaped occurrences of the character
         *
         * @param string String to escape
         * @param char Character to escape
         * @returns Escaped string
         */
        static escapeUnescapedOccurrences(string, char) {
            let result = EMPTY;
            for (let i = 0; i < string.length; i += 1) {
                if (string[i] === char && (i === 0 || string[i - 1] !== ESCAPE_CHARACTER)) {
                    result += ESCAPE_CHARACTER;
                }
                result += string[i];
            }
            return result;
        }
        /**
         * Unescape all single escaped occurrences of the character
         *
         * @param string String to unescape
         * @param char Character to unescape
         * @returns Unescaped string
         */
        static unescapeSingleEscapedOccurrences(string, char) {
            let result = EMPTY;
            for (let i = 0; i < string.length; i += 1) {
                if (string[i] === char
                    && string[i - 1] === ESCAPE_CHARACTER
                    && (i === 1 || string[i - 2] !== ESCAPE_CHARACTER)) {
                    result = result.slice(0, -1);
                }
                result += string[i];
            }
            return result;
        }
        /**
         * Get quote type of the string
         *
         * @param string String to check
         * @returns Quote type of the string
         */
        static getStringQuoteType(string) {
            // Don't check 1-character strings to avoid false positives
            if (string.length > 1) {
                if (string.startsWith(SINGLE_QUOTE) && string.endsWith(SINGLE_QUOTE)) {
                    return QuoteType.Single;
                }
                if (string.startsWith(DOUBLE_QUOTE) && string.endsWith(DOUBLE_QUOTE)) {
                    return QuoteType.Double;
                }
                if (string.startsWith(BACKTICK_QUOTE) && string.endsWith(BACKTICK_QUOTE)) {
                    return QuoteType.Backtick;
                }
            }
            return QuoteType.None;
        }
        /**
         * Set quote type of the string
         *
         * @param string String to set quote type of
         * @param quoteType Quote type to set
         * @returns String with the specified quote type
         */
        static setStringQuoteType(string, quoteType) {
            const actualQuoteType = QuoteUtils.getStringQuoteType(string);
            switch (quoteType) {
                case QuoteType.None:
                    if (actualQuoteType === QuoteType.Single) {
                        return QuoteUtils.escapeUnescapedOccurrences(string.slice(1, -1), SINGLE_QUOTE);
                    }
                    if (actualQuoteType === QuoteType.Double) {
                        return QuoteUtils.escapeUnescapedOccurrences(string.slice(1, -1), DOUBLE_QUOTE);
                    }
                    if (actualQuoteType === QuoteType.Backtick) {
                        return QuoteUtils.escapeUnescapedOccurrences(string.slice(1, -1), BACKTICK_QUOTE);
                    }
                    return string;
                case QuoteType.Single:
                    if (actualQuoteType === QuoteType.None) {
                        return SINGLE_QUOTE + QuoteUtils.escapeUnescapedOccurrences(string, SINGLE_QUOTE) + SINGLE_QUOTE;
                    }
                    if (actualQuoteType === QuoteType.Double) {
                        return SINGLE_QUOTE
                            + QuoteUtils.escapeUnescapedOccurrences(QuoteUtils.unescapeSingleEscapedOccurrences(string.slice(1, -1), DOUBLE_QUOTE), SINGLE_QUOTE) + SINGLE_QUOTE;
                    }
                    if (actualQuoteType === QuoteType.Backtick) {
                        return SINGLE_QUOTE
                            + QuoteUtils.escapeUnescapedOccurrences(QuoteUtils.unescapeSingleEscapedOccurrences(string.slice(1, -1), BACKTICK_QUOTE), SINGLE_QUOTE) + SINGLE_QUOTE;
                    }
                    return string;
                case QuoteType.Double:
                    if (actualQuoteType === QuoteType.None) {
                        return DOUBLE_QUOTE + QuoteUtils.escapeUnescapedOccurrences(string, DOUBLE_QUOTE) + DOUBLE_QUOTE;
                    }
                    if (actualQuoteType !== QuoteType.Double) {
                        // eslint-disable-next-line max-len
                        return DOUBLE_QUOTE
                            + QuoteUtils.escapeUnescapedOccurrences(QuoteUtils.unescapeSingleEscapedOccurrences(string.slice(1, -1), SINGLE_QUOTE), DOUBLE_QUOTE) + DOUBLE_QUOTE;
                    }
                    return string;
                case QuoteType.Backtick:
                    if (actualQuoteType === QuoteType.None) {
                        // eslint-disable-next-line max-len
                        return BACKTICK_QUOTE + QuoteUtils.escapeUnescapedOccurrences(string, BACKTICK_QUOTE) + BACKTICK_QUOTE;
                    }
                    if (actualQuoteType !== QuoteType.Backtick) {
                        // eslint-disable-next-line max-len
                        return BACKTICK_QUOTE
                            + QuoteUtils.escapeUnescapedOccurrences(QuoteUtils.unescapeSingleEscapedOccurrences(string.slice(1, -1), SINGLE_QUOTE), BACKTICK_QUOTE) + BACKTICK_QUOTE;
                    }
                    return string;
                default:
                    return string;
            }
        }
        /**
         * Removes bounding quotes from a string, if any
         *
         * @param string Input string
         * @returns String without quotes
         */
        static removeQuotes(string) {
            if (
            // We should check for string length to avoid false positives
            string.length > 1
                && (string[0] === SINGLE_QUOTE || string[0] === DOUBLE_QUOTE || string[0] === BACKTICK_QUOTE)
                && string[0] === string[string.length - 1]) {
                return string.slice(1, -1);
            }
            return string;
        }
        /**
         * Removes bounding quotes from a string, if any, and unescapes the escaped quotes,
         * like transforming `'abc\'def'` to `abc'def`.
         *
         * @param string Input string
         * @returns String without quotes
         */
        static removeQuotesAndUnescape(string) {
            if (
            // We should check for string length to avoid false positives
            string.length > 1
                && (string[0] === SINGLE_QUOTE || string[0] === DOUBLE_QUOTE || string[0] === BACKTICK_QUOTE)
                && string[0] === string[string.length - 1]) {
                return QuoteUtils.unescapeSingleEscapedOccurrences(string.slice(1, -1), string[0]);
            }
            return string;
        }
        /**
         * Wraps given `strings` with `quote` (defaults to single quote `'`)
         * and joins them with `separator` (defaults to comma+space `, `).
         *
         * @param strings Strings to quote and join.
         * @param quoteType Quote to use.
         * @param separator Separator to use.
         *
         * @returns String with joined items.
         *
         * @example
         * ['abc', 'def']: strings[]  ->  "'abc', 'def'": string
         */
        static quoteAndJoinStrings(strings, quoteType = QuoteType.Single, separator = `${COMMA}${SPACE}`) {
            return strings
                .map((s) => QuoteUtils.setStringQuoteType(s, quoteType))
                .join(separator);
        }
    }

    /* eslint-disable no-param-reassign */
    class UboParameterListParser extends ParameterListParser {
        /**
         * Parses an "uBO-specific parameter list".
         *
         * @param raw Raw input to parse.
         * @param options Global parser options.
         * @param baseOffset Starting offset of the input. Node locations are calculated relative to this offset.
         * @param separator Separator character (default: comma).
         * @param requireQuotes Whether to require quotes around the parameter values (default: false).
         * @param supportedQuotes Set of accepted quotes (default: {@link QUOTE_SET}).
         * @returns Parameter list node.
         *
         * @note Based on {@link https://github.com/gorhill/uBlock/blob/f9ab4b75041815e6e5690d80851189ae3dc660d0/src/js/static-filtering-parser.js#L607-L699} to provide consistency.
         */
        static parse(raw, options = defaultParserOptions, baseOffset = 0, separator = COMMA, requireQuotes = false, supportedQuotes = QUOTE_SET) {
            // Prepare the parameter list node
            const params = {
                type: 'ParameterList',
                children: [],
            };
            const { length } = raw;
            if (options.isLocIncluded) {
                params.start = baseOffset;
                params.end = baseOffset + length;
            }
            let offset = 0;
            // TODO: Eliminate the need for extraNull
            let extraNull = false;
            while (offset < length) {
                offset = StringUtils.skipWS(raw, offset);
                const paramStart = offset;
                let paramEnd = offset;
                if (supportedQuotes.has(raw[offset])) {
                    // Find the closing quote
                    const possibleClosingQuoteIndex = StringUtils.findNextUnescapedCharacter(raw, raw[offset], offset + 1);
                    if (possibleClosingQuoteIndex !== -1) {
                        // Next non-whitespace character after the closing quote should be the separator
                        const nextSeparatorIndex = StringUtils.skipWS(raw, possibleClosingQuoteIndex + 1);
                        if (nextSeparatorIndex === length) {
                            if (requireQuotes) {
                                throw new AdblockSyntaxError('Expected separator, got end of string', baseOffset + nextSeparatorIndex, baseOffset + length);
                            }
                            // If the separator is not found, the param end is the end of the string
                            paramEnd = StringUtils.skipWSBack(raw, length - 1) + 1;
                            offset = length;
                        }
                        else if (raw[nextSeparatorIndex] === separator) {
                            // If the quote is followed by a separator, we can use it as a closing quote
                            paramEnd = possibleClosingQuoteIndex + 1;
                            offset = nextSeparatorIndex + 1;
                        }
                        else {
                            if (requireQuotes) {
                                throw new AdblockSyntaxError(`Expected separator, got: '${raw[nextSeparatorIndex]}'`, baseOffset + nextSeparatorIndex, baseOffset + length);
                            }
                            // Param end should be the last separator before the quote
                            offset = StringUtils.findNextUnescapedCharacterBackwards(raw, separator, possibleClosingQuoteIndex) + 1;
                            paramEnd = StringUtils.skipWSBack(raw, offset - 2) + 1;
                        }
                    }
                    else {
                        if (requireQuotes) {
                            throw new AdblockSyntaxError('Expected closing quote, got end of string', baseOffset + offset, baseOffset + length);
                        }
                        // If the closing quote is not found, the param end is the end of the string
                        paramEnd = StringUtils.skipWSBack(raw, length - 1) + 1;
                        offset = length;
                    }
                }
                else {
                    if (requireQuotes) {
                        throw new AdblockSyntaxError(`Expected quote, got: '${raw[offset]}'`, baseOffset + offset, baseOffset + length);
                    }
                    const nextSeparator = StringUtils.findNextUnescapedCharacter(raw, separator, offset);
                    if (nextSeparator === -1) {
                        // If the separator is not found, the param end is the end of the string
                        paramEnd = StringUtils.skipWSBack(raw, length - 1) + 1;
                        offset = length;
                    }
                    else {
                        // Param end should be the last non-whitespace character before the separator
                        paramEnd = StringUtils.skipWSBack(raw, nextSeparator - 1) + 1;
                        offset = nextSeparator + 1;
                        if (StringUtils.skipWS(raw, length - 1) === nextSeparator) {
                            extraNull = true;
                        }
                    }
                }
                if (paramStart < paramEnd) {
                    params.children.push(ValueParser.parse(raw.slice(paramStart, paramEnd), options, baseOffset + paramStart));
                }
                else {
                    params.children.push(null);
                }
            }
            if (extraNull) {
                params.children.push(null);
            }
            return params;
        }
    }

    /**
     * @file uBlock scriptlet injection body parser
     */
    /**
     * `UboScriptletInjectionBodyParser` is responsible for parsing the body of a uBlock-style scriptlet rule.
     *
     * Please note that the parser will parse any scriptlet rule if it is syntactically correct.
     * For example, it will parse this:
     * ```adblock
     * example.com##+js(scriptlet0, arg0)
     * ```
     *
     * but it didn't check if the scriptlet `scriptlet0` actually supported by any adblocker.
     *
     * @see {@link https://github.com/gorhill/uBlock/wiki/Static-filter-syntax#scriptlet-injection}
     */
    class UboScriptletInjectionBodyParser extends ParserBase {
        /**
         * Error messages used by the parser.
         */
        static ERROR_MESSAGES = {
            NO_SCRIPTLET_MASK: `Invalid uBO scriptlet call, no scriptlet call mask '${UBO_SCRIPTLET_MASK}' found`,
            NO_OPENING_PARENTHESIS: `Invalid uBO scriptlet call, no opening parentheses '${OPEN_PARENTHESIS}' found`,
            NO_CLOSING_PARENTHESIS: `Invalid uBO scriptlet call, no closing parentheses '${CLOSE_PARENTHESIS}' found`,
            NO_SCRIPTLET_NAME: 'Invalid uBO scriptlet call, no scriptlet name specified',
            WHITESPACE_AFTER_MASK: 'Invalid uBO scriptlet call, whitespace is not allowed after the scriptlet call mask',
            NO_MULTIPLE_SCRIPTLET_CALLS: 'uBO syntaxes does not support multiple scriptlet calls within one single rule',
        };
        /**
         * Value map for binary serialization. This helps to reduce the size of the serialized data,
         * as it allows us to use a single byte to represent frequently used values.
         *
         * ! IMPORTANT: If you change values here, please update the {@link BINARY_SCHEMA_VERSION}!
         *
         * @note Only 256 values can be represented this way.
         */
        // TODO: Update this map with the actual values
        static FREQUENT_ARGS_SERIALIZATION_MAP = new Map([
            ['abort-current-script.js', 0],
            ['acs.js', 1],
            ['abort-current-inline-script.js', 2],
            ['acis.js', 3],
            ['abort-on-property-read.js', 4],
            ['aopr.js', 5],
            ['abort-on-property-write.js', 6],
            ['aopw.js', 7],
            ['abort-on-stack-trace.js', 8],
            ['aost.js', 9],
            ['adjust-setInterval.js', 10],
            ['nano-setInterval-booster.js', 11],
            ['nano-sib.js', 12],
            ['adjust-setTimeout.js', 13],
            ['nano-setTimeout-booster.js', 14],
            ['nano-stb.js', 15],
            ['close-window.js', 16],
            ['window-close-if.js', 17],
            ['disable-newtab-links.js', 18],
            ['evaldata-prune.js', 19],
            ['json-prune.js', 20],
            ['addEventListener-logger.js', 21],
            ['aell.js', 22],
            ['m3u-prune.js', 23],
            ['nowebrtc.js', 24],
            ['addEventListener-defuser.js', 25],
            ['aeld.js', 26],
            ['prevent-addEventListener.js', 27],
            ['adfly-defuser.js', 28],
            ['noeval-if.js', 29],
            ['prevent-eval-if.js', 30],
            ['no-fetch-if.js', 31],
            ['prevent-fetch.js', 32],
            ['no-xhr-if.js', 33],
            ['prevent-xhr.js', 34],
            ['prevent-refresh.js', 35],
            ['refresh-defuser.js', 36],
            ['no-requestAnimationFrame-if.js', 37],
            ['norafif.js', 38],
            ['prevent-requestAnimationFrame.js', 39],
            ['no-setInterval-if.js', 40],
            ['nosiif.js', 41],
            ['prevent-setInterval.js', 42],
            ['setInterval-defuser.js', 43],
            ['no-setTimeout-if.js', 44],
            ['nostif.js', 45],
            ['prevent-setTimeout.js', 46],
            ['setTimeout-defuser.js', 47],
            ['no-window-open-if.js', 48],
            ['nowoif.js', 49],
            ['prevent-window-open.js', 50],
            ['window.open-defuser.js', 51],
            ['remove-attr.js', 52],
            ['ra.js', 53],
            ['remove-class.js', 54],
            ['rc.js', 55],
            ['remove-cookie.js', 56],
            ['cookie-remover.js', 57],
            ['remove-node-text.js', 58],
            ['rmnt.js', 59],
            ['set-attr.js', 60],
            ['set-constant.js', 61],
            ['set.js', 62],
            ['set-cookie.js', 63],
            ['set-local-storage-item.js', 64],
            ['set-session-storage-item.js', 65],
            ['xml-prune.js', 66],
            ['webrtc-if.js', 67],
            ['overlay-buster.js', 68],
            ['alert-buster.js', 69],
            ['golem.de.js', 70],
            ['href-sanitizer.js', 71],
            ['call-nothrow.js', 72],
            ['window.name-defuser.js', 73],
            ['spoof-css.js', 74],
            ['trusted-set-constant.js', 75],
            ['trusted-set.js', 76],
            ['trusted-set-cookie.js', 77],
            ['trusted-set-local-storage-item.js', 78],
            ['trusted-replace-fetch-response.js', 79],
            ['json-prune-fetch-response.js', 80],
            ['json-prune-xhr-response.js', 81],
            ['trusted-replace-xhr-response.js', 82],
            ['multiup.js', 83],
            ['prevent-canvas.js', 84],
            ['set-cookie-reload.js', 85],
            ['trusted-set-cookie-reload.js', 86],
            ['trusted-click-element.js', 87],
            ['trusted-prune-inbound-object.js', 88],
            ['trusted-prune-outbound-object.js', 89],
            ['trusted-set-session-storage-item.js', 90],
            ['trusted-replace-node-text.js', 91],
            ['trusted-rpnt.js', 92],
            ['replace-node-text.js', 93],
            ['rpnt.js', 94],
        ]);
        /**
         * Value map for binary deserialization. This helps to reduce the size of the serialized data,
         * as it allows us to use a single byte to represent frequently used values.
         */
        static FREQUENT_ARGS_DESERIALIZATION_MAP = new Map(Array.from(this.FREQUENT_ARGS_SERIALIZATION_MAP).map(([key, value]) => [value, key]));
        /**
         * Parses the body of a uBlock-style scriptlet rule.
         *
         * @param raw Raw input to parse.
         * @param options Global parser options.
         * @param baseOffset Starting offset of the input. Node locations are calculated relative to this offset.
         * @returns Node of the parsed scriptlet call body
         * @throws If the body is syntactically incorrect
         * @example
         * ```
         * ##+js(scriptlet0, arg0)
         * ```
         */
        static parse(raw, options = defaultParserOptions, baseOffset = 0) {
            let offset = 0;
            // Skip leading spaces
            offset = StringUtils.skipWS(raw, offset);
            let scriptletMaskLength = 0;
            if (raw.startsWith(UBO_SCRIPTLET_MASK, offset)) {
                scriptletMaskLength = UBO_SCRIPTLET_MASK.length;
            }
            else if (raw.startsWith(UBO_SCRIPTLET_MASK_LEGACY, offset)) {
                scriptletMaskLength = UBO_SCRIPTLET_MASK_LEGACY.length;
            }
            // Scriptlet call should start with "+js"
            if (!scriptletMaskLength) {
                throw new AdblockSyntaxError(this.ERROR_MESSAGES.NO_SCRIPTLET_MASK, baseOffset + offset, baseOffset + raw.length);
            }
            offset += scriptletMaskLength;
            // Whitespace is not allowed after the mask
            if (raw[offset] === SPACE) {
                throw new AdblockSyntaxError(this.ERROR_MESSAGES.WHITESPACE_AFTER_MASK, baseOffset + offset, baseOffset + raw.length);
            }
            // Parameter list should be wrapped in parentheses
            if (raw[offset] !== OPEN_PARENTHESIS) {
                throw new AdblockSyntaxError(this.ERROR_MESSAGES.NO_OPENING_PARENTHESIS, baseOffset + offset, baseOffset + raw.length);
            }
            // Save the offset of the opening parentheses
            const openingParenthesesIndex = offset;
            // Skip whitespace from the end
            const closingParenthesesIndex = StringUtils.skipWSBack(raw, raw.length - 1);
            // Closing parentheses should be present
            if (raw[closingParenthesesIndex] !== CLOSE_PARENTHESIS
                || raw[closingParenthesesIndex - 1] === ESCAPE_CHARACTER) {
                throw new AdblockSyntaxError(this.ERROR_MESSAGES.NO_CLOSING_PARENTHESIS, baseOffset + offset, baseOffset + raw.length);
            }
            const result = {
                type: 'ScriptletInjectionRuleBody',
                children: [],
            };
            if (options.isLocIncluded) {
                result.start = baseOffset;
                result.end = baseOffset + raw.length;
            }
            // Special case: empty scriptlet call, like +js(), +js( ), etc.
            if (StringUtils.skipWS(raw, openingParenthesesIndex + 1) === closingParenthesesIndex) {
                return result;
            }
            // Parse parameter list
            const params = UboParameterListParser.parse(raw.slice(openingParenthesesIndex + 1, closingParenthesesIndex), options, baseOffset + openingParenthesesIndex + 1, COMMA);
            // Do not allow parameters without scriptlet: +js(, arg0, arg1)
            if (params.children.length > 0 && params.children[0] === null) {
                throw new AdblockSyntaxError(this.ERROR_MESSAGES.NO_SCRIPTLET_NAME, baseOffset + offset, baseOffset + raw.length);
            }
            result.children.push(params);
            return result;
        }
        /**
         * Generates a string representation of the uBlock scriptlet call body.
         *
         * @param node Scriptlet injection rule body
         * @returns String representation of the rule body
         */
        static generate(node) {
            const result = [];
            if (node.children.length > 1) {
                throw new Error(this.ERROR_MESSAGES.NO_MULTIPLE_SCRIPTLET_CALLS);
            }
            // During generation, we only support the modern scriptlet mask
            result.push(UBO_SCRIPTLET_MASK);
            result.push(OPEN_PARENTHESIS);
            if (node.children.length > 0) {
                const [parameterListNode] = node.children;
                result.push(ParameterListParser.generate(parameterListNode));
            }
            result.push(CLOSE_PARENTHESIS);
            return result.join(EMPTY);
        }
        /**
         * Serializes a scriptlet call body node to binary format.
         *
         * @param node Node to serialize.
         * @param buffer ByteBuffer for writing binary data.
         */
        static serialize(node, buffer) {
            serializeScriptletBody(node, buffer, this.FREQUENT_ARGS_SERIALIZATION_MAP);
        }
        /**
         * Deserializes a scriptlet call body node from binary format.
         *
         * @param buffer ByteBuffer for reading binary data.
         * @param node Destination node.
         * @throws If the binary data is malformed.
         */
        static deserialize(buffer, node) {
            deserializeScriptletBody(buffer, node, this.FREQUENT_ARGS_DESERIALIZATION_MAP);
        }
    }

    /**
     * @file AdGuard scriptlet injection body parser
     */
    /**
     * `AdgScriptletInjectionBodyParser` is responsible for parsing the body of an AdGuard-style scriptlet rule.
     *
     * Please note that the parser will parse any scriptlet rule if it is syntactically correct.
     * For example, it will parse this:
     * ```adblock
     * example.com#%#//scriptlet('scriptlet0', 'arg0')
     * ```
     *
     * but it didn't check if the scriptlet `scriptlet0` actually supported by any adblocker.
     *
     * @see {@link https://kb.adguard.com/en/general/how-to-create-your-own-ad-filters#scriptlets}
     */
    class AdgScriptletInjectionBodyParser extends ParserBase {
        /**
         * Error messages used by the parser.
         */
        static ERROR_MESSAGES = {
            NO_SCRIPTLET_MASK: `Invalid ADG scriptlet call, no scriptlet call mask '${ADG_SCRIPTLET_MASK}' found`,
            NO_OPENING_PARENTHESIS: `Invalid ADG scriptlet call, no opening parentheses '${OPEN_PARENTHESIS}' found`,
            NO_CLOSING_PARENTHESIS: `Invalid ADG scriptlet call, no closing parentheses '${CLOSE_PARENTHESIS}' found`,
            WHITESPACE_AFTER_MASK: 'Invalid ADG scriptlet call, whitespace is not allowed after the scriptlet call mask',
            NO_MULTIPLE_SCRIPTLET_CALLS: 'ADG syntaxes does not support multiple scriptlet calls within one single rule',
            NO_INCONSISTENT_QUOTES: 'Invalid ADG scriptlet call, inconsistent quotes',
            NO_UNCLOSED_PARAMETER: 'Invalid ADG scriptlet call, unclosed parameter',
            EXPECTED_QUOTE: "Invalid ADG scriptlet call, expected quote, got '%s'",
            EXPECTED_COMMA: "Invalid ADG scriptlet call, expected comma, got '%s'",
        };
        /**
         * Value map for binary serialization. This helps to reduce the size of the serialized data,
         * as it allows us to use a single byte to represent frequently used values.
         *
         * ! IMPORTANT: If you change values here, please update the {@link BINARY_SCHEMA_VERSION}!
         *
         * @note Only 256 values can be represented this way.
         */
        // TODO: Update this map with the actual values
        static FREQUENT_ARGS_SERIALIZATION_MAP = new Map([
            ['abort-current-inline-script', 0],
            ['abort-on-property-read', 1],
            ['abort-on-property-write', 2],
            ['abort-on-stack-trace', 3],
            ['adjust-setInterval', 4],
            ['adjust-setTimeout', 5],
            ['close-window', 6],
            ['debug-current-inline-script', 7],
            ['debug-on-property-read', 8],
            ['debug-on-property-write', 9],
            ['dir-string', 10],
            ['disable-newtab-links', 11],
            ['evaldata-prune', 12],
            ['json-prune', 13],
            ['log', 14],
            ['log-addEventListener', 15],
            ['log-eval', 16],
            ['log-on-stack-trace', 17],
            ['m3u-prune', 18],
            ['noeval', 19],
            ['nowebrtc', 20],
            ['no-topics', 21],
            ['prevent-addEventListener', 22],
            ['prevent-adfly', 23],
            ['prevent-bab', 24],
            ['prevent-eval-if', 25],
            ['prevent-fab-3.2.0', 26],
            ['prevent-fetch', 27],
            ['prevent-xhr', 28],
            ['prevent-popads-net', 29],
            ['prevent-refresh', 30],
            ['prevent-requestAnimationFrame', 31],
            ['prevent-setInterval', 32],
            ['prevent-setTimeout', 33],
            ['prevent-window-open', 34],
            ['remove-attr', 35],
            ['remove-class', 36],
            ['remove-cookie', 37],
            ['remove-node-text', 38],
            ['set-attr', 39],
            ['set-constant', 40],
            ['set-cookie', 41],
            ['set-cookie-reload', 42],
            ['set-local-storage-item', 43],
            ['set-popads-dummy', 44],
            ['set-session-storage-item', 45],
            ['xml-prune', 46],
        ]);
        /**
         * Value map for binary deserialization. This helps to reduce the size of the serialized data,
         * as it allows us to use a single byte to represent frequently used values.
         */
        static FREQUENT_ARGS_DESERIALIZATION_MAP = new Map(Array.from(this.FREQUENT_ARGS_SERIALIZATION_MAP).map(([key, value]) => [value, key]));
        /**
         * Parses the body of an AdGuard-style scriptlet rule.
         *
         * @param raw Raw input to parse.
         * @param options Global parser options.
         * @param baseOffset Starting offset of the input. Node locations are calculated relative to this offset.
         * @returns Node of the parsed scriptlet call body
         * @throws If the body is syntactically incorrect
         * @example
         * ```
         * //scriptlet('scriptlet0', 'arg0')
         * ```
         */
        static parse(raw, options = defaultParserOptions, baseOffset = 0) {
            let offset = 0;
            // Skip leading spaces
            offset = StringUtils.skipWS(raw, offset);
            // Scriptlet call should start with "//scriptlet"
            if (!raw.startsWith(ADG_SCRIPTLET_MASK, offset)) {
                throw new AdblockSyntaxError(this.ERROR_MESSAGES.NO_SCRIPTLET_MASK, baseOffset + offset, baseOffset + raw.length);
            }
            offset += ADG_SCRIPTLET_MASK.length;
            // Whitespace is not allowed after the mask
            if (raw[offset] === SPACE) {
                throw new AdblockSyntaxError(this.ERROR_MESSAGES.WHITESPACE_AFTER_MASK, baseOffset + offset, baseOffset + raw.length);
            }
            // Parameter list should be wrapped in parentheses
            if (raw[offset] !== OPEN_PARENTHESIS) {
                throw new AdblockSyntaxError(this.ERROR_MESSAGES.NO_OPENING_PARENTHESIS, baseOffset + offset, baseOffset + raw.length);
            }
            // Save the offset of the opening parentheses
            const openingParenthesesIndex = offset;
            // Skip whitespace from the end
            const closingParenthesesIndex = StringUtils.skipWSBack(raw, raw.length - 1);
            // Closing parentheses should be present
            if (raw[closingParenthesesIndex] !== CLOSE_PARENTHESIS
                || raw[closingParenthesesIndex - 1] === ESCAPE_CHARACTER) {
                throw new AdblockSyntaxError(this.ERROR_MESSAGES.NO_CLOSING_PARENTHESIS, baseOffset + offset, baseOffset + raw.length);
            }
            // Skip space, if any
            offset = StringUtils.skipWS(raw, offset + 1);
            const result = {
                type: 'ScriptletInjectionRuleBody',
                children: [],
            };
            if (options.isLocIncluded) {
                result.start = baseOffset;
                result.end = baseOffset + raw.length;
            }
            // Special case: empty scriptlet call, like `//scriptlet()`, `//scriptlet( )` etc.
            if (StringUtils.skipWS(raw, openingParenthesesIndex + 1) === closingParenthesesIndex) {
                return result;
            }
            let detectedQuote = null;
            const parameterList = {
                type: 'ParameterList',
                children: [],
            };
            if (options.isLocIncluded) {
                parameterList.start = baseOffset + openingParenthesesIndex + 1;
                parameterList.end = baseOffset + closingParenthesesIndex;
            }
            while (offset < closingParenthesesIndex) {
                // Skip whitespace
                offset = StringUtils.skipWS(raw, offset);
                // Expect comma if not first parameter
                if (parameterList.children.length > 0) {
                    if (raw[offset] !== COMMA) {
                        throw new AdblockSyntaxError(sprintf.sprintf(AdgScriptletInjectionBodyParser.ERROR_MESSAGES.EXPECTED_COMMA, raw[offset]), baseOffset + offset, baseOffset + raw.length);
                    }
                    // Eat the comma
                    offset += 1;
                    // Skip whitespace
                    offset = StringUtils.skipWS(raw, offset);
                }
                // Next character should be a quote
                if (raw[offset] === SINGLE_QUOTE || raw[offset] === DOUBLE_QUOTE) {
                    if (isNull$1(detectedQuote)) {
                        detectedQuote = raw[offset];
                    }
                    else if (detectedQuote !== raw[offset]) {
                        throw new AdblockSyntaxError(AdgScriptletInjectionBodyParser.ERROR_MESSAGES.NO_INCONSISTENT_QUOTES, baseOffset + offset, baseOffset + raw.length);
                    }
                    // Find next unescaped same quote
                    const closingQuoteIndex = StringUtils.findNextUnescapedCharacter(raw, detectedQuote, offset + 1);
                    if (closingQuoteIndex === -1) {
                        throw new AdblockSyntaxError(AdgScriptletInjectionBodyParser.ERROR_MESSAGES.NO_UNCLOSED_PARAMETER, baseOffset + offset, baseOffset + raw.length);
                    }
                    // Save the parameter
                    const parameter = ValueParser.parse(raw.slice(offset, closingQuoteIndex + 1), options, baseOffset + offset);
                    parameterList.children.push(parameter);
                    // Move after the closing quote
                    offset = StringUtils.skipWS(raw, closingQuoteIndex + 1);
                }
                else {
                    throw new AdblockSyntaxError(sprintf.sprintf(AdgScriptletInjectionBodyParser.ERROR_MESSAGES.EXPECTED_QUOTE, raw[offset]), baseOffset + offset, baseOffset + raw.length);
                }
            }
            result.children.push(parameterList);
            return result;
        }
        /**
         * Generates a string representation of the AdGuard scriptlet call body.
         *
         * @param node Scriptlet injection rule body
         * @returns String representation of the rule body
         */
        static generate(node) {
            const result = [];
            if (node.children.length > 1) {
                throw new Error(this.ERROR_MESSAGES.NO_MULTIPLE_SCRIPTLET_CALLS);
            }
            result.push(ADG_SCRIPTLET_MASK);
            result.push(OPEN_PARENTHESIS);
            if (node.children.length > 0) {
                result.push(ParameterListParser.generate(node.children[0]));
            }
            result.push(CLOSE_PARENTHESIS);
            return result.join(EMPTY);
        }
        /**
         * Serializes a scriptlet call body node to binary format.
         *
         * @param node Node to serialize.
         * @param buffer ByteBuffer for writing binary data.
         */
        static serialize(node, buffer) {
            serializeScriptletBody(node, buffer, this.FREQUENT_ARGS_SERIALIZATION_MAP);
        }
        /**
         * Deserializes a scriptlet call body node from binary format.
         *
         * @param buffer ByteBuffer for reading binary data.
         * @param node Destination node.
         * @throws If the binary data is malformed.
         */
        static deserialize(buffer, node) {
            deserializeScriptletBody(buffer, node, this.FREQUENT_ARGS_DESERIALIZATION_MAP);
        }
    }

    /* eslint-disable no-param-reassign */
    /**
     * Value map for binary serialization. This helps to reduce the size of the serialized data,
     * as it allows us to use a single byte to represent frequently used values.
     *
     * ! IMPORTANT: If you change values here, please update the {@link BINARY_SCHEMA_VERSION}!
     *
     * @note Only 256 values can be represented this way.
     */
    const SEPARATOR_SERIALIZATION_MAP = new Map([
        ['##', 0],
        ['#@#', 1],
        ['#?#', 2],
        ['#@?#', 3],
        ['#$#', 4],
        ['#$?#', 5],
        ['#@$#', 6],
        ['#@$?#', 7],
        ['#%#', 8],
        ['#@%#', 9],
        ['$$', 10],
        ['$@$', 11],
    ]);
    /**
     * Value map for binary deserialization. This helps to reduce the size of the serialized data,
     * as it allows us to use a single byte to represent frequently used values.
     */
    const SEPARATOR_DESERIALIZATION_MAP = new Map(Array.from(SEPARATOR_SERIALIZATION_MAP).map(([key, value]) => [value, key]));
    /**
     * Value map for binary deserialization. This helps to reduce the size of the serialized data,
     * as it allows us to use a single byte to represent frequently used values.
     */
    const COSMETIC_RULE_TYPE_DESERIALIZATION_MAP = new Map([
        [BinaryTypeMap.ElementHidingRule, CosmeticRuleType.ElementHidingRule],
        [BinaryTypeMap.CssInjectionRule, CosmeticRuleType.CssInjectionRule],
        [BinaryTypeMap.ScriptletInjectionRule, CosmeticRuleType.ScriptletInjectionRule],
        [BinaryTypeMap.JsInjectionRule, CosmeticRuleType.JsInjectionRule],
        [BinaryTypeMap.HtmlFilteringRule, CosmeticRuleType.HtmlFilteringRule],
    ]);
    /**
     * Property map for binary serialization. This helps to reduce the size of the serialized data,
     * as it allows us to use a single byte to represent a property.
     *
     * ! IMPORTANT: If you change values here, please update the {@link BINARY_SCHEMA_VERSION}!
     *
     * @note Only 256 values can be represented this way.
     */
    var ElementHidingRuleSerializationMap;
    (function (ElementHidingRuleSerializationMap) {
        ElementHidingRuleSerializationMap[ElementHidingRuleSerializationMap["SelectorList"] = 1] = "SelectorList";
        ElementHidingRuleSerializationMap[ElementHidingRuleSerializationMap["Start"] = 2] = "Start";
        ElementHidingRuleSerializationMap[ElementHidingRuleSerializationMap["End"] = 3] = "End";
    })(ElementHidingRuleSerializationMap || (ElementHidingRuleSerializationMap = {}));
    /**
     * Property map for binary serialization. This helps to reduce the size of the serialized data,
     * as it allows us to use a single byte to represent a property.
     *
     * ! IMPORTANT: If you change values here, please update the {@link BINARY_SCHEMA_VERSION}!
     *
     * @note Only 256 values can be represented this way.
     */
    var CssInjectionRuleSerializationMap;
    (function (CssInjectionRuleSerializationMap) {
        CssInjectionRuleSerializationMap[CssInjectionRuleSerializationMap["SelectorList"] = 1] = "SelectorList";
        CssInjectionRuleSerializationMap[CssInjectionRuleSerializationMap["DeclarationList"] = 2] = "DeclarationList";
        CssInjectionRuleSerializationMap[CssInjectionRuleSerializationMap["MediaQueryList"] = 3] = "MediaQueryList";
        CssInjectionRuleSerializationMap[CssInjectionRuleSerializationMap["Remove"] = 4] = "Remove";
        CssInjectionRuleSerializationMap[CssInjectionRuleSerializationMap["Start"] = 5] = "Start";
        CssInjectionRuleSerializationMap[CssInjectionRuleSerializationMap["End"] = 6] = "End";
    })(CssInjectionRuleSerializationMap || (CssInjectionRuleSerializationMap = {}));
    /**
     * Property map for binary serialization. This helps to reduce the size of the serialized data,
     * as it allows us to use a single byte to represent a property.
     *
     * ! IMPORTANT: If you change values here, please update the {@link BINARY_SCHEMA_VERSION}!
     *
     * @note Only 256 values can be represented this way.
     */
    var CosmeticRuleSerializationMap;
    (function (CosmeticRuleSerializationMap) {
        CosmeticRuleSerializationMap[CosmeticRuleSerializationMap["Syntax"] = 1] = "Syntax";
        CosmeticRuleSerializationMap[CosmeticRuleSerializationMap["Exception"] = 2] = "Exception";
        CosmeticRuleSerializationMap[CosmeticRuleSerializationMap["Separator"] = 3] = "Separator";
        CosmeticRuleSerializationMap[CosmeticRuleSerializationMap["Modifiers"] = 4] = "Modifiers";
        CosmeticRuleSerializationMap[CosmeticRuleSerializationMap["Domains"] = 5] = "Domains";
        CosmeticRuleSerializationMap[CosmeticRuleSerializationMap["Body"] = 6] = "Body";
        CosmeticRuleSerializationMap[CosmeticRuleSerializationMap["Start"] = 7] = "Start";
        CosmeticRuleSerializationMap[CosmeticRuleSerializationMap["End"] = 8] = "End";
    })(CosmeticRuleSerializationMap || (CosmeticRuleSerializationMap = {}));
    /**
     * Possible error messages for uBO selectors. Formatted with {@link sprintf}.
     */
    const ERROR_MESSAGES$3 = {
        EMPTY_RULE_BODY: 'Empty rule body',
        INVALID_BODY_FOR_SEPARATOR: "Body '%s' is not valid for the '%s' cosmetic rule separator",
        MISSING_ADGUARD_MODIFIER_LIST_END: "Missing '%s' at the end of the AdGuard modifier list in pattern '%s'",
        MISSING_ADGUARD_MODIFIER_LIST_MARKER: "Missing '%s' at the beginning of the AdGuard modifier list in pattern '%s'",
        SYNTAXES_CANNOT_BE_MIXED: "'%s' syntax cannot be mixed with '%s' syntax",
        SYNTAX_DISABLED: "Parsing '%s' syntax is disabled, but the rule uses it",
    };
    const ADG_CSS_INJECTION_PATTERN = /^(?:.+){(?:.+)}$/;
    /**
     * `CosmeticRuleParser` is responsible for parsing cosmetic rules.
     *
     * Where possible, it automatically detects the difference between supported syntaxes:
     *  - AdGuard
     *  - uBlock Origin
     *  - Adblock Plus
     *
     * If the syntax is common / cannot be determined, the parser gives `Common` syntax.
     *
     * Please note that syntactically correct rules are parsed even if they are not actually
     * compatible with the given adblocker. This is a completely natural behavior, meaningful
     * checking of compatibility is not done at the parser level.
     */
    // TODO: Make raw body parsing optional
    // TODO: Split into smaller sections
    class CosmeticRuleParser extends ParserBase {
        /**
         * Determines whether a rule is a cosmetic rule. The rule is considered cosmetic if it
         * contains a cosmetic rule separator.
         *
         * @param raw Raw rule
         * @returns `true` if the rule is a cosmetic rule, `false` otherwise
         */
        static isCosmeticRule(raw) {
            const trimmed = raw.trim();
            if (CommentRuleParser.isCommentRule(trimmed)) {
                return false;
            }
            return CosmeticRuleSeparatorUtils.find(trimmed) !== null;
        }
        /**
         * Parses a cosmetic rule. The structure of the cosmetic rules:
         *  - pattern (AdGuard pattern can have modifiers, other syntaxes don't)
         *  - separator
         *  - body
         *
         * @param raw Raw input to parse.
         * @param options Global parser options.
         * @param baseOffset Starting offset of the input. Node locations are calculated relative to this offset.
         * @returns
         * Parsed cosmetic rule AST or null if it failed to parse based on the known cosmetic rules
         * @throws If the input matches the cosmetic rule pattern but syntactically invalid
         */
        // TODO: Split to smaller functions
        static parse(raw, options = defaultParserOptions, baseOffset = 0) {
            // Find cosmetic rule separator - each cosmetic rule must have it, otherwise it is not a cosmetic rule
            const separatorResult = CosmeticRuleSeparatorUtils.find(raw);
            if (!separatorResult) {
                return null;
            }
            let syntax = AdblockSyntax.Common;
            let modifiers;
            const patternStart = StringUtils.skipWS(raw);
            const patternEnd = StringUtils.skipWSBack(raw, separatorResult.start - 1) + 1;
            const bodyStart = StringUtils.skipWS(raw, separatorResult.end);
            const bodyEnd = StringUtils.skipWSBack(raw) + 1;
            // Note we use '<=' instead of '===' because we have bidirectional trim
            if (bodyEnd <= bodyStart) {
                throw new AdblockSyntaxError(ERROR_MESSAGES$3.EMPTY_RULE_BODY, baseOffset, baseOffset + raw.length);
            }
            // Step 1. Parse the pattern: it can be a domain list or a domain list with modifiers (AdGuard)
            const rawPattern = raw.slice(patternStart, patternEnd);
            let patternOffset = patternStart;
            if (rawPattern[patternOffset] === OPEN_SQUARE_BRACKET) {
                // Save offset to the beginning of the modifier list for later
                const modifierListStart = patternOffset;
                // Consume opening square bracket
                patternOffset += 1;
                // Skip whitespace after opening square bracket
                patternOffset = StringUtils.skipWS(rawPattern, patternOffset);
                // Open square bracket should be followed by a modifier separator: [$
                if (rawPattern[patternOffset] !== DOLLAR_SIGN) {
                    throw new AdblockSyntaxError(sprintf.sprintf(ERROR_MESSAGES$3.MISSING_ADGUARD_MODIFIER_LIST_MARKER, DOLLAR_SIGN, rawPattern), baseOffset + patternOffset, baseOffset + rawPattern.length);
                }
                // Consume modifier separator
                patternOffset += 1;
                // Skip whitespace after modifier separator
                patternOffset = StringUtils.skipWS(rawPattern, patternOffset);
                // Modifier list ends with the last unescaped square bracket
                // We search for the last unescaped square bracket, because some modifiers can contain square brackets,
                // e.g. [$domain=/example[0-9]\.(com|org)/]##.ad
                const modifierListEnd = StringUtils.findLastUnescapedCharacter(rawPattern, CLOSE_SQUARE_BRACKET);
                if (modifierListEnd === -1) {
                    throw new AdblockSyntaxError(sprintf.sprintf(ERROR_MESSAGES$3.MISSING_ADGUARD_MODIFIER_LIST_END, CLOSE_SQUARE_BRACKET, rawPattern), baseOffset + patternOffset, baseOffset + rawPattern.length);
                }
                // Parse modifier list
                modifiers = ModifierListParser.parse(raw.slice(patternOffset, modifierListEnd), options, baseOffset + patternOffset);
                // Expand modifier list location to include the opening and closing square brackets
                if (options.isLocIncluded) {
                    modifiers.start = baseOffset + modifierListStart;
                    modifiers.end = baseOffset + modifierListEnd + 1;
                }
                // Consume modifier list
                patternOffset = modifierListEnd + 1;
                // Change the syntax to ADG
                syntax = AdblockSyntax.Adg;
            }
            // Skip whitespace after modifier list
            patternOffset = StringUtils.skipWS(rawPattern, patternOffset);
            // Parse domains
            const domains = DomainListParser.parse(rawPattern.slice(patternOffset), options, baseOffset + patternOffset);
            // Step 2. Parse the separator
            const separator = {
                type: 'Value',
                value: separatorResult.separator,
            };
            if (options.isLocIncluded) {
                separator.start = baseOffset + separatorResult.start;
                separator.end = baseOffset + separatorResult.end;
            }
            const exception = CosmeticRuleSeparatorUtils.isException(separatorResult.separator);
            // Step 3. Parse the rule body
            let rawBody = raw.slice(bodyStart, bodyEnd);
            /**
             * Ensures that the rule syntax is common or the expected one. This function is used to prevent mixing
             * different syntaxes in the same rule.
             *
             * @example
             * The following rule mixes AdGuard and uBO syntaxes, because it uses AdGuard modifier list and uBO
             * CSS injection:
             * ```adblock
             * [$path=/something]example.com##.foo:style(color: red)
             * ```
             * In this case, parser sets syntax to AdGuard, because it detects the AdGuard modifier list, but
             * when parsing the rule body, it detects uBO CSS injection, which is not compatible with AdGuard.
             *
             * @param expectedSyntax Expected syntax
             * @throws If the rule syntax is not common or the expected one
             */
            const expectCommonOrSpecificSyntax = (expectedSyntax) => {
                if (syntax !== AdblockSyntax.Common && syntax !== expectedSyntax) {
                    throw new AdblockSyntaxError(sprintf.sprintf(ERROR_MESSAGES$3.SYNTAXES_CANNOT_BE_MIXED, expectedSyntax, syntax), baseOffset + patternStart, baseOffset + bodyEnd);
                }
            };
            let uboSelector;
            // Parse UBO rule modifiers
            if (options.parseUboSpecificRules) {
                uboSelector = UboSelectorParser.parse(rawBody, options, baseOffset + bodyStart);
                rawBody = uboSelector.selector.value;
                // Do not allow ADG modifiers and UBO modifiers in the same rule
                if (uboSelector.modifiers && uboSelector.modifiers.children.length > 0) {
                    // If modifiers are present, that means that the ADG modifier list was parsed
                    expectCommonOrSpecificSyntax(AdblockSyntax.Ubo);
                    // Change the syntax to uBO
                    syntax = AdblockSyntax.Ubo;
                    // Store the rule modifiers
                    // Please note that not each special uBO modifier is a rule modifier, some of them are
                    // used for CSS injection, for example `:style()` and `:remove()`
                    for (const modifier of uboSelector.modifiers.children) {
                        // TODO: Add support for matches-media and element hiding rules
                        // TODO: Improve this condition if new uBO modifiers are added
                        if (modifier.name.value === UboPseudoName.MatchesPath) {
                            // Prepare the modifier list if it does not exist yet
                            if (!modifiers) {
                                modifiers = {
                                    type: 'ModifierList',
                                    children: [],
                                };
                                if (options.isLocIncluded) {
                                    modifiers.start = baseOffset + bodyStart;
                                    modifiers.end = baseOffset + bodyEnd;
                                }
                            }
                            modifiers.children.push(modifier);
                        }
                    }
                }
            }
            const raws = {
                text: raw,
            };
            const baseRule = {
                category: RuleCategory.Cosmetic,
                exception,
                modifiers,
                domains,
                separator,
            };
            if (options.includeRaws) {
                baseRule.raws = raws;
            }
            if (options.isLocIncluded) {
                baseRule.start = baseOffset;
                baseRule.end = baseOffset + raw.length;
            }
            const parseUboCssInjection = () => {
                if (!uboSelector || !uboSelector.modifiers || uboSelector.modifiers.children?.length < 1) {
                    return null;
                }
                expectCommonOrSpecificSyntax(AdblockSyntax.Ubo);
                const selectorList = uboSelector.selector;
                let declarationList;
                let mediaQueryList;
                let remove = false;
                for (const modifier of uboSelector.modifiers.children) {
                    switch (modifier.name.value) {
                        case UboPseudoName.Style:
                            declarationList = modifier.value;
                            break;
                        case UboPseudoName.Remove:
                            declarationList = {
                                type: 'Value',
                                value: '',
                            };
                            remove = true;
                            break;
                        case UboPseudoName.MatchesMedia:
                            mediaQueryList = modifier.value;
                            break;
                    }
                }
                // If neither `:style()` nor `:remove()` is present
                if (!declarationList) {
                    return null;
                }
                const body = {
                    type: 'CssInjectionRuleBody',
                    selectorList,
                    declarationList,
                    mediaQueryList,
                    remove,
                };
                if (options.isLocIncluded) {
                    body.start = baseOffset + bodyStart;
                    body.end = baseOffset + bodyEnd;
                }
                return {
                    syntax: AdblockSyntax.Ubo,
                    type: CosmeticRuleType.CssInjectionRule,
                    body,
                };
            };
            const parseElementHiding = () => {
                const selectorList = {
                    type: 'Value',
                    value: rawBody,
                };
                if (options.isLocIncluded) {
                    selectorList.start = baseOffset + bodyStart;
                    selectorList.end = baseOffset + bodyEnd;
                }
                const body = {
                    type: 'ElementHidingRuleBody',
                    selectorList,
                };
                if (options.isLocIncluded) {
                    body.start = baseOffset + bodyStart;
                    body.end = baseOffset + bodyEnd;
                }
                return {
                    syntax,
                    type: CosmeticRuleType.ElementHidingRule,
                    body,
                };
            };
            const parseAdgCssInjection = () => {
                // TODO: Improve this detection. Need to cover the following cases:
                // #$#body { color: red;
                // #$#@media (min-width: 100px) { body { color: red; }
                // ADG CSS injection
                if (!ADG_CSS_INJECTION_PATTERN.test(rawBody)) {
                    return null;
                }
                expectCommonOrSpecificSyntax(AdblockSyntax.Adg);
                return {
                    syntax: AdblockSyntax.Adg,
                    type: CosmeticRuleType.CssInjectionRule,
                    body: AdgCssInjectionParser.parse(rawBody, options, baseOffset + bodyStart),
                };
            };
            const parseAbpSnippetInjection = () => {
                if (!options.parseAbpSpecificRules) {
                    throw new AdblockSyntaxError(sprintf.sprintf(ERROR_MESSAGES$3.SYNTAX_DISABLED, AdblockSyntax.Abp), baseOffset + bodyStart, baseOffset + bodyEnd);
                }
                expectCommonOrSpecificSyntax(AdblockSyntax.Abp);
                const body = AbpSnippetInjectionBodyParser.parse(rawBody, options, baseOffset + bodyStart);
                if (options.isLocIncluded) {
                    body.start = baseOffset + bodyStart;
                    body.end = baseOffset + bodyEnd;
                }
                return {
                    syntax: AdblockSyntax.Abp,
                    type: CosmeticRuleType.ScriptletInjectionRule,
                    body,
                };
            };
            const parseUboScriptletInjection = () => {
                if (!rawBody.startsWith(UBO_SCRIPTLET_MASK) && !rawBody.startsWith(UBO_SCRIPTLET_MASK_LEGACY)) {
                    return null;
                }
                if (!options.parseUboSpecificRules) {
                    throw new AdblockSyntaxError(sprintf.sprintf(ERROR_MESSAGES$3.SYNTAX_DISABLED, AdblockSyntax.Ubo), baseOffset + bodyStart, baseOffset + bodyEnd);
                }
                expectCommonOrSpecificSyntax(AdblockSyntax.Ubo);
                const body = UboScriptletInjectionBodyParser.parse(rawBody, options, baseOffset + bodyStart);
                if (options.isLocIncluded) {
                    body.start = baseOffset + bodyStart;
                    body.end = baseOffset + bodyEnd;
                }
                return {
                    syntax: AdblockSyntax.Ubo,
                    type: CosmeticRuleType.ScriptletInjectionRule,
                    body,
                };
            };
            const parseAdgScriptletInjection = () => {
                // ADG scriptlet injection
                if (!rawBody.startsWith(ADG_SCRIPTLET_MASK)) {
                    return null;
                }
                expectCommonOrSpecificSyntax(AdblockSyntax.Adg);
                const body = AdgScriptletInjectionBodyParser.parse(rawBody, options, baseOffset + bodyStart);
                if (options.isLocIncluded) {
                    body.start = baseOffset + bodyStart;
                    body.end = baseOffset + bodyEnd;
                }
                return {
                    syntax: AdblockSyntax.Adg,
                    type: CosmeticRuleType.ScriptletInjectionRule,
                    body,
                };
            };
            const parseAdgJsInjection = () => {
                expectCommonOrSpecificSyntax(AdblockSyntax.Adg);
                const body = {
                    type: 'Value',
                    value: rawBody,
                };
                if (options.isLocIncluded) {
                    body.start = baseOffset + bodyStart;
                    body.end = baseOffset + bodyEnd;
                }
                return {
                    syntax: AdblockSyntax.Adg,
                    type: CosmeticRuleType.JsInjectionRule,
                    body,
                };
            };
            const parseUboHtmlFiltering = () => {
                if (!rawBody.startsWith(UBO_HTML_MASK)) {
                    return null;
                }
                if (!options.parseUboSpecificRules) {
                    throw new AdblockSyntaxError(sprintf.sprintf(ERROR_MESSAGES$3.SYNTAX_DISABLED, AdblockSyntax.Ubo), baseOffset + bodyStart, baseOffset + bodyEnd);
                }
                expectCommonOrSpecificSyntax(AdblockSyntax.Ubo);
                const body = {
                    type: 'Value',
                    value: rawBody,
                };
                if (options.isLocIncluded) {
                    body.start = baseOffset + bodyStart;
                    body.end = baseOffset + bodyEnd;
                }
                return {
                    syntax: AdblockSyntax.Ubo,
                    type: CosmeticRuleType.HtmlFilteringRule,
                    body,
                };
            };
            const parseAdgHtmlFiltering = () => {
                expectCommonOrSpecificSyntax(AdblockSyntax.Adg);
                const body = {
                    type: 'Value',
                    value: rawBody,
                };
                if (options.isLocIncluded) {
                    body.start = baseOffset + bodyStart;
                    body.end = baseOffset + bodyEnd;
                }
                return {
                    syntax: AdblockSyntax.Adg,
                    type: CosmeticRuleType.HtmlFilteringRule,
                    body,
                };
            };
            // Create a fast lookup table for cosmetic rule separators and their parsing functions.
            // One separator can have multiple parsing functions. If the first function returns null,
            // the next function is called, and so on.
            // If all functions return null, an error should be thrown.
            const separatorMap = {
                '##': [parseUboHtmlFiltering, parseUboScriptletInjection, parseUboCssInjection, parseElementHiding],
                '#@#': [parseUboHtmlFiltering, parseUboScriptletInjection, parseUboCssInjection, parseElementHiding],
                '#?#': [parseUboCssInjection, parseElementHiding],
                '#@?#': [parseUboCssInjection, parseElementHiding],
                '#$#': [parseAdgCssInjection, parseAbpSnippetInjection],
                '#@$#': [parseAdgCssInjection, parseAbpSnippetInjection],
                '#$?#': [parseAdgCssInjection],
                '#@$?#': [parseAdgCssInjection],
                '#%#': [parseAdgScriptletInjection, parseAdgJsInjection],
                '#@%#': [parseAdgScriptletInjection, parseAdgJsInjection],
                $$: [parseAdgHtmlFiltering],
                '$@$': [parseAdgHtmlFiltering],
            };
            const parseFunctions = separatorMap[separatorResult.separator];
            let restProps;
            for (const parseFunction of parseFunctions) {
                restProps = parseFunction();
                if (restProps) {
                    break;
                }
            }
            // If none of the parsing functions returned a result, it means that the rule is unknown / invalid.
            if (!restProps) {
                throw new AdblockSyntaxError(sprintf.sprintf(ERROR_MESSAGES$3.INVALID_BODY_FOR_SEPARATOR, rawBody, separatorResult.separator), baseOffset + bodyStart, baseOffset + bodyEnd);
            }
            // Combine the base rule with the rest of the properties.
            return {
                ...baseRule,
                ...restProps,
            };
        }
        /**
         * Generates the rule pattern from the AST.
         *
         * @param node Cosmetic rule node
         * @returns Raw rule pattern
         * @example
         * - '##.foo' → ''
         * - 'example.com,example.org##.foo' → 'example.com,example.org'
         * - '[$path=/foo/bar]example.com##.foo' → '[$path=/foo/bar]example.com'
         */
        static generatePattern(node) {
            let result = EMPTY;
            // AdGuard modifiers (if any)
            if (node.syntax === AdblockSyntax.Adg && node.modifiers && node.modifiers.children.length > 0) {
                result += OPEN_SQUARE_BRACKET;
                result += DOLLAR_SIGN;
                result += ModifierListParser.generate(node.modifiers);
                result += CLOSE_SQUARE_BRACKET;
            }
            // Domain list (if any)
            result += DomainListParser.generate(node.domains);
            return result;
        }
        /**
         * Generates the rule body from the node.
         *
         * @param node Cosmetic rule node
         * @returns Raw rule body
         * @example
         * - '##.foo' → '.foo'
         * - 'example.com,example.org##.foo' → '.foo'
         * - 'example.com#%#//scriptlet('foo')' → '//scriptlet('foo')'
         */
        static generateBody(node) {
            let result = EMPTY;
            // Body
            switch (node.type) {
                case CosmeticRuleType.ElementHidingRule:
                    result = node.body.selectorList.value;
                    break;
                case CosmeticRuleType.CssInjectionRule:
                    if (node.syntax === AdblockSyntax.Adg) {
                        result = AdgCssInjectionParser.generate(node.body);
                    }
                    else if (node.syntax === AdblockSyntax.Ubo) {
                        if (node.body.mediaQueryList) {
                            result += COLON;
                            result += UboPseudoName.MatchesMedia;
                            result += OPEN_PARENTHESIS;
                            result += node.body.mediaQueryList.value;
                            result += CLOSE_PARENTHESIS;
                            result += SPACE;
                        }
                        result += node.body.selectorList.value;
                        if (node.body.remove) {
                            result += COLON;
                            result += UboPseudoName.Remove;
                            result += OPEN_PARENTHESIS;
                            result += CLOSE_PARENTHESIS;
                        }
                        else if (node.body.declarationList) {
                            result += COLON;
                            result += UboPseudoName.Style;
                            result += OPEN_PARENTHESIS;
                            result += node.body.declarationList.value;
                            result += CLOSE_PARENTHESIS;
                        }
                    }
                    break;
                case CosmeticRuleType.HtmlFilteringRule:
                case CosmeticRuleType.JsInjectionRule:
                    result = node.body.value;
                    break;
                case CosmeticRuleType.ScriptletInjectionRule:
                    switch (node.syntax) {
                        case AdblockSyntax.Adg:
                            result = AdgScriptletInjectionBodyParser.generate(node.body);
                            break;
                        case AdblockSyntax.Abp:
                            result = AbpSnippetInjectionBodyParser.generate(node.body);
                            break;
                        case AdblockSyntax.Ubo:
                            result = UboScriptletInjectionBodyParser.generate(node.body);
                            break;
                        default:
                            throw new Error('Scriptlet rule should have an explicit syntax');
                    }
                    break;
                default:
                    throw new Error('Unknown cosmetic rule type');
            }
            return result;
        }
        /**
         * Converts a cosmetic rule AST into a string.
         *
         * @param node Cosmetic rule AST
         * @returns Raw string
         */
        static generate(node) {
            let result = EMPTY;
            // Pattern
            result += CosmeticRuleParser.generatePattern(node);
            // Separator
            result += node.separator.value;
            // uBO rule modifiers
            if (node.syntax === AdblockSyntax.Ubo && node.modifiers) {
                node.modifiers.children.forEach((modifier) => {
                    result += COLON;
                    result += modifier.name.value;
                    if (modifier.value) {
                        result += OPEN_PARENTHESIS;
                        result += modifier.value.value;
                        result += CLOSE_PARENTHESIS;
                    }
                });
                // If there are at least one modifier, add a space
                if (node.modifiers.children.length) {
                    result += SPACE;
                }
            }
            // Body
            result += CosmeticRuleParser.generateBody(node);
            return result;
        }
        /**
         * Serializes an element hiding rule body node to binary format.
         *
         * @param node Node to serialize.
         * @param buffer ByteBuffer for writing binary data.
         */
        static serializeElementHidingBody(node, buffer) {
            buffer.writeUint8(BinaryTypeMap.ElementHidingRuleBody);
            buffer.writeUint8(ElementHidingRuleSerializationMap.SelectorList);
            ValueParser.serialize(node.selectorList, buffer);
            if (!isUndefined$1(node.start)) {
                buffer.writeUint8(ElementHidingRuleSerializationMap.Start);
                buffer.writeUint32(node.start);
            }
            if (!isUndefined$1(node.end)) {
                buffer.writeUint8(ElementHidingRuleSerializationMap.End);
                buffer.writeUint32(node.end);
            }
            buffer.writeUint8(NULL);
        }
        /**
         * Deserializes an element hiding rule body node from binary format.
         *
         * @param buffer ByteBuffer for reading binary data.
         * @param node Destination node.
         */
        static deserializeElementHidingBody(buffer, node) {
            buffer.assertUint8(BinaryTypeMap.ElementHidingRuleBody);
            node.type = 'ElementHidingRuleBody';
            let prop = buffer.readUint8();
            while (prop !== NULL) {
                switch (prop) {
                    case ElementHidingRuleSerializationMap.SelectorList:
                        ValueParser.deserialize(buffer, node.selectorList = {});
                        break;
                    case ElementHidingRuleSerializationMap.Start:
                        node.start = buffer.readUint32();
                        break;
                    case ElementHidingRuleSerializationMap.End:
                        node.end = buffer.readUint32();
                        break;
                    default:
                        throw new Error(`Unknown property: ${prop}`);
                }
                prop = buffer.readUint8();
            }
        }
        /**
         * Serializes a CSS injection rule body node to binary format.
         *
         * @param node Node to serialize.
         * @param buffer ByteBuffer for writing binary data.
         */
        static serializeCssInjectionBody(node, buffer) {
            buffer.writeUint8(BinaryTypeMap.CssInjectionRuleBody);
            if (node.mediaQueryList) {
                buffer.writeUint8(CssInjectionRuleSerializationMap.MediaQueryList);
                ValueParser.serialize(node.mediaQueryList, buffer);
            }
            buffer.writeUint8(CssInjectionRuleSerializationMap.SelectorList);
            ValueParser.serialize(node.selectorList, buffer);
            if (node.declarationList) {
                buffer.writeUint8(CssInjectionRuleSerializationMap.DeclarationList);
                ValueParser.serialize(node.declarationList, buffer);
            }
            if (node.remove) {
                buffer.writeUint8(CssInjectionRuleSerializationMap.Remove);
            }
            if (!isUndefined$1(node.start)) {
                buffer.writeUint8(CssInjectionRuleSerializationMap.Start);
                buffer.writeUint32(node.start);
            }
            if (!isUndefined$1(node.end)) {
                buffer.writeUint8(CssInjectionRuleSerializationMap.End);
                buffer.writeUint32(node.end);
            }
            buffer.writeUint8(NULL);
        }
        /**
         * Deserializes CSS injection rule body node from binary format.
         *
         * @param buffer ByteBuffer for reading binary data.
         * @param node Destination node.
         */
        static deserializeCssInjectionBody(buffer, node) {
            buffer.assertUint8(BinaryTypeMap.CssInjectionRuleBody);
            node.type = 'CssInjectionRuleBody';
            node.remove = false;
            let prop = buffer.readUint8();
            while (prop !== NULL) {
                switch (prop) {
                    case CssInjectionRuleSerializationMap.MediaQueryList:
                        ValueParser.deserialize(buffer, node.mediaQueryList = {});
                        break;
                    case CssInjectionRuleSerializationMap.SelectorList:
                        ValueParser.deserialize(buffer, node.selectorList = {});
                        break;
                    case CssInjectionRuleSerializationMap.DeclarationList:
                        ValueParser.deserialize(buffer, node.declarationList = {});
                        break;
                    case CssInjectionRuleSerializationMap.Remove:
                        node.remove = true;
                        break;
                    case CssInjectionRuleSerializationMap.Start:
                        node.start = buffer.readUint32();
                        break;
                    case CssInjectionRuleSerializationMap.End:
                        node.end = buffer.readUint32();
                        break;
                    default:
                        throw new Error(`Unknown property: ${prop}`);
                }
                prop = buffer.readUint8();
            }
        }
        /**
         * Serializes a cosmetic rule node to binary format.
         *
         * @param node Node to serialize.
         * @param buffer ByteBuffer for writing binary data.
         */
        // TODO: add support for raws, if ever needed
        static serialize(node, buffer) {
            // specific properties
            switch (node.type) {
                case CosmeticRuleType.ElementHidingRule:
                    // rule type
                    buffer.writeUint8(BinaryTypeMap.ElementHidingRule);
                    // syntax
                    buffer.writeUint8(SYNTAX_SERIALIZATION_MAP.get(node.syntax) ?? 0);
                    // rule body
                    CosmeticRuleParser.serializeElementHidingBody(node.body, buffer);
                    break;
                case CosmeticRuleType.CssInjectionRule:
                    // rule type
                    buffer.writeUint8(BinaryTypeMap.CssInjectionRule);
                    // syntax
                    buffer.writeUint8(SYNTAX_SERIALIZATION_MAP.get(node.syntax) ?? 0);
                    // rule body
                    CosmeticRuleParser.serializeCssInjectionBody(node.body, buffer);
                    break;
                case CosmeticRuleType.JsInjectionRule:
                    // rule type
                    buffer.writeUint8(BinaryTypeMap.JsInjectionRule);
                    // syntax
                    buffer.writeUint8(SYNTAX_SERIALIZATION_MAP.get(node.syntax) ?? 0);
                    // rule body
                    ValueParser.serialize(node.body, buffer);
                    break;
                case CosmeticRuleType.HtmlFilteringRule:
                    // rule type
                    buffer.writeUint8(BinaryTypeMap.HtmlFilteringRule);
                    // syntax
                    buffer.writeUint8(SYNTAX_SERIALIZATION_MAP.get(node.syntax) ?? 0);
                    // rule body
                    ValueParser.serialize(node.body, buffer);
                    break;
                case CosmeticRuleType.ScriptletInjectionRule:
                    // rule type
                    buffer.writeUint8(BinaryTypeMap.ScriptletInjectionRule);
                    // syntax
                    buffer.writeUint8(SYNTAX_SERIALIZATION_MAP.get(node.syntax) ?? 0);
                    // rule body
                    switch (node.syntax) {
                        case AdblockSyntax.Adg:
                            AdgScriptletInjectionBodyParser.serialize(node.body, buffer);
                            break;
                        case AdblockSyntax.Abp:
                            AbpSnippetInjectionBodyParser.serialize(node.body, buffer);
                            break;
                        case AdblockSyntax.Ubo:
                            UboScriptletInjectionBodyParser.serialize(node.body, buffer);
                            break;
                        default:
                            throw new Error('Scriptlet rule should have an explicit syntax');
                    }
                    break;
                default:
                    throw new Error('Unknown cosmetic rule type');
            }
            // common properties
            buffer.writeUint8(CosmeticRuleSerializationMap.Exception);
            buffer.writeUint8(node.exception ? 1 : 0);
            buffer.writeUint8(CosmeticRuleSerializationMap.Separator);
            ValueParser.serialize(node.separator, buffer, SEPARATOR_SERIALIZATION_MAP);
            if (node.modifiers) {
                buffer.writeUint8(CosmeticRuleSerializationMap.Modifiers);
                ModifierListParser.serialize(node.modifiers, buffer);
            }
            buffer.writeUint8(CosmeticRuleSerializationMap.Domains);
            DomainListParser.serialize(node.domains, buffer);
            if (!isUndefined$1(node.start)) {
                buffer.writeUint8(CosmeticRuleSerializationMap.Start);
                buffer.writeUint32(node.start);
            }
            if (!isUndefined$1(node.end)) {
                buffer.writeUint8(CosmeticRuleSerializationMap.End);
                buffer.writeUint32(node.end);
            }
            buffer.writeUint8(NULL);
        }
        /**
         * Deserializes a cosmetic rule node from binary format.
         *
         * @param buffer ByteBuffer for reading binary data.
         * @param node Destination node.
         */
        static deserialize(buffer, node) {
            const type = COSMETIC_RULE_TYPE_DESERIALIZATION_MAP.get(buffer.readUint8());
            if (isUndefined$1(type)) {
                throw new Error(`Unknown rule type: ${type}`);
            }
            node.type = type;
            node.category = RuleCategory.Cosmetic;
            const syntax = SYNTAX_DESERIALIZATION_MAP.get(buffer.readUint8()) ?? AdblockSyntax.Common;
            node.syntax = syntax;
            node.modifiers = undefined;
            switch (type) {
                case CosmeticRuleType.ElementHidingRule:
                    CosmeticRuleParser.deserializeElementHidingBody(buffer, node.body = {});
                    break;
                case CosmeticRuleType.CssInjectionRule:
                    CosmeticRuleParser.deserializeCssInjectionBody(buffer, node.body = {});
                    break;
                case CosmeticRuleType.JsInjectionRule:
                    ValueParser.deserialize(buffer, node.body = {});
                    break;
                case CosmeticRuleType.HtmlFilteringRule:
                    ValueParser.deserialize(buffer, node.body = {});
                    break;
                case CosmeticRuleType.ScriptletInjectionRule:
                    switch (syntax) {
                        case AdblockSyntax.Adg:
                            // eslint-disable-next-line max-len
                            AdgScriptletInjectionBodyParser.deserialize(buffer, node.body = {});
                            break;
                        case AdblockSyntax.Abp:
                            AbpSnippetInjectionBodyParser.deserialize(buffer, node.body = {});
                            break;
                        case AdblockSyntax.Ubo:
                            // eslint-disable-next-line max-len
                            UboScriptletInjectionBodyParser.deserialize(buffer, node.body = {});
                            break;
                        default:
                            throw new Error('Scriptlet rule should have an explicit syntax');
                    }
                    break;
                default:
                    throw new Error('Unknown cosmetic rule type');
            }
            let prop = buffer.readUint8();
            while (prop !== NULL) {
                switch (prop) {
                    case CosmeticRuleSerializationMap.Exception:
                        node.exception = buffer.readUint8() === 1;
                        break;
                    case CosmeticRuleSerializationMap.Separator:
                        ValueParser.deserialize(buffer, node.separator = {}, SEPARATOR_DESERIALIZATION_MAP);
                        break;
                    case CosmeticRuleSerializationMap.Modifiers:
                        node.modifiers = {};
                        ModifierListParser.deserialize(buffer, node.modifiers);
                        break;
                    case CosmeticRuleSerializationMap.Domains:
                        DomainListParser.deserialize(buffer, node.domains = {});
                        break;
                    case CosmeticRuleSerializationMap.Start:
                        node.start = buffer.readUint32();
                        break;
                    case CosmeticRuleSerializationMap.End:
                        node.end = buffer.readUint32();
                        break;
                    default:
                        throw new Error(`Unknown property: ${prop}`);
                }
                prop = buffer.readUint8();
            }
        }
    }

    /* eslint-disable no-param-reassign */
    /**
     * Property map for binary serialization. This helps to reduce the size of the serialized data,
     * as it allows us to use a single byte to represent a property.
     *
     * ! IMPORTANT: If you change values here, please update the {@link BINARY_SCHEMA_VERSION}!
     *
     * @note Only 256 values can be represented this way.
     */
    var NetworkRuleSerializationMap;
    (function (NetworkRuleSerializationMap) {
        NetworkRuleSerializationMap[NetworkRuleSerializationMap["Syntax"] = 1] = "Syntax";
        NetworkRuleSerializationMap[NetworkRuleSerializationMap["Raws"] = 2] = "Raws";
        NetworkRuleSerializationMap[NetworkRuleSerializationMap["Exception"] = 3] = "Exception";
        NetworkRuleSerializationMap[NetworkRuleSerializationMap["Pattern"] = 4] = "Pattern";
        NetworkRuleSerializationMap[NetworkRuleSerializationMap["ModifierList"] = 5] = "ModifierList";
        NetworkRuleSerializationMap[NetworkRuleSerializationMap["Start"] = 6] = "Start";
        NetworkRuleSerializationMap[NetworkRuleSerializationMap["End"] = 7] = "End";
    })(NetworkRuleSerializationMap || (NetworkRuleSerializationMap = {}));
    /**
     * `NetworkRuleParser` is responsible for parsing network rules.
     *
     * Please note that this will parse all syntactically correct network rules.
     * Modifier compatibility is not checked at the parser level.
     *
     * @see {@link https://kb.adguard.com/en/general/how-to-create-your-own-ad-filters#basic-rules}
     * @see {@link https://help.eyeo.com/adblockplus/how-to-write-filters#basic}
     */
    class NetworkRuleParser extends ParserBase {
        /**
         * Parses a network rule (also known as basic rule).
         *
         * @param raw Raw input to parse.
         * @param options Global parser options.
         * @param baseOffset Starting offset of the input. Node locations are calculated relative to this offset.
         * @returns Network rule AST
         *
         * @throws If the rule is syntactically incorrect.
         */
        static parse(raw, options = defaultParserOptions, baseOffset = 0) {
            let offset = 0;
            // Skip leading whitespace
            offset = StringUtils.skipWS(raw, offset);
            // Handle exception rules
            let exception = false;
            // Rule starts with exception marker, eg @@||example.com,
            // where @@ is the exception marker
            if (raw.startsWith(NETWORK_RULE_EXCEPTION_MARKER, offset)) {
                offset += NETWORK_RULE_EXCEPTION_MARKER_LEN;
                exception = true;
            }
            // Save the start of the pattern
            const patternStart = offset;
            // Find corresponding (last) separator ($) character (if any)
            const separatorIndex = NetworkRuleParser.findNetworkRuleSeparatorIndex(raw);
            // Save the end of the pattern
            const patternEnd = separatorIndex === -1
                ? StringUtils.skipWSBack(raw) + 1
                : StringUtils.skipWSBack(raw, separatorIndex - 1) + 1;
            // Parse pattern
            const pattern = ValueParser.parse(raw.slice(patternStart, patternEnd), options, baseOffset + patternStart);
            // Parse modifiers (if any)
            let modifiers;
            // Find start and end index of the modifiers
            const modifiersStart = separatorIndex + 1;
            const modifiersEnd = StringUtils.skipWSBack(raw) + 1;
            if (separatorIndex !== -1) {
                modifiers = ModifierListParser.parse(raw.slice(modifiersStart, modifiersEnd), options, baseOffset + modifiersStart);
            }
            // Throw error if there is no pattern and no modifiers
            if (pattern.value.length === 0 && (modifiers === undefined || modifiers.children.length === 0)) {
                throw new AdblockSyntaxError('Network rule must have a pattern or modifiers', baseOffset, baseOffset + raw.length);
            }
            const result = {
                type: NetworkRuleType.NetworkRule,
                category: RuleCategory.Network,
                syntax: AdblockSyntax.Common,
                exception,
                pattern,
                modifiers,
            };
            if (options.includeRaws) {
                result.raws = {
                    text: raw,
                };
            }
            if (options.isLocIncluded) {
                result.start = baseOffset;
                result.end = baseOffset + raw.length;
            }
            return result;
        }
        /**
         * Finds the index of the separator character in a network rule.
         *
         * @param rule Network rule to check
         * @returns The index of the separator character, or -1 if there is no separator
         */
        static findNetworkRuleSeparatorIndex(rule) {
            // As we are looking for the last separator, we start from the end of the string
            for (let i = rule.length - 1; i >= 0; i -= 1) {
                // If we find a potential separator, we should check
                // - if it's not escaped
                // - if it's not followed by a regex marker, for example: `example.org^$removeparam=/regex$/`
                // eslint-disable-next-line max-len
                if (rule[i] === NETWORK_RULE_SEPARATOR && rule[i + 1] !== REGEX_MARKER && rule[i - 1] !== ESCAPE_CHARACTER) {
                    return i;
                }
            }
            return -1;
        }
        /**
         * Converts a network rule (basic rule) AST to a string.
         *
         * @param node Network rule node
         * @returns Raw string
         */
        static generate(node) {
            let result = EMPTY;
            // If the rule is an exception, add the exception marker: `@@||example.org`
            if (node.exception) {
                result += NETWORK_RULE_EXCEPTION_MARKER;
            }
            // Add the pattern: `||example.org`
            result += node.pattern.value;
            // If there are modifiers, add a separator and the modifiers: `||example.org$important`
            if (node.modifiers && node.modifiers.children.length > 0) {
                result += NETWORK_RULE_SEPARATOR;
                result += ModifierListParser.generate(node.modifiers);
            }
            return result;
        }
        /**
         * Serializes a network rule node to binary format.
         *
         * @param node Node to serialize.
         * @param buffer ByteBuffer for writing binary data.
         */
        // TODO: add support for raws, if ever needed
        static serialize(node, buffer) {
            buffer.writeUint8(BinaryTypeMap.NetworkRuleNode);
            buffer.writeUint8(NetworkRuleSerializationMap.Syntax);
            buffer.writeUint8(SYNTAX_SERIALIZATION_MAP.get(node.syntax) ?? 0);
            buffer.writeUint8(NetworkRuleSerializationMap.Exception);
            buffer.writeUint8(node.exception ? 1 : 0);
            buffer.writeUint8(NetworkRuleSerializationMap.Pattern);
            ValueParser.serialize(node.pattern, buffer);
            if (!isUndefined$1(node.modifiers)) {
                buffer.writeUint8(NetworkRuleSerializationMap.ModifierList);
                ModifierListParser.serialize(node.modifiers, buffer);
            }
            if (!isUndefined$1(node.start)) {
                buffer.writeUint8(NetworkRuleSerializationMap.Start);
                buffer.writeUint32(node.start);
            }
            if (!isUndefined$1(node.end)) {
                buffer.writeUint8(NetworkRuleSerializationMap.End);
                buffer.writeUint32(node.end);
            }
            buffer.writeUint8(NULL);
        }
        /**
         * Deserializes a modifier node from binary format.
         *
         * @param buffer ByteBuffer for reading binary data.
         * @param node Destination node.
         */
        static deserialize(buffer, node) {
            buffer.assertUint8(BinaryTypeMap.NetworkRuleNode);
            node.type = NetworkRuleType.NetworkRule;
            node.category = RuleCategory.Network;
            node.modifiers = undefined;
            let prop = buffer.readUint8();
            while (prop !== NULL) {
                switch (prop) {
                    case NetworkRuleSerializationMap.Syntax:
                        node.syntax = SYNTAX_DESERIALIZATION_MAP.get(buffer.readUint8()) ?? AdblockSyntax.Common;
                        break;
                    case NetworkRuleSerializationMap.Exception:
                        node.exception = buffer.readUint8() === 1;
                        break;
                    case NetworkRuleSerializationMap.Pattern:
                        ValueParser.deserialize(buffer, node.pattern = {});
                        break;
                    case NetworkRuleSerializationMap.ModifierList:
                        ModifierListParser.deserialize(buffer, node.modifiers = {});
                        break;
                    case NetworkRuleSerializationMap.Start:
                        node.start = buffer.readUint32();
                        break;
                    case NetworkRuleSerializationMap.End:
                        node.end = buffer.readUint32();
                        break;
                    default:
                        throw new Error(`Invalid property: ${prop}.`);
                }
                prop = buffer.readUint8();
            }
        }
    }

    /* eslint-disable no-param-reassign */
    /**
     * Property map for binary serialization. This helps to reduce the size of the serialized data,
     * as it allows us to use a single byte to represent a property.
     *
     * ! IMPORTANT: If you change values here, please update the {@link BINARY_SCHEMA_VERSION}!
     *
     * @note Only 256 values can be represented this way.
     */
    var HostRuleSerializationMap;
    (function (HostRuleSerializationMap) {
        HostRuleSerializationMap[HostRuleSerializationMap["Syntax"] = 1] = "Syntax";
        HostRuleSerializationMap[HostRuleSerializationMap["Raws"] = 2] = "Raws";
        HostRuleSerializationMap[HostRuleSerializationMap["Ip"] = 3] = "Ip";
        HostRuleSerializationMap[HostRuleSerializationMap["HostnameList"] = 4] = "HostnameList";
        HostRuleSerializationMap[HostRuleSerializationMap["Comment"] = 5] = "Comment";
        HostRuleSerializationMap[HostRuleSerializationMap["Start"] = 6] = "Start";
        HostRuleSerializationMap[HostRuleSerializationMap["End"] = 7] = "End";
    })(HostRuleSerializationMap || (HostRuleSerializationMap = {}));
    /**
     * Property map for binary serialization. This helps to reduce the size of the serialized data,
     * as it allows us to use a single byte to represent a property.
     *
     * ! IMPORTANT: If you change values here, please update the {@link BINARY_SCHEMA_VERSION}!
     *
     * @note Only 256 values can be represented this way.
     */
    var HostnameListNodeSerializationMap;
    (function (HostnameListNodeSerializationMap) {
        HostnameListNodeSerializationMap[HostnameListNodeSerializationMap["Children"] = 1] = "Children";
        HostnameListNodeSerializationMap[HostnameListNodeSerializationMap["Start"] = 2] = "Start";
        HostnameListNodeSerializationMap[HostnameListNodeSerializationMap["End"] = 3] = "End";
    })(HostnameListNodeSerializationMap || (HostnameListNodeSerializationMap = {}));
    /**
     * `HostRuleParser` is responsible for parsing hosts-like rules.
     *
     * HostRule is a structure for simple host-level rules (i.e. /etc/hosts syntax).
     * It also supports "just domain" syntax. In this case, the IP will be set to 0.0.0.0.
     *
     * Rules syntax looks like this:
     * ```text
     * IP_address canonical_hostname [aliases...]
     * ```
     *
     * @example
     * `192.168.1.13 bar.mydomain.org bar` -- ipv4
     * `ff02::1 ip6-allnodes` -- ipv6
     * `::1 localhost ip6-localhost ip6-loopback` -- ipv6 aliases
     * `example.org` -- "just domain" syntax
     * @see {@link http://man7.org/linux/man-pages/man5/hosts.5.html}
     */
    class HostRuleParser extends ParserBase {
        static NULL_IP = '0.0.0.0';
        static COMMENT_MARKER = '#';
        /**
         * Parses an etc/hosts-like rule.
         *
         * @param raw Raw input to parse.
         * @param options Global parser options.
         * @param baseOffset Starting offset of the input. Node locations are calculated relative to this offset.
         * @returns Host rule node.
         *
         * @throws If the input contains invalid data.
         */
        static parse(raw, options = defaultParserOptions, baseOffset = 0) {
            let offset = StringUtils.skipWS(raw, 0);
            const parts = [];
            let lastPartStartIndex = offset;
            let comment = null;
            const rawLength = raw.length;
            const parsePartIfNeeded = (startIndex, endIndex) => {
                if (startIndex < endIndex) {
                    parts.push(ValueParser.parse(raw.slice(startIndex, endIndex), options, baseOffset + startIndex));
                }
            };
            while (offset < rawLength) {
                if (StringUtils.isWhitespace(raw[offset])) {
                    parsePartIfNeeded(lastPartStartIndex, offset);
                    offset = StringUtils.skipWS(raw, offset);
                    lastPartStartIndex = offset;
                }
                else if (raw[offset] === HostRuleParser.COMMENT_MARKER) {
                    const commentStart = offset;
                    offset = StringUtils.skipWS(raw, offset + 1);
                    comment = ValueParser.parse(raw.slice(offset), options, baseOffset + commentStart);
                    offset = rawLength;
                    lastPartStartIndex = offset;
                }
                else {
                    offset += 1;
                }
            }
            parsePartIfNeeded(lastPartStartIndex, offset);
            const partsLength = parts.length;
            if (partsLength < 1) {
                throw new Error('Host rule must have at least one domain name or an IP address and a domain name');
            }
            const result = {
                category: RuleCategory.Network,
                type: NetworkRuleType.HostRule,
                syntax: AdblockSyntax.Common,
            };
            if (partsLength === 1) {
                // "Just domain" syntax, e.g. `example.org`
                // In this case, domain should be valid and IP will be set to 0.0.0.0 by default
                if (getDomain(parts[0].value) !== parts[0].value) {
                    throw new Error(`Not a valid domain: ${parts[0].value}`);
                }
                result.ip = {
                    type: 'Value',
                    value: HostRuleParser.NULL_IP,
                };
                result.hostnames = {
                    type: 'HostnameList',
                    children: parts,
                };
            }
            else if (partsLength > 1) {
                // IP + domain list syntax
                const [ip, ...hostnames] = parts;
                if (!isIp$1(ip.value)) {
                    throw new Error(`Invalid IP address: ${ip.value}`);
                }
                for (const { value } of hostnames) {
                    if (getHostname(value) !== value) {
                        throw new Error(`Not a valid hostname: ${value}`);
                    }
                }
                result.ip = ip;
                result.hostnames = {
                    type: 'HostnameList',
                    children: hostnames,
                };
            }
            if (comment) {
                result.comment = comment;
            }
            if (options.includeRaws) {
                result.raws = {
                    text: raw,
                };
            }
            return result;
        }
        /**
         * Converts a host rule node to a raw string.
         *
         * @param node Host rule node.
         * @returns Raw string.
         */
        static generate(node) {
            const result = [];
            if (node.ip) {
                result.push(node.ip.value);
            }
            if (node.hostnames) {
                result.push(SPACE);
                result.push(node.hostnames.children.map(({ value }) => value).join(SPACE));
            }
            if (node.comment) {
                result.push(SPACE);
                result.push(HostRuleParser.COMMENT_MARKER);
                result.push(SPACE);
                result.push(node.comment.value);
            }
            return result.join(EMPTY);
        }
        /**
         * Serializes a hostname list node to binary format.
         *
         * @param node Node to serialize.
         * @param buffer ByteBuffer for writing binary data.
         */
        static serializeHostnameList(node, buffer) {
            buffer.writeUint8(BinaryTypeMap.HostnameListNode);
            if (!isUndefined$1(node.start)) {
                buffer.writeUint8(HostnameListNodeSerializationMap.Start);
                buffer.writeUint32(node.start);
            }
            if (!isUndefined$1(node.end)) {
                buffer.writeUint8(HostnameListNodeSerializationMap.End);
                buffer.writeUint32(node.end);
            }
            const count = node.children.length;
            if (count) {
                // note: we store the count, because re-construction of the array is faster if we know the length
                if (count > UINT16_MAX) {
                    throw new Error(`Too many children: ${count}, the limit is ${UINT16_MAX}`);
                }
                buffer.writeUint8(HostnameListNodeSerializationMap.Children);
                buffer.writeUint16(count);
                for (let i = 0; i < count; i += 1) {
                    ValueParser.serialize(node.children[i], buffer);
                }
            }
            buffer.writeUint8(NULL);
        }
        /**
         * Deserializes a hostname list node from binary format.
         *
         * @param buffer ByteBuffer for reading binary data.
         * @param node Destination node.
         */
        static deserializeHostnameList(buffer, node) {
            buffer.assertUint8(BinaryTypeMap.HostnameListNode);
            node.type = 'HostnameList';
            let prop = buffer.readUint8();
            while (prop !== NULL) {
                switch (prop) {
                    case HostnameListNodeSerializationMap.Children:
                        node.children = new Array(buffer.readUint16());
                        // read children
                        for (let i = 0; i < node.children.length; i += 1) {
                            ValueParser.deserialize(buffer, node.children[i] = {});
                        }
                        break;
                    case HostnameListNodeSerializationMap.Start:
                        node.start = buffer.readUint32();
                        break;
                    case HostnameListNodeSerializationMap.End:
                        node.end = buffer.readUint32();
                        break;
                    default:
                        throw new Error(`Unknown property: ${prop}`);
                }
                prop = buffer.readUint8();
            }
        }
        /**
         * Serializes a host rule node to binary format.
         *
         * @param node Node to serialize.
         * @param buffer ByteBuffer for writing binary data.
         */
        // TODO: add support for raws, if ever needed
        static serialize(node, buffer) {
            buffer.writeUint8(BinaryTypeMap.HostRuleNode);
            buffer.writeUint8(HostRuleSerializationMap.Syntax);
            buffer.writeUint8(SYNTAX_SERIALIZATION_MAP.get(node.syntax) ?? 0);
            if (node.ip) {
                buffer.writeUint8(HostRuleSerializationMap.Ip);
                ValueParser.serialize(node.ip, buffer);
            }
            if (node.hostnames) {
                buffer.writeUint8(HostRuleSerializationMap.HostnameList);
                HostRuleParser.serializeHostnameList(node.hostnames, buffer);
            }
            if (node.comment) {
                buffer.writeUint8(HostRuleSerializationMap.Comment);
                ValueParser.serialize(node.comment, buffer);
            }
            if (!isUndefined$1(node.start)) {
                buffer.writeUint8(HostRuleSerializationMap.Start);
                buffer.writeUint32(node.start);
            }
            if (!isUndefined$1(node.end)) {
                buffer.writeUint8(HostRuleSerializationMap.End);
                buffer.writeUint32(node.end);
            }
            buffer.writeUint8(NULL);
        }
        /**
         * Deserializes a modifier node from binary format.
         *
         * @param buffer ByteBuffer for reading binary data.
         * @param node Destination node.
         */
        static deserialize(buffer, node) {
            buffer.assertUint8(BinaryTypeMap.HostRuleNode);
            node.category = RuleCategory.Network;
            node.type = NetworkRuleType.HostRule;
            let prop = buffer.readUint8();
            while (prop !== NULL) {
                switch (prop) {
                    case HostRuleSerializationMap.Syntax:
                        node.syntax = SYNTAX_DESERIALIZATION_MAP.get(buffer.readUint8()) ?? AdblockSyntax.Common;
                        break;
                    case HostRuleSerializationMap.Ip:
                        node.ip = {};
                        ValueParser.deserialize(buffer, node.ip);
                        break;
                    case HostRuleSerializationMap.HostnameList:
                        node.hostnames = {};
                        HostRuleParser.deserializeHostnameList(buffer, node.hostnames);
                        break;
                    case HostRuleSerializationMap.Comment:
                        node.comment = {};
                        ValueParser.deserialize(buffer, node.comment);
                        break;
                    case HostRuleSerializationMap.Start:
                        node.start = buffer.readUint32();
                        break;
                    case HostRuleSerializationMap.End:
                        node.end = buffer.readUint32();
                        break;
                    default:
                        throw new Error(`Invalid property: ${prop}.`);
                }
                prop = buffer.readUint8();
            }
        }
    }

    /* eslint-disable no-param-reassign */
    /**
     * Property map for binary serialization. This helps to reduce the size of the serialized data,
     * as it allows us to use a single byte to represent a property.
     *
     * ! IMPORTANT: If you change values here, please update the {@link BINARY_SCHEMA_VERSION}!
     *
     * @note Only 256 values can be represented this way.
     */
    var EmptyRuleSerializationMap;
    (function (EmptyRuleSerializationMap) {
        EmptyRuleSerializationMap[EmptyRuleSerializationMap["Start"] = 1] = "Start";
        EmptyRuleSerializationMap[EmptyRuleSerializationMap["End"] = 2] = "End";
    })(EmptyRuleSerializationMap || (EmptyRuleSerializationMap = {}));
    /**
     * Property map for binary serialization. This helps to reduce the size of the serialized data,
     * as it allows us to use a single byte to represent a property.
     *
     * ! IMPORTANT: If you change values here, please update the {@link BINARY_SCHEMA_VERSION}!
     *
     * @note Only 256 values can be represented this way.
     */
    var InvalidRuleErrorNodeSerializationMap;
    (function (InvalidRuleErrorNodeSerializationMap) {
        InvalidRuleErrorNodeSerializationMap[InvalidRuleErrorNodeSerializationMap["Name"] = 1] = "Name";
        InvalidRuleErrorNodeSerializationMap[InvalidRuleErrorNodeSerializationMap["Message"] = 2] = "Message";
        InvalidRuleErrorNodeSerializationMap[InvalidRuleErrorNodeSerializationMap["Start"] = 3] = "Start";
        InvalidRuleErrorNodeSerializationMap[InvalidRuleErrorNodeSerializationMap["End"] = 4] = "End";
    })(InvalidRuleErrorNodeSerializationMap || (InvalidRuleErrorNodeSerializationMap = {}));
    /**
     * Property map for binary serialization. This helps to reduce the size of the serialized data,
     * as it allows us to use a single byte to represent a property.
     *
     * ! IMPORTANT: If you change values here, please update the binary schema version.!
     *
     * @note Only 256 values can be represented this way.
     */
    var InvalidRuleSerializationMap;
    (function (InvalidRuleSerializationMap) {
        InvalidRuleSerializationMap[InvalidRuleSerializationMap["Error"] = 1] = "Error";
        InvalidRuleSerializationMap[InvalidRuleSerializationMap["Start"] = 2] = "Start";
        InvalidRuleSerializationMap[InvalidRuleSerializationMap["End"] = 3] = "End";
    })(InvalidRuleSerializationMap || (InvalidRuleSerializationMap = {}));
    /**
     * `RuleParser` is responsible for parsing the rules.
     *
     * It automatically determines the category and syntax of the rule, so you can pass any kind of rule to it.
     */
    class RuleParser extends ParserBase {
        /**
         * Helper method to parse host rules if the `parseHostRules` option is enabled, otherwise it will
         * parse network rules.
         *
         * @param raw Raw input to parse.
         * @param options Global parser options.
         * @param baseOffset Starting offset of the input. Node locations are calculated relative to this offset.
         * @returns Host rule or network rule node.
         */
        static parseHostOrNetworkRule(raw, options, baseOffset) {
            if (options.parseHostRules) {
                try {
                    return HostRuleParser.parse(raw, options, baseOffset);
                }
                catch (error) {
                    // Ignore the error, and fall back to network rule parser
                }
            }
            return NetworkRuleParser.parse(raw, options, baseOffset);
        }
        /**
         * Parse an adblock rule. You can pass any kind of rule to this method, since it will automatically determine
         * the category and syntax. If the rule is syntactically invalid, then an error will be thrown. If the
         * syntax / compatibility cannot be determined clearly, then the value of the `syntax` property will be
         * `Common`.
         *
         * For example, let's have this network rule:
         * ```adblock
         * ||example.org^$important
         * ```
         * The `syntax` property will be `Common`, since the rule is syntactically correct in every adblockers, but we
         * cannot determine at parsing level whether `important` is an existing option or not, nor if it exists, then
         * which adblocker supports it. This is why the `syntax` property is simply `Common` at this point.
         * The concrete COMPATIBILITY of the rule will be determined later, in a different, higher-level layer, called
         * "Compatibility table".
         *
         * But we can determinate the concrete syntax of this rule:
         * ```adblock
         * example.org#%#//scriptlet("scriptlet0", "arg0")
         * ```
         * since it is clearly an AdGuard-specific rule and no other adblockers uses this syntax natively. However, we also
         * cannot determine the COMPATIBILITY of this rule, as it is not clear at this point whether the `scriptlet0`
         * scriptlet is supported by AdGuard or not. This is also the task of the "Compatibility table". Here, we simply
         * mark the rule with the `AdGuard` syntax in this case.
         *
         * @param raw Raw input to parse.
         * @param options Global parser options.
         * @param baseOffset Starting offset of the input. Node locations are calculated relative to this offset.
         * @returns Adblock rule node
         * @throws If the input matches a pattern but syntactically invalid
         * @example
         * Take a look at the following example:
         * ```js
         * // Parse a network rule
         * const ast1 = RuleParser.parse("||example.org^$important");
         *
         * // Parse another network rule
         * const ast2 = RuleParser.parse("/ads.js^$important,third-party,domain=example.org|~example.com");
         *
         * // Parse a cosmetic rule
         * const ast2 = RuleParser.parse("example.org##.banner");
         *
         * // Parse another cosmetic rule
         * const ast3 = RuleParser.parse("example.org#?#.banner:-abp-has(.ad)");
         *
         * // Parse a comment rule
         * const ast4 = RuleParser.parse("! Comment");
         *
         * // Parse an empty rule
         * const ast5 = RuleParser.parse("");
         *
         * // Parse a comment rule (with metadata)
         * const ast6 = RuleParser.parse("! Title: Example");
         *
         * // Parse a pre-processor rule
         * const ast7 = RuleParser.parse("!#if (adguard)");
         * ```
         */
        static parse(raw, options = defaultParserOptions, baseOffset = 0) {
            try {
                // Empty lines / rules (handle it just for convenience)
                if (raw.trim().length === 0) {
                    const result = {
                        type: 'EmptyRule',
                        category: RuleCategory.Empty,
                        syntax: AdblockSyntax.Common,
                    };
                    if (options.includeRaws) {
                        result.raws = {
                            text: raw,
                        };
                    }
                    if (options.isLocIncluded) {
                        result.start = baseOffset;
                        result.end = baseOffset + raw.length;
                    }
                    return result;
                }
                // Try to parse the rule with all sub-parsers. If a rule doesn't match
                // the pattern of a parser, then it will return `null`. For example, a
                // network rule will not match the pattern of a comment rule, since it
                // doesn't start with comment marker. But if the rule matches the
                // pattern of a parser, then it will return the AST of the rule, or
                // throw an error if the rule is syntactically invalid.
                if (options.ignoreComments) {
                    if (CommentRuleParser.isCommentRule(raw)) {
                        const result = {
                            type: 'EmptyRule',
                            category: RuleCategory.Empty,
                            syntax: AdblockSyntax.Common,
                        };
                        if (options.includeRaws) {
                            result.raws = {
                                text: raw,
                            };
                        }
                        if (options.isLocIncluded) {
                            result.start = baseOffset;
                            result.end = baseOffset + raw.length;
                        }
                        return result;
                    }
                    return CosmeticRuleParser.parse(raw, options, baseOffset)
                        || RuleParser.parseHostOrNetworkRule(raw, options, baseOffset);
                }
                return CommentRuleParser.parse(raw, options, baseOffset)
                    || CosmeticRuleParser.parse(raw, options, baseOffset)
                    || RuleParser.parseHostOrNetworkRule(raw, options, baseOffset);
            }
            catch (error) {
                // If tolerant mode is disabled or the error is not known, then simply
                // re-throw the error
                if (!options.tolerant || !(error instanceof Error)) {
                    throw error;
                }
                const errorNode = {
                    type: 'InvalidRuleError',
                    name: error.name,
                    message: error.message,
                };
                // If the error is an AdblockSyntaxError, then we can add the
                // location of the error to the result
                if (error instanceof AdblockSyntaxError) {
                    errorNode.start = error.start;
                    errorNode.end = error.end;
                }
                // Otherwise, return an invalid rule (tolerant mode)
                const result = {
                    type: 'InvalidRule',
                    category: RuleCategory.Invalid,
                    syntax: AdblockSyntax.Common,
                    raw,
                    error: errorNode,
                };
                if (options.includeRaws) {
                    result.raws = {
                        text: raw,
                    };
                }
                if (options.isLocIncluded) {
                    result.start = baseOffset;
                    result.end = baseOffset + raw.length;
                }
                return result;
            }
        }
        /**
         * Converts a rule AST to a string.
         *
         * @param ast - Adblock rule AST
         * @returns Raw string
         * @example
         * Take a look at the following example:
         * ```js
         * // Parse the rule to the AST
         * const ast = RuleParser.parse("example.org##.banner");
         * // Generate the rule from the AST
         * const raw = RuleParser.generate(ast);
         * // Print the generated rule
         * console.log(raw); // "example.org##.banner"
         * ```
         */
        static generate(ast) {
            switch (ast.category) {
                // Empty lines
                case RuleCategory.Empty:
                    return EMPTY;
                // Invalid rules
                case RuleCategory.Invalid:
                    return ast.raw;
                // Comment rules
                case RuleCategory.Comment:
                    return CommentRuleParser.generate(ast);
                // Cosmetic / non-basic rules
                case RuleCategory.Cosmetic:
                    return CosmeticRuleParser.generate(ast);
                // Network / basic rules
                case RuleCategory.Network:
                    switch (ast.type) {
                        case NetworkRuleType.HostRule:
                            return HostRuleParser.generate(ast);
                        case NetworkRuleType.NetworkRule:
                            return NetworkRuleParser.generate(ast);
                        default:
                            throw new Error('Unknown network rule type');
                    }
                default:
                    throw new Error('Unknown rule category');
            }
        }
        /**
         * Serializes an empty rule node to binary format.
         *
         * @param node Node to serialize.
         * @param buffer ByteBuffer for writing binary data.
         */
        static serializeEmptyRule(node, buffer) {
            buffer.writeUint8(BinaryTypeMap.EmptyRule);
            if (!isUndefined$1(node.start)) {
                buffer.writeUint8(EmptyRuleSerializationMap.Start);
                buffer.writeUint32(node.start);
            }
            if (!isUndefined$1(node.end)) {
                buffer.writeUint8(EmptyRuleSerializationMap.End);
                buffer.writeUint32(node.end);
            }
            buffer.writeUint8(NULL);
        }
        /**
         * Deserializes an empty rule node from binary format.
         *
         * @param buffer ByteBuffer for reading binary data.
         * @param node Destination node.
         */
        static deserializeEmptyRule(buffer, node) {
            buffer.assertUint8(BinaryTypeMap.EmptyRule);
            node.type = 'EmptyRule';
            node.category = RuleCategory.Empty;
            node.syntax = AdblockSyntax.Common;
            let prop = buffer.readUint8();
            while (prop !== NULL) {
                switch (prop) {
                    case EmptyRuleSerializationMap.Start:
                        node.start = buffer.readUint32();
                        break;
                    case EmptyRuleSerializationMap.End:
                        node.end = buffer.readUint32();
                        break;
                    default:
                        throw new Error(`Invalid property: ${prop}.`);
                }
                prop = buffer.readUint8();
            }
        }
        /**
         * Serializes an invalid rule error node to binary format.
         *
         * @param node Node to serialize.
         * @param buffer ByteBuffer for writing binary data.
         */
        static serializeInvalidRuleErrorNode(node, buffer) {
            buffer.writeUint8(BinaryTypeMap.InvalidRuleErrorNode);
            buffer.writeUint8(InvalidRuleErrorNodeSerializationMap.Name);
            buffer.writeString(node.name);
            buffer.writeUint8(InvalidRuleErrorNodeSerializationMap.Message);
            buffer.writeString(node.message);
            if (!isUndefined$1(node.start)) {
                buffer.writeUint8(InvalidRuleErrorNodeSerializationMap.Start);
                buffer.writeUint32(node.start);
            }
            if (!isUndefined$1(node.end)) {
                buffer.writeUint8(InvalidRuleErrorNodeSerializationMap.End);
                buffer.writeUint32(node.end);
            }
            buffer.writeUint8(NULL);
        }
        /**
         * Deserializes an invalid rule error node from binary format.
         *
         * @param buffer ByteBuffer for reading binary data.
         * @param node Destination node.
         */
        static deserializeInvalidRuleErrorNode(buffer, node) {
            buffer.assertUint8(BinaryTypeMap.InvalidRuleErrorNode);
            node.type = 'InvalidRuleError';
            let prop = buffer.readUint8();
            while (prop !== NULL) {
                switch (prop) {
                    case InvalidRuleErrorNodeSerializationMap.Name:
                        node.name = buffer.readString();
                        break;
                    case InvalidRuleErrorNodeSerializationMap.Message:
                        node.message = buffer.readString();
                        break;
                    case InvalidRuleErrorNodeSerializationMap.Start:
                        node.start = buffer.readUint32();
                        break;
                    case InvalidRuleErrorNodeSerializationMap.End:
                        node.end = buffer.readUint32();
                        break;
                    default:
                        throw new Error(`Invalid property: ${prop}.`);
                }
                prop = buffer.readUint8();
            }
        }
        /**
         * Serializes an invalid rule node to binary format.
         *
         * @param node Node to serialize.
         * @param buffer ByteBuffer for writing binary data.
         */
        static serializeInvalidRule(node, buffer) {
            buffer.writeUint8(BinaryTypeMap.InvalidRule);
            buffer.writeUint8(InvalidRuleSerializationMap.Error);
            RuleParser.serializeInvalidRuleErrorNode(node.error, buffer);
            if (!isUndefined$1(node.start)) {
                buffer.writeUint8(InvalidRuleSerializationMap.Start);
                buffer.writeUint32(node.start);
            }
            if (!isUndefined$1(node.end)) {
                buffer.writeUint8(InvalidRuleSerializationMap.End);
                buffer.writeUint32(node.end);
            }
            buffer.writeUint8(NULL);
        }
        /**
         * Deserializes an invalid rule node from binary format.
         *
         * @param buffer ByteBuffer for reading binary data.
         * @param node Destination node.
         */
        static deserializeInvalidRule(buffer, node) {
            buffer.assertUint8(BinaryTypeMap.InvalidRule);
            node.type = 'InvalidRule';
            node.category = RuleCategory.Invalid;
            let prop = buffer.readUint8();
            while (prop !== NULL) {
                switch (prop) {
                    case InvalidRuleSerializationMap.Error:
                        RuleParser.deserializeInvalidRuleErrorNode(buffer, node.error = {});
                        break;
                    case InvalidRuleSerializationMap.Start:
                        node.start = buffer.readUint32();
                        break;
                    case InvalidRuleSerializationMap.End:
                        node.end = buffer.readUint32();
                        break;
                    default:
                        throw new Error(`Invalid property: ${prop}.`);
                }
                prop = buffer.readUint8();
            }
        }
        /**
         * Serializes a rule node to binary format.
         *
         * @param node Node to serialize.
         * @param buffer ByteBuffer for writing binary data.
         */
        // TODO: add support for raws, if ever needed
        static serialize(node, buffer) {
            switch (node.category) {
                case RuleCategory.Comment:
                    CommentRuleParser.serialize(node, buffer);
                    break;
                case RuleCategory.Cosmetic:
                    CosmeticRuleParser.serialize(node, buffer);
                    break;
                case RuleCategory.Network:
                    switch (node.type) {
                        case NetworkRuleType.HostRule:
                            HostRuleParser.serialize(node, buffer);
                            break;
                        case NetworkRuleType.NetworkRule:
                            NetworkRuleParser.serialize(node, buffer);
                            break;
                        default:
                            throw new Error('Unknown network rule type');
                    }
                    break;
                case RuleCategory.Empty:
                    RuleParser.serializeEmptyRule(node, buffer);
                    break;
                case RuleCategory.Invalid:
                    RuleParser.serializeInvalidRule(node, buffer);
                    break;
                default:
                    throw new Error('Unknown rule category');
            }
        }
        /**
         * Deserializes a rule node from binary format.
         *
         * @param buffer ByteBuffer for reading binary data.
         * @param node Destination node.
         */
        static deserialize(buffer, node) {
            // lookup instead of storing +1 byte
            const type = buffer.peekUint8();
            switch (type) {
                case BinaryTypeMap.AgentRuleNode:
                case BinaryTypeMap.HintRuleNode:
                case BinaryTypeMap.PreProcessorCommentRuleNode:
                case BinaryTypeMap.MetadataCommentRuleNode:
                case BinaryTypeMap.ConfigCommentRuleNode:
                case BinaryTypeMap.CommentRuleNode:
                    CommentRuleParser.deserialize(buffer, node);
                    break;
                case BinaryTypeMap.ElementHidingRule:
                case BinaryTypeMap.CssInjectionRule:
                case BinaryTypeMap.ScriptletInjectionRule:
                case BinaryTypeMap.HtmlFilteringRule:
                case BinaryTypeMap.JsInjectionRule:
                    CosmeticRuleParser.deserialize(buffer, node);
                    break;
                case BinaryTypeMap.NetworkRuleNode:
                    NetworkRuleParser.deserialize(buffer, node);
                    break;
                case BinaryTypeMap.HostRuleNode:
                    HostRuleParser.deserialize(buffer, node);
                    break;
                case BinaryTypeMap.EmptyRule:
                    RuleParser.deserializeEmptyRule(buffer, node);
                    break;
                case BinaryTypeMap.InvalidRule:
                    RuleParser.deserializeInvalidRule(buffer, node);
                    break;
                default:
                    throw new Error('Unknown rule category');
            }
        }
    }

    const APP_LIST_SEPARATOR = PIPE;
    /**
     * `AppListParser` is responsible for parsing an app list.
     *
     * @see {@link https://adguard.app/kb/general/ad-filtering/create-own-filters/#app-modifier}
     */
    class AppListParser extends ParserBase {
        /**
         * Parses an app list which items are separated by `|`,
         * e.g. `Example.exe|com.example.osx`.
         *
         * @param raw Raw input to parse.
         * @param options Global parser options.
         * @param baseOffset Starting offset of the input. Node locations are calculated relative to this offset.
         *
         * @returns App list AST.
         * @throws An {@link AdblockSyntaxError} if the app list is syntactically invalid.
         * @throws An {@link Error} if the options are invalid.
         */
        static parse(raw, options = defaultParserOptions, baseOffset = 0) {
            const result = {
                type: ListNodeType.AppList,
                separator: APP_LIST_SEPARATOR,
                children: parseListItems(raw, options, baseOffset, APP_LIST_SEPARATOR, ListItemNodeType.App),
            };
            if (options.isLocIncluded) {
                result.start = baseOffset;
                result.end = baseOffset + raw.length;
            }
            return result;
        }
    }

    const METHOD_LIST_SEPARATOR = PIPE;
    /**
     * `MethodListParser` is responsible for parsing a method list.
     *
     * @see {@link https://adguard.app/kb/general/ad-filtering/create-own-filters/#method-modifier}
     */
    class MethodListParser extends ParserBase {
        /**
         * Parses a method list which items are separated by `|`,
         * e.g. `get|post|put`.
         *
         * @param raw Raw input to parse.
         * @param options Global parser options.
         * @param baseOffset Starting offset of the input. Node locations are calculated relative to this offset.
         *
         * @returns Method list AST.
         * @throws An {@link AdblockSyntaxError} if the method list is syntactically invalid.
         * @throws An {@link Error} if the options are invalid.
         */
        static parse(raw, options = defaultParserOptions, baseOffset = 0) {
            const result = {
                type: ListNodeType.MethodList,
                separator: METHOD_LIST_SEPARATOR,
                children: parseListItems(raw, options, baseOffset, METHOD_LIST_SEPARATOR, ListItemNodeType.Method),
            };
            if (options.isLocIncluded) {
                result.start = baseOffset;
                result.end = baseOffset + raw.length;
            }
            return result;
        }
    }

    const STEALTH_OPTION_LIST_SEPARATOR = PIPE;
    /**
     * `StealthOptionListParser` is responsible for parsing a list of stealth options.
     *
     * @see {@link https://adguard.app/kb/general/ad-filtering/create-own-filters/#stealth-modifier}
     */
    class StealthOptionListParser extends ParserBase {
        /**
         * Parses a stealth option list which items are separated by `|`,
         * e.g. `dpi|ip`.
         *
         * @param raw Raw input to parse.
         * @param options Global parser options.
         * @param baseOffset Starting offset of the input. Node locations are calculated relative to this offset.
         *
         * @returns Stealth option list AST.
         * @throws An {@link AdblockSyntaxError} if the stealth option list is syntactically invalid.
         * @throws An {@link Error} if the options are invalid.
         */
        static parse(raw, options = defaultParserOptions, baseOffset = 0) {
            const result = {
                type: ListNodeType.StealthOptionList,
                separator: STEALTH_OPTION_LIST_SEPARATOR,
                // eslint-disable-next-line max-len
                children: parseListItems(raw, options, baseOffset, STEALTH_OPTION_LIST_SEPARATOR, ListItemNodeType.StealthOption),
            };
            if (options.isLocIncluded) {
                result.start = baseOffset;
                result.end = baseOffset + raw.length;
            }
            return result;
        }
    }

    /* eslint-disable no-param-reassign */
    /**
     * Property map for binary serialization. This helps to reduce the size of the serialized data,
     * as it allows us to use a single byte to represent a property.
     *
     * ! IMPORTANT: If you change values here, please update the {@link BINARY_SCHEMA_VERSION}!
     *
     * @note Only 256 values can be represented this way.
     */
    var FilterListNodeSerializationMap;
    (function (FilterListNodeSerializationMap) {
        FilterListNodeSerializationMap[FilterListNodeSerializationMap["Children"] = 1] = "Children";
        FilterListNodeSerializationMap[FilterListNodeSerializationMap["Start"] = 2] = "Start";
        FilterListNodeSerializationMap[FilterListNodeSerializationMap["End"] = 3] = "End";
    })(FilterListNodeSerializationMap || (FilterListNodeSerializationMap = {}));

    /**
     * @file Customized error class for conversion errors.
     */
    const ERROR_NAME$1 = 'RuleConversionError';
    /**
     * Customized error class for conversion errors.
     */
    class RuleConversionError extends Error {
        /**
         * Constructs a new `RuleConversionError` instance.
         *
         * @param message Error message
         */
        constructor(message) {
            super(message);
            this.name = ERROR_NAME$1;
        }
    }

    /**
     * Prefixes for different adblockers to describe the platform-specific modifiers data
     * stored in the yaml files.
     */
    ({
        [AdblockSyntax.Adg]: 'adg_',
        [AdblockSyntax.Ubo]: 'ubo_',
        [AdblockSyntax.Abp]: 'abp_',
    });
    /**
     * Set of all allowed characters for app name except the dot `.`.
     */
    const APP_NAME_ALLOWED_CHARS = new Set([
        ...CAPITAL_LETTERS,
        ...SMALL_LETTERS,
        ...NUMBERS,
        UNDERSCORE,
    ]);
    /**
     * Allowed methods for $method modifier.
     *
     * @see {@link https://adguard.app/kb/general/ad-filtering/create-own-filters/#method-modifier}
     */
    const ALLOWED_METHODS = new Set([
        'connect',
        'delete',
        'get',
        'head',
        'options',
        'patch',
        'post',
        'put',
        'trace',
    ]);
    /**
     * Allowed stealth options for $stealth modifier.
     *
     * @see {@link https://adguard.app/kb/general/ad-filtering/create-own-filters/#stealth-modifier}
     */
    const ALLOWED_STEALTH_OPTIONS = new Set([
        'searchqueries',
        'donottrack',
        '3p-cookie',
        '1p-cookie',
        '3p-cache',
        '3p-auth',
        'webrtc',
        'push',
        'location',
        'flash',
        'java',
        'referrer',
        'useragent',
        'ip',
        'xclientdata',
        'dpi',
    ]);
    /**
     * Allowed CSP directives for $csp modifier.
     *
     * @see {@link https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy#directives}
     */
    const ALLOWED_CSP_DIRECTIVES = new Set([
        'base-uri',
        'child-src',
        'connect-src',
        'default-src',
        'fenced-frame-src',
        'font-src',
        'form-action',
        'frame-ancestors',
        'frame-src',
        'img-src',
        'manifest-src',
        'media-src',
        'navigate-to',
        'object-src',
        'plugin-types',
        'prefetch-src',
        'referrer',
        'report-to',
        'report-uri',
        'require-trusted-types-for',
        'sandbox',
        'script-src',
        'script-src-attr',
        'script-src-elem',
        'style-src',
        'style-src-attr',
        'style-src-elem',
        'trusted-types',
        'upgrade-insecure-requests',
        'worker-src',
    ]);
    /**
     * Allowed directives for $permissions modifier.
     *
     * @see {@link https://adguard.app/kb/general/ad-filtering/create-own-filters/#permissions-modifier}
     */
    const ALLOWED_PERMISSION_DIRECTIVES = new Set([
        'accelerometer',
        'ambient-light-sensor',
        'autoplay',
        'battery',
        'browsing-topics',
        'camera',
        'display-capture',
        'document-domain',
        'encrypted-media',
        'execution-while-not-rendered',
        'execution-while-out-of-viewport',
        'fullscreen',
        'gamepad',
        'geolocation',
        'gyroscope',
        'hid',
        'identity-credentials-get',
        'idle-detection',
        'join-ad-interest-group',
        'local-fonts',
        'magnetometer',
        'microphone',
        'midi',
        'payment',
        'picture-in-picture',
        'publickey-credentials-create',
        'publickey-credentials-get',
        'run-ad-auction',
        'screen-wake-lock',
        'serial',
        'speaker-selection',
        'storage-access',
        'usb',
        'web-share',
        'xr-spatial-tracking',
    ]);
    /**
     * One of available tokens for $permission modifier value.
     *
     * @see {@link https://w3c.github.io/webappsec-permissions-policy/#structured-header-serialization}
     */
    const PERMISSIONS_TOKEN_SELF = 'self';
    /**
     * One of allowlist values for $permissions modifier.
     *
     * @see {@link https://developer.mozilla.org/en-US/docs/Web/HTTP/Permissions_Policy#allowlists}
     */
    const EMPTY_PERMISSIONS_ALLOWLIST = `${OPEN_PARENTHESIS}${CLOSE_PARENTHESIS}`;
    /**
     * Allowed directives for $referrerpolicy modifier.
     *
     * @see {@link https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Referrer-Policy}
     */
    const REFERRER_POLICY_DIRECTIVES = new Set([
        'no-referrer',
        'no-referrer-when-downgrade',
        'origin',
        'origin-when-cross-origin',
        'same-origin',
        'strict-origin',
        'strict-origin-when-cross-origin',
        'unsafe-url',
    ]);
    /**
     * Prefixes for error messages used in modifier validation.
     */
    const VALIDATION_ERROR_PREFIX = {
        BLOCK_ONLY: 'Only blocking rules may contain the modifier',
        EXCEPTION_ONLY: 'Only exception rules may contain the modifier',
        INVALID_CSP_DIRECTIVES: 'Invalid CSP directives for the modifier',
        INVALID_LIST_VALUES: 'Invalid values for the modifier',
        INVALID_NOOP: 'Invalid noop modifier',
        INVALID_PERMISSION_DIRECTIVE: 'Invalid Permissions-Policy directive for the modifier',
        INVALID_PERMISSION_ORIGINS: 'Origins in the value is invalid for the modifier and the directive',
        INVALID_PERMISSION_ORIGIN_QUOTES: 'Double quotes should be used for origins in the value of the modifier',
        INVALID_REFERRER_POLICY_DIRECTIVE: 'Invalid Referrer-Policy directive for the modifier',
        MIXED_NEGATIONS: 'Simultaneous usage of negated and not negated values is forbidden for the modifier',
        NO_CSP_VALUE: 'No CSP value for the modifier and the directive',
        NO_CSP_DIRECTIVE_QUOTE: 'CSP directives should no be quoted for the modifier',
        NO_UNESCAPED_PERMISSION_COMMA: 'Unescaped comma in the value is not allowed for the modifier',
        // TODO: implement later for $scp and $permissions
        // NO_VALUE_ONLY_FOR_EXCEPTION: 'Modifier without value can be used only in exception rules',
        NOT_EXISTENT: 'Non-existent modifier',
        NOT_NEGATABLE_MODIFIER: 'Non-negatable modifier',
        NOT_NEGATABLE_VALUE: 'Values cannot be negated for the modifier',
        NOT_SUPPORTED: 'The adblocker does not support the modifier',
        REMOVED: 'Removed and no longer supported modifier',
        VALUE_FORBIDDEN: 'Value is not allowed for the modifier',
        VALUE_INVALID: 'Value is invalid for the modifier',
        VALUE_REQUIRED: 'Value is required for the modifier',
    };
    /**
     * Returns invalid validation result with given error message.
     *
     * @param error Error message.
     *
     * @returns Validation result `{ valid: false, error }`.
     */
    const getInvalidValidationResult = (error) => {
        return {
            valid: false,
            error,
        };
    };
    /**
     * Returns invalid validation result which uses {@link VALIDATION_ERROR_PREFIX.VALUE_REQUIRED} as prefix
     * and specifies the given `modifierName` in the error message.
     *
     * @param modifierName Modifier name.
     *
     * @returns Validation result `{ valid: false, error }`.
     */
    const getValueRequiredValidationResult = (modifierName) => {
        return getInvalidValidationResult(`${VALIDATION_ERROR_PREFIX.VALUE_REQUIRED}: '${modifierName}'`);
    };

    /**
     * @file Utility functions for domain and hostname validation.
     */
    /**
     * Marker for a wildcard top-level domain — `.*`.
     *
     * @example
     * `example.*` — matches with any TLD, e.g. `example.org`, `example.com`, etc.
     */
    const WILDCARD_TLD = DOT + WILDCARD;
    /**
     * Marker for a wildcard subdomain — `*.`.
     *
     * @example
     * `*.example.org` — matches with any subdomain, e.g. `foo.example.org` or `bar.example.org`
     */
    const WILDCARD_SUBDOMAIN = WILDCARD + DOT;
    class DomainUtils {
        /**
         * Check if the input is a valid domain or hostname.
         *
         * @param domain Domain to check
         * @returns `true` if the domain is valid, `false` otherwise
         */
        static isValidDomainOrHostname(domain) {
            let domainToCheck = domain;
            // Wildcard-only domain, typically a generic rule
            if (domainToCheck === WILDCARD) {
                return true;
            }
            // https://adguard.com/kb/general/ad-filtering/create-own-filters/#wildcard-for-tld
            if (domainToCheck.endsWith(WILDCARD_TLD)) {
                // Remove the wildcard TLD
                domainToCheck = domainToCheck.substring(0, domainToCheck.length - WILDCARD_TLD.length);
            }
            if (domainToCheck.startsWith(WILDCARD_SUBDOMAIN)) {
                // Remove the wildcard subdomain
                domainToCheck = domainToCheck.substring(WILDCARD_SUBDOMAIN.length);
            }
            // Parse the domain with tldts
            const tldtsResult = parse(domainToCheck);
            // Check if the domain is valid
            return domainToCheck === tldtsResult.domain || domainToCheck === tldtsResult.hostname;
        }
    }

    /**
     * Pre-defined available validators for modifiers with custom `value_format`.
     */
    var CustomValueFormatValidatorName;
    (function (CustomValueFormatValidatorName) {
        CustomValueFormatValidatorName["App"] = "pipe_separated_apps";
        CustomValueFormatValidatorName["Csp"] = "csp_value";
        // there are some differences between $domain and $denyallow
        CustomValueFormatValidatorName["DenyAllow"] = "pipe_separated_denyallow_domains";
        CustomValueFormatValidatorName["Domain"] = "pipe_separated_domains";
        CustomValueFormatValidatorName["Method"] = "pipe_separated_methods";
        CustomValueFormatValidatorName["Permissions"] = "permissions_value";
        CustomValueFormatValidatorName["ReferrerPolicy"] = "referrerpolicy_value";
        CustomValueFormatValidatorName["StealthOption"] = "pipe_separated_stealth_options";
    })(CustomValueFormatValidatorName || (CustomValueFormatValidatorName = {}));
    /**
     * Checks whether the `chunk` of app name (which if splitted by dot `.`) is valid.
     * Only letters, numbers, and underscore `_` are allowed.
     *
     * @param chunk Chunk of app name to check.
     *
     * @returns True if the `chunk` is valid part of app name, false otherwise.
     */
    const isValidAppNameChunk = (chunk) => {
        // e.g. 'Example..exe'
        if (chunk.length === 0) {
            return false;
        }
        for (let i = 0; i < chunk.length; i += 1) {
            const char = chunk[i];
            if (!APP_NAME_ALLOWED_CHARS.has(char)) {
                return false;
            }
        }
        return true;
    };
    /**
     * Checks whether the given `value` is valid app name as $app modifier value.
     *
     * @param value App name to check.
     *
     * @returns True if the `value` is valid app name, false otherwise.
     */
    const isValidAppModifierValue = (value) => {
        // $app modifier does not support wildcard tld
        // https://adguard.app/kb/general/ad-filtering/create-own-filters/#app-modifier
        if (value.includes(WILDCARD)) {
            return false;
        }
        return value
            .split(DOT)
            .every((chunk) => isValidAppNameChunk(chunk));
    };
    /**
     * Checks whether the given `value` is valid HTTP method as $method modifier value.
     *
     * @param value Method to check.
     *
     * @returns True if the `value` is valid HTTP method, false otherwise.
     */
    const isValidMethodModifierValue = (value) => {
        return ALLOWED_METHODS.has(value);
    };
    /**
     * Checks whether the given `value` is valid option as $stealth modifier value.
     *
     * @param value Stealth option to check.
     *
     * @returns True if the `value` is valid stealth option, false otherwise.
     */
    const isValidStealthModifierValue = (value) => {
        return ALLOWED_STEALTH_OPTIONS.has(value);
    };
    /**
     * Checks whether the given `rawOrigin` is valid as Permissions Allowlist origin.
     *
     * @see {@link https://w3c.github.io/webappsec-permissions-policy/#allowlists}
     *
     * @param rawOrigin The raw origin.
     *
     * @returns True if the origin is valid, false otherwise.
     */
    const isValidPermissionsOrigin = (rawOrigin) => {
        // origins should be quoted by double quote
        const actualQuoteType = QuoteUtils.getStringQuoteType(rawOrigin);
        if (actualQuoteType !== QuoteType.Double) {
            return false;
        }
        const origin = QuoteUtils.removeQuotes(rawOrigin);
        try {
            // validate the origin by URL constructor
            // https://w3c.github.io/webappsec-permissions-policy/#algo-parse-policy-directive
            new URL(origin);
        }
        catch (e) {
            return false;
        }
        return true;
    };
    /**
     * Checks whether the given `value` is valid domain as $denyallow modifier value.
     * Important: wildcard tld are not supported, compared to $domain.
     *
     * @param value Value to check.
     *
     * @returns True if the `value` is valid domain and does not contain wildcard `*`, false otherwise.
     */
    const isValidDenyAllowModifierValue = (value) => {
        // $denyallow modifier does not support wildcard tld
        // https://adguard.app/kb/general/ad-filtering/create-own-filters/#denyallow-modifier
        // but here we are simply checking whether the value contains wildcard `*`, not ends with `.*`
        if (value.includes(WILDCARD)) {
            return false;
        }
        // TODO: add cache for domains validation
        return DomainUtils.isValidDomainOrHostname(value);
    };
    /**
     * Checks whether the given `value` is valid domain as $domain modifier value.
     *
     * @param value Value to check.
     *
     * @returns True if the `value` is valid domain, false otherwise.
     */
    const isValidDomainModifierValue = (value) => {
        // TODO: add cache for domains validation
        return DomainUtils.isValidDomainOrHostname(value);
    };
    /**
     * Checks whether the all list items' exceptions are `false`.
     * Those items which `exception` is `true` is to be specified in the validation result error message.
     *
     * @param modifierName Modifier name.
     * @param listItems List items to check.
     *
     * @returns Validation result.
     */
    const customNoNegatedListItemsValidator = (modifierName, listItems) => {
        const negatedValues = [];
        listItems.forEach((listItem) => {
            if (listItem.exception) {
                negatedValues.push(listItem.value);
            }
        });
        if (negatedValues.length > 0) {
            const valuesToStr = QuoteUtils.quoteAndJoinStrings(negatedValues);
            return getInvalidValidationResult(`${VALIDATION_ERROR_PREFIX.NOT_NEGATABLE_VALUE}: '${modifierName}': ${valuesToStr}`);
        }
        return { valid: true };
    };
    /**
     * Checks whether the all list items' exceptions are consistent,
     * i.e. all items are either negated or not negated.
     *
     * The `exception` value of the first item is used as a reference, and all other items are checked against it.
     * Those items which `exception` is not consistent with the first item
     * is to be specified in the validation result error message.
     *
     * @see {@link https://adguard.com/kb/general/ad-filtering/create-own-filters/#method-modifier}
     *
     * @param modifierName Modifier name.
     * @param listItems List items to check.
     *
     * @returns Validation result.
     */
    const customConsistentExceptionsValidator = (modifierName, listItems) => {
        const firstException = listItems[0].exception;
        const nonConsistentItemValues = [];
        listItems.forEach((listItem) => {
            if (listItem.exception !== firstException) {
                nonConsistentItemValues.push(listItem.value);
            }
        });
        if (nonConsistentItemValues.length > 0) {
            const valuesToStr = QuoteUtils.quoteAndJoinStrings(nonConsistentItemValues);
            return getInvalidValidationResult(`${VALIDATION_ERROR_PREFIX.MIXED_NEGATIONS}: '${modifierName}': ${valuesToStr}`);
        }
        return { valid: true };
    };
    /**
     * Checks whether the given `modifier` value is valid.
     * Supposed to validate the value of modifiers which values are lists separated by pipe `|` —
     * $app, $domain, $denyallow, $method.
     *
     * @param modifier Modifier AST node.
     * @param listParser Parser function for parsing modifier value
     * which is supposed to be a list separated by pipe `|`.
     * @param isValidListItem Predicate function for checking of modifier's list item validity,
     * e.g. $denyallow modifier does not support wildcard tld, but $domain does.
     * @param customListValidator Optional; custom validator for specific modifier,
     * e.g. $denyallow modifier does not support negated domains.
     *
     * @returns Result of modifier domains validation.
     */
    const validateListItemsModifier = (modifier, listParser, isValidListItem, customListValidator) => {
        const modifierName = modifier.name.value;
        const defaultInvalidValueResult = getValueRequiredValidationResult(modifierName);
        if (!modifier.value?.value) {
            return defaultInvalidValueResult;
        }
        let theList;
        try {
            theList = listParser(modifier.value.value, defaultParserOptions, 0, PIPE);
        }
        catch (e) {
            if (e instanceof AdblockSyntaxError) {
                return {
                    valid: false,
                    error: e.message,
                };
            }
            return defaultInvalidValueResult;
        }
        const invalidListItems = [];
        theList.children.forEach((item) => {
            // different validators are used for $denyallow and $domain modifiers
            // because of different requirements and restrictions
            if (!isValidListItem(item.value)) {
                invalidListItems.push(item.value);
            }
        });
        if (invalidListItems.length > 0) {
            const itemsToStr = QuoteUtils.quoteAndJoinStrings(invalidListItems);
            return getInvalidValidationResult(`${VALIDATION_ERROR_PREFIX.INVALID_LIST_VALUES}: '${modifierName}': ${itemsToStr}`);
        }
        // IMPORTANT: run custom validator after all other checks
        // Some lists should be fully checked, not just the list items:
        // e.g. Safari does not support allowed and disallowed domains for $domain in the same list
        // or   domains cannot be negated for $denyallow modifier
        if (customListValidator) {
            return customListValidator(modifierName, theList.children);
        }
        return { valid: true };
    };
    /**
     * Validates 'pipe_separated_apps' custom value format.
     * Used for $app modifier.
     *
     * @param modifier Modifier AST node.
     *
     * @returns Validation result.
     */
    const validatePipeSeparatedApps = (modifier) => {
        return validateListItemsModifier(modifier, (raw) => AppListParser.parse(raw), isValidAppModifierValue);
    };
    /**
     * Validates 'pipe_separated_denyallow_domains' custom value format.
     * Used for $denyallow modifier.
     *
     * @param modifier Modifier AST node.
     *
     * @returns Validation result.
     */
    const validatePipeSeparatedDenyAllowDomains = (modifier) => {
        return validateListItemsModifier(modifier, DomainListParser.parse, isValidDenyAllowModifierValue, customNoNegatedListItemsValidator);
    };
    /**
     * Validates 'pipe_separated_domains' custom value format.
     * Used for $domains modifier.
     *
     * @param modifier Modifier AST node.
     *
     * @returns Validation result.
     */
    const validatePipeSeparatedDomains = (modifier) => {
        return validateListItemsModifier(modifier, DomainListParser.parse, isValidDomainModifierValue);
    };
    /**
     * Validates 'pipe_separated_methods' custom value format.
     * Used for $method modifier.
     *
     * @param modifier Modifier AST node.
     *
     * @returns Validation result.
     */
    const validatePipeSeparatedMethods = (modifier) => {
        return validateListItemsModifier(modifier, (raw) => MethodListParser.parse(raw), isValidMethodModifierValue, customConsistentExceptionsValidator);
    };
    /**
     * Validates 'pipe_separated_stealth_options' custom value format.
     * Used for $stealth modifier.
     *
     * @param modifier Modifier AST node.
     *
     * @returns Validation result.
     */
    const validatePipeSeparatedStealthOptions = (modifier) => {
        return validateListItemsModifier(modifier, (raw) => StealthOptionListParser.parse(raw), isValidStealthModifierValue, customNoNegatedListItemsValidator);
    };
    /**
     * Validates `csp_value` custom value format.
     * Used for $csp modifier.
     *
     * @param modifier Modifier AST node.
     *
     * @returns Validation result.
     */
    const validateCspValue = (modifier) => {
        const modifierName = modifier.name.value;
        if (!modifier.value?.value) {
            return getValueRequiredValidationResult(modifierName);
        }
        // $csp modifier value may contain multiple directives
        // e.g. "csp=child-src 'none'; frame-src 'self' *; worker-src 'none'"
        const policyDirectives = modifier.value.value
            .split(SEMICOLON)
            // rule with $csp modifier may end with semicolon
            // e.g. "$csp=sandbox allow-same-origin;"
            // TODO: add predicate helper for `(i) => !!i`
            .filter((i) => !!i);
        const invalidValueValidationResult = getInvalidValidationResult(`${VALIDATION_ERROR_PREFIX.VALUE_INVALID}: '${modifierName}': "${modifier.value.value}"`);
        if (policyDirectives.length === 0) {
            return invalidValueValidationResult;
        }
        const invalidDirectives = [];
        for (let i = 0; i < policyDirectives.length; i += 1) {
            const policyDirective = policyDirectives[i].trim();
            if (!policyDirective) {
                return invalidValueValidationResult;
            }
            const chunks = policyDirective.split(SPACE);
            const [directive, ...valueChunks] = chunks;
            // e.g. "csp=child-src 'none'; ; worker-src 'none'"
            // validator it here          ↑
            if (!directive) {
                return invalidValueValidationResult;
            }
            if (!ALLOWED_CSP_DIRECTIVES.has(directive)) {
                // e.g. "csp='child-src' 'none'"
                if (ALLOWED_CSP_DIRECTIVES.has(QuoteUtils.removeQuotes(directive))) {
                    return getInvalidValidationResult(`${VALIDATION_ERROR_PREFIX.NO_CSP_DIRECTIVE_QUOTE}: '${modifierName}': ${directive}`);
                }
                invalidDirectives.push(directive);
                continue;
            }
            if (valueChunks.length === 0) {
                return getInvalidValidationResult(`${VALIDATION_ERROR_PREFIX.NO_CSP_VALUE}: '${modifierName}': '${directive}'`);
            }
        }
        if (invalidDirectives.length > 0) {
            const directivesToStr = QuoteUtils.quoteAndJoinStrings(invalidDirectives, QuoteType.Double);
            return getInvalidValidationResult(`${VALIDATION_ERROR_PREFIX.INVALID_CSP_DIRECTIVES}: '${modifierName}': ${directivesToStr}`);
        }
        return { valid: true };
    };
    /**
     * Validates permission allowlist origins in the value of $permissions modifier.
     *
     * @see {@link https://w3c.github.io/webappsec-permissions-policy/#allowlists}
     *
     * @param allowlistChunks Array of allowlist chunks.
     * @param directive Permission directive name.
     * @param modifierName Modifier name.
     *
     * @returns Validation result.
     */
    const validatePermissionAllowlistOrigins = (allowlistChunks, directive, modifierName) => {
        const invalidOrigins = [];
        for (let i = 0; i < allowlistChunks.length; i += 1) {
            const chunk = allowlistChunks[i].trim();
            // skip few spaces between origins (they were splitted by space)
            // e.g. 'geolocation=("https://example.com"  "https://*.example.com")'
            if (chunk.length === 0) {
                continue;
            }
            /**
             * 'self' should be checked case-insensitively
             *
             * @see {@link https://w3c.github.io/webappsec-permissions-policy/#algo-parse-policy-directive}
             *
             * @example 'geolocation=(self)'
             */
            if (chunk.toLowerCase() === PERMISSIONS_TOKEN_SELF) {
                continue;
            }
            if (QuoteUtils.getStringQuoteType(chunk) !== QuoteType.Double) {
                return getInvalidValidationResult(
                // eslint-disable-next-line max-len
                `${VALIDATION_ERROR_PREFIX.INVALID_PERMISSION_ORIGIN_QUOTES}: '${modifierName}': '${directive}': '${QuoteUtils.removeQuotes(chunk)}'`);
            }
            if (!isValidPermissionsOrigin(chunk)) {
                invalidOrigins.push(chunk);
            }
        }
        if (invalidOrigins.length > 0) {
            const originsToStr = QuoteUtils.quoteAndJoinStrings(invalidOrigins);
            return getInvalidValidationResult(
            // eslint-disable-next-line max-len
            `${VALIDATION_ERROR_PREFIX.INVALID_PERMISSION_ORIGINS}: '${modifierName}': '${directive}': ${originsToStr}`);
        }
        return { valid: true };
    };
    /**
     * Validates permission allowlist in the modifier value.
     *
     * @see {@link https://developer.mozilla.org/en-US/docs/Web/HTTP/Permissions_Policy#allowlists}
     * @see {@link https://w3c.github.io/webappsec-permissions-policy/#allowlists}
     *
     * @param allowlist Allowlist value.
     * @param directive Permission directive name.
     * @param modifierName Modifier name.
     *
     * @returns Validation result.
     */
    const validatePermissionAllowlist = (allowlist, directive, modifierName) => {
        // `*` is one of available permissions tokens
        // e.g. 'fullscreen=*'
        // https://w3c.github.io/webappsec-permissions-policy/#structured-header-serialization
        if (allowlist === WILDCARD
            // e.g. 'autoplay=()'
            || allowlist === EMPTY_PERMISSIONS_ALLOWLIST) {
            return { valid: true };
        }
        if (!(allowlist.startsWith(OPEN_PARENTHESIS) && allowlist.endsWith(CLOSE_PARENTHESIS))) {
            return getInvalidValidationResult(`${VALIDATION_ERROR_PREFIX.VALUE_INVALID}: '${modifierName}'`);
        }
        const allowlistChunks = allowlist.slice(1, -1).split(SPACE);
        return validatePermissionAllowlistOrigins(allowlistChunks, directive, modifierName);
    };
    /**
     * Validates single permission in the modifier value.
     *
     * @param permission Single permission value.
     * @param modifierName Modifier name.
     * @param modifierValue Modifier value.
     *
     * @returns Validation result.
     */
    const validateSinglePermission = (permission, modifierName, modifierValue) => {
        // empty permission in the rule
        // e.g. 'permissions=storage-access=()\\, \\, camera=()'
        // the validator is here                 ↑
        if (!permission) {
            return getInvalidValidationResult(`${VALIDATION_ERROR_PREFIX.VALUE_INVALID}: '${modifierName}'`);
        }
        if (permission.includes(COMMA)) {
            return getInvalidValidationResult(`${VALIDATION_ERROR_PREFIX.NO_UNESCAPED_PERMISSION_COMMA}: '${modifierName}': '${modifierValue}'`);
        }
        const [directive, allowlist] = permission.split(EQUALS);
        if (!ALLOWED_PERMISSION_DIRECTIVES.has(directive)) {
            return getInvalidValidationResult(`${VALIDATION_ERROR_PREFIX.INVALID_PERMISSION_DIRECTIVE}: '${modifierName}': '${directive}'`);
        }
        return validatePermissionAllowlist(allowlist, directive, modifierName);
    };
    /**
     * Validates `permissions_value` custom value format.
     * Used for $permissions modifier.
     *
     * @param modifier Modifier AST node.
     *
     * @returns Validation result.
     */
    const validatePermissions = (modifier) => {
        if (!modifier.value?.value) {
            return getValueRequiredValidationResult(modifier.name.value);
        }
        const modifierName = modifier.name.value;
        const modifierValue = modifier.value.value;
        // multiple permissions may be separated by escaped commas
        const permissions = modifier.value.value.split(`${BACKSLASH}${COMMA}`);
        for (let i = 0; i < permissions.length; i += 1) {
            const permission = permissions[i].trim();
            const singlePermissionValidationResult = validateSinglePermission(permission, modifierName, modifierValue);
            if (!singlePermissionValidationResult.valid) {
                return singlePermissionValidationResult;
            }
        }
        return { valid: true };
    };
    /**
     * Validates `referrerpolicy_value` custom value format.
     * Used for $referrerpolicy modifier.
     *
     * @param modifier Modifier AST node.
     *
     * @returns Validation result.
     */
    const validateReferrerPolicy = (modifier) => {
        if (!modifier.value?.value) {
            return getValueRequiredValidationResult(modifier.name.value);
        }
        const modifierName = modifier.name.value;
        const modifierValue = modifier.value.value;
        if (!REFERRER_POLICY_DIRECTIVES.has(modifierValue)) {
            // eslint-disable-next-line max-len
            return getInvalidValidationResult(`${VALIDATION_ERROR_PREFIX.INVALID_REFERRER_POLICY_DIRECTIVE}: '${modifierName}': '${modifierValue}'`);
        }
        return { valid: true };
    };
    /**
     * Map of all available pre-defined validators for modifiers with custom `value_format`.
     */
    ({
        [CustomValueFormatValidatorName.App]: validatePipeSeparatedApps,
        [CustomValueFormatValidatorName.Csp]: validateCspValue,
        [CustomValueFormatValidatorName.DenyAllow]: validatePipeSeparatedDenyAllowDomains,
        [CustomValueFormatValidatorName.Domain]: validatePipeSeparatedDomains,
        [CustomValueFormatValidatorName.Method]: validatePipeSeparatedMethods,
        [CustomValueFormatValidatorName.Permissions]: validatePermissions,
        [CustomValueFormatValidatorName.ReferrerPolicy]: validateReferrerPolicy,
        [CustomValueFormatValidatorName.StealthOption]: validatePipeSeparatedStealthOptions,
    });

    /**
     * @file Clone related utilities
     *
     * We should keep clone related functions in this file. Thus, we just provide
     * a simple interface for cloning values, we use it across the AGTree project,
     * and the implementation "under the hood" can be improved later, if needed.
     */
    /**
     * Clones an input value to avoid side effects. Use it only in justified cases,
     * because it can impact performance negatively.
     *
     * @param value Value to clone
     * @returns Cloned value
     */
    function clone(value) {
        // TODO: Replace cloneDeep with a more efficient implementation
        return cloneDeep$1(value);
    }

    /* eslint-disable no-bitwise */
    /**
     * @file Provides platform enums.
     * The difference between specific and generic platforms is that specific platforms are individual platforms
     * (e.g. AdGuard for Windows, AdGuard for Android, etc.),
     * while generic platforms are groups of specific platforms
     * (e.g. AdGuard for any OS, AdGuard for any Chromium-based extension, etc.).
     */
    /**
     * List of specific platforms.
     */
    var SpecificPlatform;
    (function (SpecificPlatform) {
        SpecificPlatform[SpecificPlatform["AdgOsWindows"] = 1] = "AdgOsWindows";
        SpecificPlatform[SpecificPlatform["AdgOsMac"] = 2] = "AdgOsMac";
        SpecificPlatform[SpecificPlatform["AdgOsAndroid"] = 4] = "AdgOsAndroid";
        SpecificPlatform[SpecificPlatform["AdgExtChrome"] = 8] = "AdgExtChrome";
        SpecificPlatform[SpecificPlatform["AdgExtOpera"] = 16] = "AdgExtOpera";
        SpecificPlatform[SpecificPlatform["AdgExtEdge"] = 32] = "AdgExtEdge";
        SpecificPlatform[SpecificPlatform["AdgExtFirefox"] = 64] = "AdgExtFirefox";
        SpecificPlatform[SpecificPlatform["AdgCbAndroid"] = 128] = "AdgCbAndroid";
        SpecificPlatform[SpecificPlatform["AdgCbIos"] = 256] = "AdgCbIos";
        SpecificPlatform[SpecificPlatform["AdgCbSafari"] = 512] = "AdgCbSafari";
        SpecificPlatform[SpecificPlatform["UboExtChrome"] = 1024] = "UboExtChrome";
        SpecificPlatform[SpecificPlatform["UboExtOpera"] = 2048] = "UboExtOpera";
        SpecificPlatform[SpecificPlatform["UboExtEdge"] = 4096] = "UboExtEdge";
        SpecificPlatform[SpecificPlatform["UboExtFirefox"] = 8192] = "UboExtFirefox";
        SpecificPlatform[SpecificPlatform["AbpExtChrome"] = 16384] = "AbpExtChrome";
        SpecificPlatform[SpecificPlatform["AbpExtOpera"] = 32768] = "AbpExtOpera";
        SpecificPlatform[SpecificPlatform["AbpExtEdge"] = 65536] = "AbpExtEdge";
        SpecificPlatform[SpecificPlatform["AbpExtFirefox"] = 131072] = "AbpExtFirefox";
    })(SpecificPlatform || (SpecificPlatform = {}));
    /**
     * List of generic platforms (combinations of specific platforms).
     */
    var GenericPlatform;
    (function (GenericPlatform) {
        GenericPlatform[GenericPlatform["AdgOsAny"] = 7] = "AdgOsAny";
        GenericPlatform[GenericPlatform["AdgSafariAny"] = 768] = "AdgSafariAny";
        GenericPlatform[GenericPlatform["AdgExtChromium"] = 56] = "AdgExtChromium";
        GenericPlatform[GenericPlatform["AdgExtAny"] = 120] = "AdgExtAny";
        GenericPlatform[GenericPlatform["AdgAny"] = 1023] = "AdgAny";
        GenericPlatform[GenericPlatform["UboExtChromium"] = 7168] = "UboExtChromium";
        GenericPlatform[GenericPlatform["UboExtAny"] = 15360] = "UboExtAny";
        GenericPlatform[GenericPlatform["UboAny"] = 15360] = "UboAny";
        GenericPlatform[GenericPlatform["AbpExtChromium"] = 114688] = "AbpExtChromium";
        GenericPlatform[GenericPlatform["AbpExtAny"] = 245760] = "AbpExtAny";
        GenericPlatform[GenericPlatform["AbpAny"] = 245760] = "AbpAny";
        GenericPlatform[GenericPlatform["Any"] = 262143] = "Any";
    })(GenericPlatform || (GenericPlatform = {}));

    /* eslint-disable no-bitwise */
    /**
     * @file Provides platform mapping and helper functions.
     */
    /**
     * Map of specific platforms string names to their corresponding enum values.
     */
    const SPECIFIC_PLATFORM_MAP = new Map([
        ['adg_os_windows', SpecificPlatform.AdgOsWindows],
        ['adg_os_mac', SpecificPlatform.AdgOsMac],
        ['adg_os_android', SpecificPlatform.AdgOsAndroid],
        ['adg_ext_chrome', SpecificPlatform.AdgExtChrome],
        ['adg_ext_opera', SpecificPlatform.AdgExtOpera],
        ['adg_ext_edge', SpecificPlatform.AdgExtEdge],
        ['adg_ext_firefox', SpecificPlatform.AdgExtFirefox],
        ['adg_cb_android', SpecificPlatform.AdgCbAndroid],
        ['adg_cb_ios', SpecificPlatform.AdgCbIos],
        ['adg_cb_safari', SpecificPlatform.AdgCbSafari],
        ['ubo_ext_chrome', SpecificPlatform.UboExtChrome],
        ['ubo_ext_opera', SpecificPlatform.UboExtOpera],
        ['ubo_ext_edge', SpecificPlatform.UboExtEdge],
        ['ubo_ext_firefox', SpecificPlatform.UboExtFirefox],
        ['abp_ext_chrome', SpecificPlatform.AbpExtChrome],
        ['abp_ext_opera', SpecificPlatform.AbpExtOpera],
        ['abp_ext_edge', SpecificPlatform.AbpExtEdge],
        ['abp_ext_firefox', SpecificPlatform.AbpExtFirefox],
    ]);
    /**
     * Map of specific platforms enum values to their corresponding string names.
     *
     * @note Reverse of {@link SPECIFIC_PLATFORM_MAP}.
     */
    new Map([...SPECIFIC_PLATFORM_MAP].map(([key, value]) => [value, key]));
    /**
     * Map of generic platforms string names to their corresponding enum values.
     */
    const GENERIC_PLATFORM_MAP = new Map([
        ['adg_os_any', GenericPlatform.AdgOsAny],
        ['adg_safari_any', GenericPlatform.AdgSafariAny],
        ['adg_ext_chromium', GenericPlatform.AdgExtChromium],
        ['adg_ext_any', GenericPlatform.AdgExtAny],
        ['adg_any', GenericPlatform.AdgAny],
        ['ubo_ext_chromium', GenericPlatform.UboExtChromium],
        ['ubo_ext_any', GenericPlatform.UboExtAny],
        ['ubo_any', GenericPlatform.UboAny],
        ['abp_ext_chromium', GenericPlatform.AbpExtChromium],
        ['abp_ext_any', GenericPlatform.AbpExtAny],
        ['abp_any', GenericPlatform.AbpAny],
        ['any', GenericPlatform.Any],
    ]);
    /**
     * Check if the platform is a generic platform.
     *
     * @param platform Platform to check.
     *
     * @returns True if the platform is a generic platform, false otherwise.
     */
    const isGenericPlatform = (platform) => {
        // if more than one bit is set, it's a generic platform
        return !!(platform & (platform - 1));
    };

    /* eslint-disable no-bitwise */
    /**
     * @file Provides common compatibility table methods.
     */
    /**
     * Base compatibility table class which provides common methods to work with compatibility data.
     *
     * @template T Compatibility data schema.
     */
    class CompatibilityTableBase {
        /**
         * Compatibility table data.
         */
        data;
        /**
         * Optional name transformer function. If provided,
         * it will be called in all methods before processing compatibility data names.
         */
        nameTransformer;
        /**
         * Creates a new instance of the common compatibility table.
         *
         * @param data Compatibility table data.
         * @param nameTransformer Optional name transformer function.
         */
        constructor(data, nameTransformer = null) {
            this.data = data;
            this.nameTransformer = nameTransformer;
        }
        /**
         * Helper method to get a 'row' from the compatibility table data by name.
         *
         * @param name Compatibility data name.
         * @returns Compatibility table row storage or `null` if not found.
         */
        getRowStorage(name) {
            const idx = this.data.map[name];
            if (isUndefined$1(idx)) {
                return null;
            }
            return this.data.shared[idx];
        }
        /**
         * Checks whether a compatibility data `name` exists for any platform.
         *
         * @note Technically, do the same as `exists()` method with generic platform _any_
         * but it is faster because it does not apply complex logic.
         *
         * @param name Compatibility data name.
         *
         * @returns True if the compatibility data exists, false otherwise.
         */
        existsAny(name) {
            const normalizedName = this.nameTransformer ? this.nameTransformer(name) : name;
            return !isUndefined$1(this.data.map[normalizedName]);
        }
        /**
         * Checks whether a compatibility data `name` exists for a specified platform.
         *
         * @param name Compatibility data name.
         * @param platform Specific or generic platform.
         *
         * @returns True if the compatibility data exists, false otherwise.
         */
        exists(name, platform) {
            const normalizedName = this.nameTransformer ? this.nameTransformer(name) : name;
            const data = this.getRowStorage(normalizedName);
            if (!data) {
                return false;
            }
            const isMatch = (idx) => {
                const el = data.shared[idx];
                return !isUndefined$1(el) && (el.name === normalizedName || !!el.aliases?.includes(normalizedName));
            };
            if (isGenericPlatform(platform)) {
                // Since indexes are specific platforms in the compatibility table data,
                // we can't index them directly if the platform is generic (union of specific platforms).
                // In this case, we need to iterate over the keys and return true on the first match.
                const keys = Object.keys(data.map);
                for (let i = 0; i < keys.length; i += 1) {
                    const key = Number(keys[i]);
                    if (platform & key) {
                        const idx = data.map[key];
                        if (isMatch(idx)) {
                            return true;
                        }
                    }
                }
                return false;
            }
            const idx = data.map[platform];
            return isMatch(idx);
        }
        /**
         * Returns a compatibility data by name and specific platform.
         *
         * @param name The name of the compatibility data.
         * @param platform The specific platform.
         *
         * @returns A single compatibility data or `null` if not found.
         */
        getSingle(name, platform) {
            const normalizedName = this.nameTransformer ? this.nameTransformer(name) : name;
            const data = this.getRowStorage(normalizedName);
            if (!data) {
                return null;
            }
            const idx = data.map[platform];
            return isUndefined$1(idx) ? null : data.shared[idx];
        }
        /**
         * Returns all compatibility data records for name and specified platform.
         *
         * @param name Compatibility data name.
         * @param platform Specific or generic platform.
         *
         * @returns Multiple records grouped by platforms.
         * Technically, it is an object where keys are platform enums values and values are compatibility data records.
         *
         * @note Platform enum values can be converted to string names using {@link getSpecificPlatformName} on demand.
         */
        getMultiple(name, platform) {
            const normalizedName = this.nameTransformer ? this.nameTransformer(name) : name;
            const data = this.getRowStorage(normalizedName);
            if (!data) {
                return null;
            }
            if (isGenericPlatform(platform)) {
                const result = {};
                const keys = Object.keys(data.map);
                for (let i = 0; i < keys.length; i += 1) {
                    const key = Number(keys[i]);
                    if (platform & key) {
                        const idx = data.map[key];
                        if (!isUndefined$1(idx)) {
                            result[key] = data.shared[idx];
                        }
                    }
                }
                return result;
            }
            const idx = data.map[platform];
            if (isUndefined$1(idx)) {
                return null;
            }
            return { key: data.shared[idx] };
        }
        /**
         * Returns all compatibility data records for the specified platform.
         *
         * @param platform Specific or generic platform.
         *
         * @returns Array of multiple records grouped by platforms.
         */
        getAllMultiple(platform) {
            const result = [];
            for (let i = 0; i < this.data.shared.length; i += 1) {
                const data = this.data.shared[i];
                const names = new Set(data.shared.map(({ name }) => name));
                names.forEach((name) => {
                    const multipleRecords = this.getMultiple(name, platform);
                    if (multipleRecords) {
                        result.push(multipleRecords);
                    }
                });
            }
            return result;
        }
        /**
         * Returns the first compatibility data record for name and specified platform.
         *
         * @param name Compatibility data name.
         * @param platform Specific or generic platform.
         *
         * @returns First found compatibility data record or `null` if not found.
         */
        getFirst(name, platform) {
            const normalizedName = this.nameTransformer ? this.nameTransformer(name) : name;
            const data = this.getRowStorage(normalizedName);
            if (!data) {
                return null;
            }
            if (isGenericPlatform(platform)) {
                const keys = Object.keys(data.map);
                for (let i = 0; i < keys.length; i += 1) {
                    const key = Number(keys[i]);
                    if (platform & key) {
                        const idx = data.map[key];
                        if (!isUndefined$1(idx)) {
                            // return the first found record
                            return data.shared[idx];
                        }
                    }
                }
                return null;
            }
            const idx = data.map[platform];
            if (isUndefined$1(idx)) {
                return null;
            }
            return data.shared[idx];
        }
        /**
         * Returns all compatibility data records for the specified name.
         *
         * @param name Compatibility data name.
         *
         * @returns Array of multiple records grouped by platforms.
         */
        getRow(name) {
            const normalizedName = this.nameTransformer ? this.nameTransformer(name) : name;
            const data = this.getRowStorage(normalizedName);
            if (!data) {
                return [];
            }
            return data.shared;
        }
        /**
         * Returns all compatibility data grouped by products.
         *
         * @returns Array of multiple records grouped by products.
         */
        getRowsByProduct() {
            const result = [];
            for (let i = 0; i < this.data.shared.length; i += 1) {
                const data = this.data.shared[i];
                const keys = Object.keys(data.map);
                const row = {
                    [AdblockSyntax.Adg]: {},
                    [AdblockSyntax.Ubo]: {},
                    [AdblockSyntax.Abp]: {},
                };
                for (let j = 0; j < keys.length; j += 1) {
                    const key = Number(keys[j]);
                    if (key & GenericPlatform.AdgAny) {
                        row[AdblockSyntax.Adg][key] = data.shared[data.map[key]];
                    }
                    else if (key & GenericPlatform.UboAny) {
                        row[AdblockSyntax.Ubo][key] = data.shared[data.map[key]];
                    }
                    else if (key & GenericPlatform.AbpAny) {
                        row[AdblockSyntax.Abp][key] = data.shared[data.map[key]];
                    }
                }
                result.push(row);
            }
            return result;
        }
    }

    /**
     * Simple deep freeze implementation.
     * It freezes the object and all its properties recursively.
     *
     * @param object Object to freeze.
     *
     * @returns Frozen object.
     *
     * @template T Type of the object to freeze.
     *
     * @see {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/freeze#deep_freezing}
     */
    const deepFreeze = (object) => {
        // Retrieve the property names defined on object
        const propNames = Reflect.ownKeys(object);
        // Freeze properties before freezing self
        for (const name of propNames) {
            const value = object[name];
            if ((value && typeof value === 'object') || typeof value === 'function') {
                deepFreeze(value);
            }
        }
        return Object.freeze(object);
    };

    /**
     * @file Compatibility tables for modifiers.
     */
    /**
     * Transforms the name of the modifier to a normalized form.
     * This is a special case: the noop modifier normally '_', but it can consist of any number of characters,
     * e.g. '____' is also valid. In this case, we need to normalize the name to '_'.
     *
     * @param name Modifier name to normalize.
     * @returns Normalized modifier name.
     */
    const noopModifierNameNormalizer = (name) => {
        if (name.startsWith(UNDERSCORE)) {
            if (name.split(EMPTY).every((char) => char === UNDERSCORE)) {
                // in compatibility tables, we just store '_', so we need to reduce the number of underscores to 1
                // before checking the existence of the noop modifier
                return UNDERSCORE;
            }
        }
        return name;
    };
    /**
     * Compatibility table for modifiers.
     */
    class ModifiersCompatibilityTable extends CompatibilityTableBase {
        /**
         * Creates a new instance of the compatibility table for modifiers.
         *
         * @param data Compatibility table data.
         */
        constructor(data) {
            super(data, noopModifierNameNormalizer);
        }
    }
    /**
     * Deep freeze the compatibility table data to avoid accidental modifications.
     */
    deepFreeze(modifiersCompatibilityTableData_1);
    /**
     * Compatibility table instance for modifiers.
     */
    const modifiersCompatibilityTable = new ModifiersCompatibilityTable(modifiersCompatibilityTableData_1);

    /**
     * @file Base class for converters
     *
     * TS doesn't support abstract static methods, so we should use
     * a workaround and extend this class instead of implementing it
     */
    /* eslint-disable jsdoc/require-returns-check */
    /* eslint-disable @typescript-eslint/no-unused-vars */
    /**
     * Basic class for rule converters
     */
    class ConverterBase {
        /**
         * Converts some data to AdGuard format
         *
         * @param data Data to convert
         * @returns An object which follows the {@link ConversionResult} interface. Its `result` property contains
         * the converted node, and its `isConverted` flag indicates whether the original node was converted.
         * If the node was not converted, the result will contain the original node with the same object reference
         * @throws If the data is invalid or incompatible
         */
        static convertToAdg(data) {
            throw new NotImplementedError();
        }
        /**
         * Converts some data to Adblock Plus format
         *
         * @param data Data to convert
         * @returns An object which follows the {@link ConversionResult} interface. Its `result` property contains
         * the converted node, and its `isConverted` flag indicates whether the original node was converted.
         * If the node was not converted, the result will contain the original node with the same object reference
         * @throws If the data is invalid or incompatible
         */
        static convertToAbp(data) {
            throw new NotImplementedError();
        }
        /**
         * Converts some data to uBlock Origin format
         *
         * @param data Data to convert
         * @returns An object which follows the {@link ConversionResult} interface. Its `result` property contains
         * the converted node, and its `isConverted` flag indicates whether the original node was converted.
         * If the node was not converted, the result will contain the original node with the same object reference
         * @throws If the data is invalid or incompatible
         */
        static convertToUbo(data) {
            throw new NotImplementedError();
        }
    }

    /**
     * @file Base class for rule converters
     *
     * TS doesn't support abstract static methods, so we should use
     * a workaround and extend this class instead of implementing it
     */
    /* eslint-disable jsdoc/require-returns-check */
    /* eslint-disable @typescript-eslint/no-unused-vars */
    /**
     * Basic class for rule converters
     */
    class RuleConverterBase extends ConverterBase {
        /**
         * Converts an adblock filtering rule to AdGuard format, if possible.
         *
         * @param rule Rule node to convert
         * @returns An object which follows the {@link NodeConversionResult} interface. Its `result` property contains
         * the array of converted rule nodes, and its `isConverted` flag indicates whether the original rule was converted.
         * If the rule was not converted, the result array will contain the original node with the same object reference
         * @throws If the rule is invalid or cannot be converted
         */
        static convertToAdg(rule) {
            throw new NotImplementedError();
        }
        /**
         * Converts an adblock filtering rule to Adblock Plus format, if possible.
         *
         * @param rule Rule node to convert
         * @returns An object which follows the {@link NodeConversionResult} interface. Its `result` property contains
         * the array of converted rule nodes, and its `isConverted` flag indicates whether the original rule was converted.
         * If the rule was not converted, the result array will contain the original node with the same object reference
         * @throws If the rule is invalid or cannot be converted
         */
        static convertToAbp(rule) {
            throw new NotImplementedError();
        }
        /**
         * Converts an adblock filtering rule to uBlock Origin format, if possible.
         *
         * @param rule Rule node to convert
         * @returns An object which follows the {@link NodeConversionResult} interface. Its `result` property contains
         * the array of converted rule nodes, and its `isConverted` flag indicates whether the original rule was converted.
         * If the rule was not converted, the result array will contain the original node with the same object reference
         * @throws If the rule is invalid or cannot be converted
         */
        static convertToUbo(rule) {
            throw new NotImplementedError();
        }
    }

    /**
     * @file Conversion result interface and helper functions
     */
    /**
     * Helper function to create a generic conversion result.
     *
     * @param result Conversion result
     * @param isConverted Indicates whether the input item was converted
     * @template T Type of the item to convert
     * @template U Type of the conversion result (defaults to `T`, but can be `T[]` as well)
     * @returns Generic conversion result
     */
    // eslint-disable-next-line max-len
    function createConversionResult(result, isConverted) {
        return {
            result,
            isConverted,
        };
    }
    /**
     * Helper function to create a node conversion result.
     *
     * @param nodes Array of nodes
     * @param isConverted Indicates whether the input item was converted
     * @template T Type of the node (extends `Node`)
     * @returns Node conversion result
     */
    function createNodeConversionResult(nodes, isConverted) {
        return createConversionResult(nodes, isConverted);
    }

    /**
     * @file Comment rule converter
     */
    /**
     * Comment rule converter class
     *
     * @todo Implement `convertToUbo` and `convertToAbp`
     */
    class CommentRuleConverter extends RuleConverterBase {
        /**
         * Converts a comment rule to AdGuard format, if possible.
         *
         * @param rule Rule node to convert
         * @returns An object which follows the {@link NodeConversionResult} interface. Its `result` property contains
         * the array of converted rule nodes, and its `isConverted` flag indicates whether the original rule was converted.
         * If the rule was not converted, the result array will contain the original node with the same object reference
         * @throws If the rule is invalid or cannot be converted
         */
        static convertToAdg(rule) {
            // TODO: Add support for other comment types, if needed
            // Main task is # -> ! conversion
            switch (rule.type) {
                case CommentRuleType.CommentRule:
                    // Check if the rule needs to be converted
                    if (rule.type === CommentRuleType.CommentRule && rule.marker.value === CommentMarker.Hashmark) {
                        // Add a ! to the beginning of the comment
                        // TODO: Replace with custom clone method
                        const ruleClone = clone(rule);
                        ruleClone.marker.value = CommentMarker.Regular;
                        // Add the hashmark to the beginning of the comment text
                        ruleClone.text.value = `${SPACE}${CommentMarker.Hashmark}${ruleClone.text.value}`;
                        return createNodeConversionResult([ruleClone], true);
                    }
                    return createNodeConversionResult([rule], false);
                // Leave any other comment rule as is
                default:
                    return createNodeConversionResult([rule], false);
            }
        }
    }

    /**
     * @file Regular expression utilities
     */
    // Special RegExp constants
    const REGEX_START = CARET; // '^'
    const REGEX_END = DOLLAR_SIGN; // '$'
    const REGEX_ANY_CHARACTERS = DOT + ASTERISK; // '.*'
    // Special adblock pattern symbols and their RegExp equivalents
    const ADBLOCK_URL_START = PIPE + PIPE; // '||'
    const ADBLOCK_URL_START_REGEX = '^(http|https|ws|wss)://([a-z0-9-_.]+\\.)?';
    const ADBLOCK_URL_SEPARATOR = CARET; // '^'
    const ADBLOCK_URL_SEPARATOR_REGEX = '([^ a-zA-Z0-9.%_-]|$)';
    const ADBLOCK_WILDCARD = ASTERISK; // '*'
    const ADBLOCK_WILDCARD_REGEX = REGEX_ANY_CHARACTERS;
    // Negation wrapper for RegExp patterns
    const REGEX_NEGATION_PREFIX = '^((?!';
    const REGEX_NEGATION_SUFFIX = ').)*$';
    /**
     * Special RegExp symbols
     *
     * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions#special-escape
     */
    const SPECIAL_REGEX_SYMBOLS = new Set([
        ASTERISK,
        CARET,
        CLOSE_CURLY_BRACKET,
        CLOSE_PARENTHESIS,
        CLOSE_SQUARE_BRACKET,
        DOLLAR_SIGN,
        DOT,
        ESCAPE_CHARACTER,
        OPEN_CURLY_BRACKET,
        OPEN_PARENTHESIS,
        OPEN_SQUARE_BRACKET,
        PIPE,
        PLUS,
        QUESTION_MARK,
        SLASH,
    ]);
    /**
     * Utility functions for working with RegExp patterns
     */
    class RegExpUtils {
        /**
         * Checks whether a string possibly is a RegExp pattern.
         * Flags are not supported.
         *
         * Note: it does not perform a full validation of the pattern,
         * it just checks if the string starts and ends with a slash.
         *
         * @param pattern - Pattern to check
         * @returns `true` if the string is a RegExp pattern, `false` otherwise
         */
        static isRegexPattern(pattern) {
            const trimmedPattern = pattern.trim();
            // Avoid false positives
            return trimmedPattern.length > REGEX_MARKER.length * 2
                && trimmedPattern.startsWith(REGEX_MARKER)
                && trimmedPattern.endsWith(REGEX_MARKER)
                && trimmedPattern[REGEX_MARKER.length - 2] !== ESCAPE_CHARACTER;
        }
        /**
         * Negates a RegExp pattern. Technically, this method wraps the pattern in `^((?!` and `).)*$`.
         *
         * RegExp modifiers are not supported.
         *
         * @param pattern Pattern to negate (can be wrapped in slashes or not)
         * @returns Negated RegExp pattern
         */
        static negateRegexPattern(pattern) {
            let result = pattern.trim();
            let slashes = false;
            // Remove the leading and trailing slashes (/)
            if (RegExpUtils.isRegexPattern(result)) {
                result = result.substring(REGEX_MARKER.length, result.length - REGEX_MARKER.length);
                slashes = true;
            }
            // Only negate the pattern if it's not already negated
            if (!(result.startsWith(REGEX_NEGATION_PREFIX) && result.endsWith(REGEX_NEGATION_SUFFIX))) {
                // Remove leading caret (^)
                if (result.startsWith(REGEX_START)) {
                    result = result.substring(REGEX_START.length);
                }
                // Remove trailing dollar sign ($)
                if (result.endsWith(REGEX_END)) {
                    result = result.substring(0, result.length - REGEX_END.length);
                }
                // Wrap the pattern in the negation
                result = `${REGEX_NEGATION_PREFIX}${result}${REGEX_NEGATION_SUFFIX}`;
            }
            // Add the leading and trailing slashes back if they were there
            if (slashes) {
                result = `${REGEX_MARKER}${result}${REGEX_MARKER}`;
            }
            return result;
        }
        /**
         * Converts a basic adblock rule pattern to a RegExp pattern. Based on
         * https://github.com/AdguardTeam/tsurlfilter/blob/9b26e0b4a0e30b87690bc60f7cf377d112c3085c/packages/tsurlfilter/src/rules/simple-regex.ts#L219
         *
         * @param pattern Pattern to convert
         * @returns RegExp equivalent of the pattern
         * @see {@link https://kb.adguard.com/en/general/how-to-create-your-own-ad-filters#basic-rules}
         */
        static patternToRegexp(pattern) {
            const trimmed = pattern.trim();
            // Return regex for any character sequence if the pattern is just |, ||, * or empty
            if (trimmed === ADBLOCK_URL_START
                || trimmed === PIPE
                || trimmed === ADBLOCK_WILDCARD
                || trimmed === EMPTY) {
                return REGEX_ANY_CHARACTERS;
            }
            // If the pattern is already a RegExp, just return it, but remove the leading and trailing slashes
            if (RegExpUtils.isRegexPattern(pattern)) {
                return pattern.substring(REGEX_MARKER.length, pattern.length - REGEX_MARKER.length);
            }
            let result = EMPTY;
            let offset = 0;
            let len = trimmed.length;
            // Handle leading pipes
            if (trimmed[0] === PIPE) {
                if (trimmed[1] === PIPE) {
                    // Replace adblock url start (||) with its RegExp equivalent
                    result += ADBLOCK_URL_START_REGEX;
                    offset = ADBLOCK_URL_START.length;
                }
                else {
                    // Replace single pipe (|) with the RegExp start symbol (^)
                    result += REGEX_START;
                    offset = REGEX_START.length;
                }
            }
            // Handle trailing pipes
            let trailingPipe = false;
            if (trimmed.endsWith(PIPE)) {
                trailingPipe = true;
                len -= PIPE.length;
            }
            // Handle the rest of the pattern, if any
            for (; offset < len; offset += 1) {
                if (trimmed[offset] === ADBLOCK_WILDCARD) {
                    // Replace adblock wildcard (*) with its RegExp equivalent
                    result += ADBLOCK_WILDCARD_REGEX;
                }
                else if (trimmed[offset] === ADBLOCK_URL_SEPARATOR) {
                    // Replace adblock url separator (^) with its RegExp equivalent
                    result += ADBLOCK_URL_SEPARATOR_REGEX;
                }
                else if (SPECIAL_REGEX_SYMBOLS.has(trimmed[offset])) {
                    // Escape special RegExp symbols (we handled pipe (|) and asterisk (*) already)
                    result += ESCAPE_CHARACTER + trimmed[offset];
                }
                else {
                    // Just add any other character
                    result += trimmed[offset];
                }
            }
            // Handle trailing pipes
            if (trailingPipe) {
                // Replace trailing pipe (|) with the RegExp end symbol ($)
                result += REGEX_END;
            }
            return result;
        }
    }

    /**
     * @file Custom clone functions for AST nodes, this is probably the most efficient way to clone AST nodes.
     * @todo Maybe move them to parser classes as 'clone' methods
     */
    /**
     * Clones a scriptlet rule node.
     *
     * @param node Node to clone
     * @returns Cloned node
     */
    function cloneScriptletRuleNode(node) {
        return {
            type: node.type,
            children: node.children.map((child) => (isNull$1(child) ? null : { ...child })),
        };
    }
    /**
     * Clones a domain list node.
     *
     * @param node Node to clone
     * @returns Cloned node
     */
    function cloneDomainListNode(node) {
        return {
            type: node.type,
            separator: node.separator,
            children: node.children.map((domain) => ({ ...domain })),
        };
    }
    /**
     * Clones a modifier list node.
     *
     * @param node Node to clone
     * @returns Cloned node
     */
    function cloneModifierListNode(node) {
        return {
            type: node.type,
            children: node.children.map((modifier) => {
                const res = {
                    type: modifier.type,
                    exception: modifier.exception,
                    name: { ...modifier.name },
                };
                if (modifier.value) {
                    res.value = { ...modifier.value };
                }
                return res;
            }),
        };
    }

    /**
     * @file HTML filtering rule converter
     */
    /**
     * From the AdGuard docs:
     * Specifies the maximum length for content of HTML element. If this parameter is
     * set and the content length exceeds the value, a rule does not apply to the element.
     * If this parameter is not specified, the max-length is considered to be 8192 (8 KB).
     * When converting from other formats, we set the max-length to 262144 (256 KB).
     *
     * @see {@link https://adguard.com/kb/general/ad-filtering/create-own-filters/#html-filtering-rules}
     */
    const ADG_HTML_DEFAULT_MAX_LENGTH = 8192;
    const ADG_HTML_CONVERSION_MAX_LENGTH = ADG_HTML_DEFAULT_MAX_LENGTH * 32;
    const NOT_SPECIFIED = -1;
    var PseudoClasses$1;
    (function (PseudoClasses) {
        PseudoClasses["Contains"] = "contains";
        PseudoClasses["HasText"] = "has-text";
        PseudoClasses["MinTextLength"] = "min-text-length";
    })(PseudoClasses$1 || (PseudoClasses$1 = {}));
    var AttributeSelectors;
    (function (AttributeSelectors) {
        AttributeSelectors["MaxLength"] = "max-length";
        AttributeSelectors["MinLength"] = "min-length";
        AttributeSelectors["TagContent"] = "tag-content";
        AttributeSelectors["Wildcard"] = "wildcard";
    })(AttributeSelectors || (AttributeSelectors = {}));
    const SUPPORTED_UBO_PSEUDO_CLASSES = new Set([
        PseudoClasses$1.Contains,
        PseudoClasses$1.HasText,
        PseudoClasses$1.MinTextLength,
    ]);
    const ERROR_MESSAGES$2 = {
        ABP_NOT_SUPPORTED: 'Invalid rule, ABP does not support HTML filtering rules',
        TAG_SHOULD_BE_FIRST_CHILD: "Unexpected token '%s' with value '%s', tag selector should be the first child",
        EXPECTED_BUT_GOT_WITH_VALUE: "Expected '%s', but got '%s' with value '%s'",
        INVALID_ATTRIBUTE_NAME: "Attribute name should be an identifier, but got '%s' with value '%s'",
        // eslint-disable-next-line max-len
        INVALID_ATTRIBUTE_VALUE: `Expected '${getFormattedTokenName(TokenType$1.Ident)}' or '${getFormattedTokenName(TokenType$1.String)}' as attribute value, but got '%s' with value '%s`,
        INVALID_FLAG: "Unsupported attribute selector flag '%s'",
        INVALID_OPERATOR_FOR_ATTR: "Unsupported operator '%s' for '%s' attribute",
        VALUE_FOR_ATTR_SHOULD_BE_INT: "Value for '%s' attribute should be an integer, but got '%s'",
        INVALID_PSEUDO_CLASS: "Unsupported pseudo class '%s'",
        VALUE_FOR_PSEUDO_CLASS_SHOULD_BE_INT: "Value for '%s' pseudo class should be an integer, but got '%s'",
        // eslint-disable-next-line max-len
        REGEXP_NOT_SUPPORTED: "Cannot convert RegExp parameter '%s' from '%s' pseudo class, because converting RegExp patterns are not supported yet",
        ATTRIBUTE_SELECTOR_REQUIRES_VALUE: "Attribute selector '%s' requires a value",
        INVALID_ATTRIBUTE_SELECTOR_OPERATOR: "Unsupported attribute selector operator '%s'",
        VALUE_SHOULD_BE_SPECIFIED: 'Value should be specified if operator is specified',
        OPERATOR_SHOULD_BE_SPECIFIED: 'Operator should be specified if value is specified',
        UNEXPECTED_TOKEN_WITH_VALUE: "Unexpected token '%s' with value '%s'",
        FLAGS_NOT_SUPPORTED: 'Flags are not supported for attribute selectors',
    };
    /**
     * Convert `""` to `\"` within strings, because it does not compatible with the standard CSS syntax.
     *
     * @param selector CSS selector string
     * @returns Escaped CSS selector
     * @note In the legacy syntax, `""` is used to escape double quotes, but it cannot be used in the standard CSS syntax,
     * so we use conversion functions to handle this.
     * @see {@link https://kb.adguard.com/en/general/how-to-create-your-own-ad-filters#tag-content}
     */
    function escapeDoubleQuotes(selector) {
        let withinString = false;
        const buffer = [];
        for (let i = 0; i < selector.length; i += 1) {
            if (!withinString && selector[i] === DOUBLE_QUOTE_MARKER) {
                withinString = true;
                buffer.push(selector[i]);
            }
            else if (withinString && selector[i] === DOUBLE_QUOTE_MARKER && selector[i + 1] === DOUBLE_QUOTE_MARKER) {
                buffer.push(ESCAPE_CHARACTER);
                buffer.push(DOUBLE_QUOTE_MARKER);
                i += 1;
            }
            else if (withinString && selector[i] === DOUBLE_QUOTE_MARKER && selector[i + 1] !== DOUBLE_QUOTE_MARKER) {
                buffer.push(DOUBLE_QUOTE_MARKER);
                withinString = false;
            }
            else {
                buffer.push(selector[i]);
            }
        }
        return buffer.join(EMPTY);
    }
    /**
     * Convert escaped double quotes `\"` to `""` within strings.
     *
     * @param selector CSS selector string
     * @returns Unescaped CSS selector
     * @note In the legacy syntax, `""` is used to escape double quotes, but it cannot be used in the standard CSS syntax,
     * so we use conversion functions to handle this.
     * @see {@link https://kb.adguard.com/en/general/how-to-create-your-own-ad-filters#tag-content}
     */
    function unescapeDoubleQuotes(selector) {
        let withinString = false;
        const buffer = [];
        for (let i = 0; i < selector.length; i += 1) {
            if (selector[i] === DOUBLE_QUOTE_MARKER && selector[i - 1] !== ESCAPE_CHARACTER) {
                withinString = !withinString;
                buffer.push(selector[i]);
            }
            else if (withinString && selector[i] === ESCAPE_CHARACTER && selector[i + 1] === DOUBLE_QUOTE_MARKER) {
                buffer.push(DOUBLE_QUOTE_MARKER);
            }
            else {
                buffer.push(selector[i]);
            }
        }
        return buffer.join(EMPTY);
    }
    /**
     * Helper function to render an attribute selector
     *
     * @param attr Attribute name
     * @param op Operator (optional)
     * @param value Attribute value (optional)
     * @param flags Attribute flags (optional)
     * @returns Rendered attribute selector string
     */
    function renderAttrSelector(attr, op, value, flags) {
        const result = [];
        result.push(OPEN_SQUARE_BRACKET);
        result.push(attr);
        if (op !== undefined) {
            if (value === undefined) {
                throw new Error(ERROR_MESSAGES$2.VALUE_SHOULD_BE_SPECIFIED);
            }
            result.push(op);
        }
        if (value !== undefined) {
            if (!op) {
                throw new Error(ERROR_MESSAGES$2.OPERATOR_SHOULD_BE_SPECIFIED);
            }
            result.push(DOUBLE_QUOTE_MARKER);
            result.push(value);
            result.push(DOUBLE_QUOTE_MARKER);
        }
        if (flags !== undefined) {
            result.push(SPACE);
            result.push(flags);
        }
        result.push(CLOSE_SQUARE_BRACKET);
        return result.join(EMPTY);
    }
    /**
     * HTML filtering rule converter class
     *
     * @todo Implement `convertToUbo` (ABP currently doesn't support HTML filtering rules)
     */
    class HtmlRuleConverter extends RuleConverterBase {
        /**
         * Converts a HTML rule to AdGuard syntax, if possible. Also can be used to convert
         * AdGuard rules to AdGuard syntax to validate them.
         *
         * _Note:_ uBlock Origin supports multiple selectors within a single rule, but AdGuard doesn't,
         * so the following rule
         * ```
         * example.com##^div[attr1="value1"][attr2="value2"], script:has-text(value)
         * ```
         * will be converted to multiple AdGuard rules:
         * ```
         * example.com$$div[attr1="value1"][attr2="value2"][max-length="262144"]
         * example.com$$script[tag-content="value"][max-length="262144"]
         * ```
         *
         * @param rule Rule node to convert
         * @returns An object which follows the {@link NodeConversionResult} interface. Its `result` property contains
         * the array of converted rule nodes, and its `isConverted` flag indicates whether the original rule was converted.
         * If the rule was not converted, the result array will contain the original node with the same object reference
         * @throws If the rule is invalid or cannot be converted
         */
        static convertToAdg(rule) {
            // Ignore AdGuard rules
            if (rule.syntax === AdblockSyntax.Adg) {
                return createNodeConversionResult([rule], false);
            }
            if (rule.syntax === AdblockSyntax.Abp) {
                throw new RuleConversionError(ERROR_MESSAGES$2.ABP_NOT_SUPPORTED);
            }
            const source = escapeDoubleQuotes(rule.body.value);
            const stream = new CssTokenStream(source);
            const convertedSelector = [];
            const convertedSelectorList = [];
            let minLen = NOT_SPECIFIED;
            let maxLen = NOT_SPECIFIED;
            // Skip leading whitespace
            stream.skipWhitespace();
            // Skip ^
            stream.expect(TokenType$1.Delim, { value: UBO_HTML_MASK });
            stream.advance();
            while (!stream.isEof()) {
                const token = stream.getOrFail();
                if (token.type === TokenType$1.Ident) {
                    // Tag selector should be the first child, if present, but whitespace is allowed before it
                    if (convertedSelector.length !== 0 && stream.lookbehindForNonWs() !== undefined) {
                        throw new RuleConversionError(sprintf.sprintf(ERROR_MESSAGES$2.TAG_SHOULD_BE_FIRST_CHILD, getFormattedTokenName(token.type), source.slice(token.start, token.end)));
                    }
                    convertedSelector.push(source.slice(token.start, token.end));
                    stream.advance();
                }
                else if (token.type === TokenType$1.OpenSquareBracket) {
                    // Attribute selectors: https://developer.mozilla.org/en-US/docs/Web/CSS/Attribute_selectors#syntax
                    const { start } = token;
                    let tempToken;
                    // Advance opening square bracket
                    stream.advance();
                    // Skip optional whitespace after the opening square bracket
                    stream.skipWhitespace();
                    // Parse attribute name
                    tempToken = stream.getOrFail();
                    if (tempToken.type !== TokenType$1.Ident) {
                        throw new RuleConversionError(sprintf.sprintf(ERROR_MESSAGES$2.INVALID_ATTRIBUTE_NAME, getFormattedTokenName(tempToken.type), source.slice(tempToken.start, tempToken.end)));
                    }
                    const attr = source.slice(tempToken.start, tempToken.end);
                    stream.advance();
                    // Skip optional whitespace after the attribute name
                    stream.skipWhitespace();
                    // Maybe attribute selector ends here, because value is not required, like in '[disabled]'
                    tempToken = stream.getOrFail();
                    // So check if the next non whitespace token is a closing square bracket
                    if (tempToken.type === TokenType$1.CloseSquareBracket) {
                        const { end } = tempToken;
                        stream.advance();
                        // Special case for min-length and max-length attributes
                        if (attr === AttributeSelectors.MinLength || attr === AttributeSelectors.MaxLength) {
                            throw new RuleConversionError(sprintf.sprintf(ERROR_MESSAGES$2.ATTRIBUTE_SELECTOR_REQUIRES_VALUE, attr));
                        }
                        convertedSelector.push(source.slice(start, end));
                        continue;
                    }
                    // Next token should be a valid attribute selector operator
                    // Only '=' operator is supported
                    stream.expect(TokenType$1.Delim, { value: EQUALS });
                    // Advance the operator
                    stream.advance();
                    // Skip optional whitespace after the operator
                    stream.skipWhitespace();
                    // Parse attribute value
                    tempToken = stream.getOrFail();
                    // According to the spec, attribute value should be an identifier or a string
                    if (tempToken.type !== TokenType$1.Ident && tempToken.type !== TokenType$1.String) {
                        throw new RuleConversionError(sprintf.sprintf(ERROR_MESSAGES$2.INVALID_ATTRIBUTE_VALUE, getFormattedTokenName(tempToken.type), source.slice(tempToken.start, tempToken.end)));
                    }
                    const value = source.slice(tempToken.start, tempToken.end);
                    // Advance the attribute value
                    stream.advance();
                    // Skip optional whitespace after the attribute value
                    stream.skipWhitespace();
                    // Attribute selector may have flags - but AdGuard HTML filtering does not support them
                    tempToken = stream.getOrFail();
                    if (tempToken.type === TokenType$1.Ident) {
                        throw new RuleConversionError(sprintf.sprintf(ERROR_MESSAGES$2.FLAGS_NOT_SUPPORTED));
                    }
                    // Next token should be a closing square bracket
                    stream.expect(TokenType$1.CloseSquareBracket);
                    const { end } = stream.getOrFail();
                    stream.advance();
                    if (attr === AttributeSelectors.MinLength) {
                        // Min length attribute
                        const parsed = parseInt(value, 10);
                        if (Number.isNaN(parsed)) {
                            throw new RuleConversionError(sprintf.sprintf(ERROR_MESSAGES$2.VALUE_FOR_ATTR_SHOULD_BE_INT, attr, value));
                        }
                        minLen = parsed;
                    }
                    else if (attr === AttributeSelectors.MaxLength) {
                        // Max length attribute
                        const parsed = parseInt(value, 10);
                        if (Number.isNaN(parsed)) {
                            throw new RuleConversionError(sprintf.sprintf(ERROR_MESSAGES$2.VALUE_FOR_ATTR_SHOULD_BE_INT, attr, value));
                        }
                        maxLen = parsed;
                    }
                    else {
                        convertedSelector.push(source.slice(start, end));
                    }
                }
                else if (token.type === TokenType$1.Colon) {
                    let tempToken;
                    // Pseudo classes: https://developer.mozilla.org/en-US/docs/Web/CSS/Pseudo-classes#syntax
                    stream.advance();
                    // Next token should be a pseudo class name
                    stream.expect(TokenType$1.Function);
                    tempToken = stream.getOrFail();
                    const fn = source.slice(tempToken.start, tempToken.end - 1); // do not include '('
                    // Pseudo class should be supported
                    if (!SUPPORTED_UBO_PSEUDO_CLASSES.has(fn)) {
                        throw new RuleConversionError(sprintf.sprintf(ERROR_MESSAGES$2.INVALID_PSEUDO_CLASS, fn));
                    }
                    const paramStart = tempToken.end;
                    // Find the closing paren
                    stream.skipUntilBalanced();
                    tempToken = stream.getOrFail();
                    const paramEnd = tempToken.end;
                    // Get the parameter
                    const param = source.slice(paramStart, paramEnd - 1);
                    if (fn === PseudoClasses$1.MinTextLength) {
                        // Min text length pseudo class
                        // Parameter should be parsed as an integer
                        const parsed = parseInt(param, 10);
                        if (Number.isNaN(parsed)) {
                            throw new RuleConversionError(sprintf.sprintf(ERROR_MESSAGES$2.VALUE_FOR_PSEUDO_CLASS_SHOULD_BE_INT, fn, param));
                        }
                        minLen = parsed;
                    }
                    else if (fn === PseudoClasses$1.Contains || fn === PseudoClasses$1.HasText) {
                        // Contains and has-text pseudo classes
                        // Check if the argument is a RegExp
                        if (RegExpUtils.isRegexPattern(param)) {
                            // TODO: Add some support for RegExp patterns later
                            // Need to find a way to convert some RegExp patterns to glob patterns
                            throw new RuleConversionError(sprintf.sprintf(ERROR_MESSAGES$2.REGEXP_NOT_SUPPORTED, param, fn));
                        }
                        // Escape unescaped double quotes in the parameter
                        const paramEscaped = StringUtils.escapeCharacter(param, DOUBLE_QUOTE_MARKER);
                        convertedSelector.push(renderAttrSelector(AttributeSelectors.TagContent, EQUALS, paramEscaped));
                    }
                    stream.advance();
                }
                else if (token.type === TokenType$1.Comma && token.balance === 0) {
                    if (minLen !== NOT_SPECIFIED) {
                        convertedSelector.push(renderAttrSelector(AttributeSelectors.MinLength, EQUALS, minLen.toString()));
                    }
                    convertedSelector.push(renderAttrSelector(AttributeSelectors.MaxLength, EQUALS, maxLen !== NOT_SPECIFIED ? maxLen.toString() : ADG_HTML_CONVERSION_MAX_LENGTH.toString()));
                    convertedSelectorList.push(convertedSelector.join(EMPTY));
                    convertedSelector.length = 0;
                    stream.advance();
                }
                else if (token.type === TokenType$1.Whitespace) {
                    stream.advance();
                }
                else {
                    throw new RuleConversionError(sprintf.sprintf(ERROR_MESSAGES$2.UNEXPECTED_TOKEN_WITH_VALUE, getFormattedTokenName(token.type), source.slice(token.start, token.end)));
                }
            }
            if (convertedSelector.length !== 0) {
                if (minLen !== NOT_SPECIFIED) {
                    convertedSelector.push(renderAttrSelector(AttributeSelectors.MinLength, EQUALS, minLen.toString()));
                }
                convertedSelector.push(renderAttrSelector(AttributeSelectors.MaxLength, EQUALS, maxLen !== NOT_SPECIFIED ? maxLen.toString() : ADG_HTML_CONVERSION_MAX_LENGTH.toString()));
                convertedSelectorList.push(convertedSelector.join(EMPTY));
            }
            return createNodeConversionResult(
            // Since AdGuard HTML filtering rules do not support multiple selectors, we need to split each selector
            // into a separate rule node.
            convertedSelectorList.map((selector) => ({
                category: RuleCategory.Cosmetic,
                type: CosmeticRuleType.HtmlFilteringRule,
                syntax: AdblockSyntax.Adg,
                exception: rule.exception,
                domains: cloneDomainListNode(rule.domains),
                // Convert the separator based on the exception status
                separator: {
                    type: 'Value',
                    value: rule.exception
                        ? CosmeticRuleSeparator.AdgHtmlFilteringException
                        : CosmeticRuleSeparator.AdgHtmlFiltering,
                },
                body: {
                    type: 'Value',
                    value: unescapeDoubleQuotes(selector),
                },
            })), true);
        }
    }

    /**
     * @file Utility functions for working with scriptlet nodes
     */
    /**
     * Get name of the scriptlet from the scriptlet node
     *
     * @param scriptletNode Scriptlet node to get name of
     * @returns Name of the scriptlet
     * @throws If the scriptlet is empty
     */
    function getScriptletName(scriptletNode) {
        if (scriptletNode.children.length === 0) {
            throw new Error('Empty scriptlet');
        }
        return scriptletNode.children[0]?.value ?? EMPTY;
    }
    /**
     * Transform the nth argument of the scriptlet node
     *
     * @param scriptletNode Scriptlet node to transform argument of
     * @param index Index of the argument to transform (index 0 is the scriptlet name)
     * @param transform Function to transform the argument
     */
    function transformNthScriptletArgument(scriptletNode, index, transform) {
        const child = scriptletNode.children[index];
        if (!isUndefined$1(child)) {
            const transformed = transform(child?.value ?? null);
            if (isNull$1(transformed)) {
                // eslint-disable-next-line no-param-reassign
                scriptletNode.children[index] = null;
                return;
            }
            if (isNull$1(child)) {
                // eslint-disable-next-line no-param-reassign
                scriptletNode.children[index] = {
                    type: 'Value',
                    value: transformed,
                };
                return;
            }
            child.value = transformed;
        }
    }
    /**
     * Transform all arguments of the scriptlet node
     *
     * @param scriptletNode Scriptlet node to transform arguments of
     * @param transform Function to transform the arguments
     */
    function transformAllScriptletArguments(scriptletNode, transform) {
        for (let i = 0; i < scriptletNode.children.length; i += 1) {
            transformNthScriptletArgument(scriptletNode, i, transform);
        }
    }
    /**
     * Set name of the scriptlet.
     * Modifies input `scriptletNode` if needed.
     *
     * @param scriptletNode Scriptlet node to set name of
     * @param name Name to set
     */
    function setScriptletName(scriptletNode, name) {
        transformNthScriptletArgument(scriptletNode, 0, () => name);
    }
    /**
     * Set quote type of the scriptlet parameters
     *
     * @param scriptletNode Scriptlet node to set quote type of
     * @param quoteType Preferred quote type
     */
    function setScriptletQuoteType(scriptletNode, quoteType) {
        // null is a special value that means "no value", but we can't change its quote type,
        // so we need to convert it to empty string
        transformAllScriptletArguments(scriptletNode, (value) => QuoteUtils.setStringQuoteType(value ?? EMPTY, quoteType));
    }

    /**
     * @file Resource type schema.
     */
    /**
     * Resource type.
     *
     * @see {@link https://developer.chrome.com/docs/extensions/reference/declarativeNetRequest/#type-ResourceType}
     */
    var ResourceType;
    (function (ResourceType) {
        ResourceType["MainFrame"] = "main_frame";
        ResourceType["SubFrame"] = "sub_frame";
        ResourceType["Stylesheet"] = "stylesheet";
        ResourceType["Script"] = "script";
        ResourceType["Image"] = "image";
        ResourceType["Font"] = "font";
        ResourceType["Object"] = "object";
        ResourceType["XmlHttpRequest"] = "xmlhttprequest";
        ResourceType["Ping"] = "ping";
        ResourceType["Media"] = "media";
        ResourceType["WebSocket"] = "websocket";
        ResourceType["Other"] = "other";
    })(ResourceType || (ResourceType = {}));
    /**
     * Resource type schema.
     */
    const resourceTypeSchema = z.nativeEnum(ResourceType);

    /**
     * Map of resource types to their corresponding adblock modifier names.
     *
     * @note Record type is used to ensure that all resource types are present in the map.
     */
    const RESOURCE_TYPE_MODIFIER_MAP = Object.freeze({
        [ResourceType.MainFrame]: 'document',
        [ResourceType.SubFrame]: 'subdocument',
        [ResourceType.Stylesheet]: 'stylesheet',
        [ResourceType.Script]: 'script',
        [ResourceType.Image]: 'image',
        [ResourceType.Font]: 'font',
        [ResourceType.Object]: 'object',
        [ResourceType.XmlHttpRequest]: 'xmlhttprequest',
        [ResourceType.Ping]: 'ping',
        [ResourceType.Media]: 'media',
        [ResourceType.WebSocket]: 'websocket',
        [ResourceType.Other]: 'other',
    });
    /**
     * Gets the adblock modifier name for the given resource type.
     *
     * @param resourceType Resource type to get the modifier name for.
     * @param platform Platform to get the modifier for.
     *
     * @returns A string containing the adblock modifier name for the given resource type
     * or `null` if the modifier could not be found.
     */
    const getResourceTypeModifier = (resourceType, platform) => {
        const modifierName = RESOURCE_TYPE_MODIFIER_MAP[resourceType];
        if (!modifierName) {
            return null;
        }
        const modifierData = modifiersCompatibilityTable.getFirst(modifierName, platform);
        if (isNull$1(modifierData)) {
            return null;
        }
        return modifierData.name;
    };
    /**
     * Checks if the given resource type is valid.
     *
     * @param resourceType Resource type to check.
     *
     * @returns `true` if the resource type is valid, `false` otherwise.
     */
    const isValidResourceType = (resourceType) => {
        return Object.values(ResourceType).includes(resourceType);
    };

    /**
     * @file Compatibility tables for redirects.
     */
    /**
     * Prefix for resource redirection names.
     */
    const ABP_RESOURCE_PREFIX = 'abp-resource:';
    const ABP_RESOURCE_PREFIX_LENGTH = ABP_RESOURCE_PREFIX.length;
    /**
     * Normalizes the redirect name.
     *
     * @param name Redirect name to normalize.
     *
     * @returns Normalized redirect name.
     *
     * @example
     * redirectNameNormalizer('abp-resource:my-resource') // => 'my-resource'
     * redirectNameNormalizer('noop.js:99') // => 'noop.js'
     */
    const redirectNameNormalizer = (name) => {
        // Remove ABP resource prefix, if present
        if (name.startsWith(ABP_RESOURCE_PREFIX)) {
            return name.slice(ABP_RESOURCE_PREFIX_LENGTH);
        }
        // Remove :[integer] priority suffix from the name, if present
        // See:
        // - https://github.com/AdguardTeam/tsurlfilter/issues/59
        // - https://github.com/gorhill/uBlock/wiki/Static-filter-syntax#redirect
        const colonIndex = name.lastIndexOf(COLON);
        if (colonIndex !== -1 && /^\d+$/.test(name.slice(colonIndex + 1))) {
            return name.slice(0, colonIndex);
        }
        return name;
    };
    /**
     * Compatibility table for redirects.
     */
    class RedirectsCompatibilityTable extends CompatibilityTableBase {
        /**
         * Creates a new instance of the compatibility table for redirects.
         *
         * @param data Compatibility table data.
         */
        constructor(data) {
            super(data, redirectNameNormalizer);
        }
        /**
         * Gets the resource type adblock modifiers for the redirect for the given platform
         * based on the `resourceTypes` field.
         *
         * @param redirect Redirect name or redirect data.
         * @param platform Platform to get the modifiers for.
         *
         * @returns Set of resource type modifiers or an empty set if the redirect is not found or has no resource types.
         */
        getResourceTypeModifiers(redirect, platform) {
            let redirectData = null;
            if (isString(redirect)) {
                redirectData = this.getFirst(redirect, platform);
            }
            else {
                redirectData = redirect;
            }
            const modifierNames = new Set();
            if (isNull$1(redirectData) || isUndefined$1(redirectData.resourceTypes)) {
                return modifierNames;
            }
            for (const resourceType of redirectData.resourceTypes) {
                const modifierName = getResourceTypeModifier(resourceType, platform);
                if (isNull$1(modifierName)) {
                    continue;
                }
                modifierNames.add(modifierName);
            }
            return modifierNames;
        }
    }
    /**
     * Deep freeze the compatibility table data to avoid accidental modifications.
     */
    deepFreeze(redirectsCompatibilityTableData_1);
    /**
     * Compatibility table instance for redirects.
     */
    const redirectsCompatibilityTable = new RedirectsCompatibilityTable(redirectsCompatibilityTableData_1);

    /**
     * @file Compatibility tables for scriptlets.
     */
    /**
     * Compatibility table for scriptlets.
     */
    class ScriptletsCompatibilityTable extends CompatibilityTableBase {
    }
    /**
     * Deep freeze the compatibility table data to avoid accidental modifications.
     */
    deepFreeze(scriptletsCompatibilityTableData_1);
    /**
     * Compatibility table instance for scriptlets.
     */
    const scriptletsCompatibilityTable = new ScriptletsCompatibilityTable(scriptletsCompatibilityTableData_1);

    /* eslint-disable no-bitwise */
    /**
     * @file Platform schema.
     */
    /**
     * Platform separator, e.g. 'adg_os_any|adg_safari_any' means any AdGuard OS platform and
     * any AdGuard Safari content blocker platform.
     */
    const PLATFORM_SEPARATOR = '|';
    /**
     * Platform negation character, e.g. 'adg_any|~adg_safari_any' means any AdGuard product except
     * Safari content blockers.
     */
    const PLATFORM_NEGATION = '~';
    /**
     * Parses a raw platform string into a platform bitmask.
     *
     * @param rawPlatforms Raw platform string, e.g. 'adg_safari_any|adg_os_any'.
     *
     * @returns Platform bitmask.
     */
    const parseRawPlatforms = (rawPlatforms) => {
        // e.g. 'adg_safari_any|adg_os_any'
        const rawPlatformList = rawPlatforms
            .split(PLATFORM_SEPARATOR)
            .map((rawPlatform) => rawPlatform.trim());
        let result = 0;
        for (let rawPlatform of rawPlatformList) {
            // negation, e.g. 'adg_any|~adg_safari_any' means any AdGuard product except Safari content blockers
            let negated = false;
            if (rawPlatform.startsWith(PLATFORM_NEGATION)) {
                negated = true;
                rawPlatform = rawPlatform.slice(1).trim();
            }
            const platform = SPECIFIC_PLATFORM_MAP.get(rawPlatform) ?? GENERIC_PLATFORM_MAP.get(rawPlatform);
            if (isUndefined$1(platform)) {
                throw new Error(`Unknown platform: ${rawPlatform}`);
            }
            if (negated) {
                result &= ~platform;
            }
            else {
                result |= platform;
            }
        }
        if (result === 0) {
            throw new Error('No platforms specified');
        }
        return result;
    };
    /**
     * Platform schema.
     */
    z
        .string()
        .min(1)
        .transform((value) => parseRawPlatforms(value));

    function getDefaultExportFromCjs (x) {
    	return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, 'default') ? x['default'] : x;
    }

    var mapObj$1 = {exports: {}};

    const isObject$1 = value => typeof value === 'object' && value !== null;
    const mapObjectSkip = Symbol('skip');

    // Customized for this use-case
    const isObjectCustom = value =>
    	isObject$1(value) &&
    	!(value instanceof RegExp) &&
    	!(value instanceof Error) &&
    	!(value instanceof Date);

    const mapObject = (object, mapper, options, isSeen = new WeakMap()) => {
    	options = {
    		deep: false,
    		target: {},
    		...options
    	};

    	if (isSeen.has(object)) {
    		return isSeen.get(object);
    	}

    	isSeen.set(object, options.target);

    	const {target} = options;
    	delete options.target;

    	const mapArray = array => array.map(element => isObjectCustom(element) ? mapObject(element, mapper, options, isSeen) : element);
    	if (Array.isArray(object)) {
    		return mapArray(object);
    	}

    	for (const [key, value] of Object.entries(object)) {
    		const mapResult = mapper(key, value, object);

    		if (mapResult === mapObjectSkip) {
    			continue;
    		}

    		let [newKey, newValue, {shouldRecurse = true} = {}] = mapResult;

    		// Drop `__proto__` keys.
    		if (newKey === '__proto__') {
    			continue;
    		}

    		if (options.deep && shouldRecurse && isObjectCustom(newValue)) {
    			newValue = Array.isArray(newValue) ?
    				mapArray(newValue) :
    				mapObject(newValue, mapper, options, isSeen);
    		}

    		target[newKey] = newValue;
    	}

    	return target;
    };

    mapObj$1.exports = (object, mapper, options) => {
    	if (!isObject$1(object)) {
    		throw new TypeError(`Expected an object, got \`${object}\` (${typeof object})`);
    	}

    	return mapObject(object, mapper, options);
    };

    mapObj$1.exports.mapObjectSkip = mapObjectSkip;

    var mapObjExports = mapObj$1.exports;

    var camelcase = {exports: {}};

    const UPPERCASE = /[\p{Lu}]/u;
    const LOWERCASE = /[\p{Ll}]/u;
    const LEADING_CAPITAL = /^[\p{Lu}](?![\p{Lu}])/gu;
    const IDENTIFIER = /([\p{Alpha}\p{N}_]|$)/u;
    const SEPARATORS = /[_.\- ]+/;

    const LEADING_SEPARATORS = new RegExp('^' + SEPARATORS.source);
    const SEPARATORS_AND_IDENTIFIER = new RegExp(SEPARATORS.source + IDENTIFIER.source, 'gu');
    const NUMBERS_AND_IDENTIFIER = new RegExp('\\d+' + IDENTIFIER.source, 'gu');

    const preserveCamelCase = (string, toLowerCase, toUpperCase) => {
    	let isLastCharLower = false;
    	let isLastCharUpper = false;
    	let isLastLastCharUpper = false;

    	for (let i = 0; i < string.length; i++) {
    		const character = string[i];

    		if (isLastCharLower && UPPERCASE.test(character)) {
    			string = string.slice(0, i) + '-' + string.slice(i);
    			isLastCharLower = false;
    			isLastLastCharUpper = isLastCharUpper;
    			isLastCharUpper = true;
    			i++;
    		} else if (isLastCharUpper && isLastLastCharUpper && LOWERCASE.test(character)) {
    			string = string.slice(0, i - 1) + '-' + string.slice(i - 1);
    			isLastLastCharUpper = isLastCharUpper;
    			isLastCharUpper = false;
    			isLastCharLower = true;
    		} else {
    			isLastCharLower = toLowerCase(character) === character && toUpperCase(character) !== character;
    			isLastLastCharUpper = isLastCharUpper;
    			isLastCharUpper = toUpperCase(character) === character && toLowerCase(character) !== character;
    		}
    	}

    	return string;
    };

    const preserveConsecutiveUppercase = (input, toLowerCase) => {
    	LEADING_CAPITAL.lastIndex = 0;

    	return input.replace(LEADING_CAPITAL, m1 => toLowerCase(m1));
    };

    const postProcess = (input, toUpperCase) => {
    	SEPARATORS_AND_IDENTIFIER.lastIndex = 0;
    	NUMBERS_AND_IDENTIFIER.lastIndex = 0;

    	return input.replace(SEPARATORS_AND_IDENTIFIER, (_, identifier) => toUpperCase(identifier))
    		.replace(NUMBERS_AND_IDENTIFIER, m => toUpperCase(m));
    };

    const camelCase$1 = (input, options) => {
    	if (!(typeof input === 'string' || Array.isArray(input))) {
    		throw new TypeError('Expected the input to be `string | string[]`');
    	}

    	options = {
    		pascalCase: false,
    		preserveConsecutiveUppercase: false,
    		...options
    	};

    	if (Array.isArray(input)) {
    		input = input.map(x => x.trim())
    			.filter(x => x.length)
    			.join('-');
    	} else {
    		input = input.trim();
    	}

    	if (input.length === 0) {
    		return '';
    	}

    	const toLowerCase = options.locale === false ?
    		string => string.toLowerCase() :
    		string => string.toLocaleLowerCase(options.locale);
    	const toUpperCase = options.locale === false ?
    		string => string.toUpperCase() :
    		string => string.toLocaleUpperCase(options.locale);

    	if (input.length === 1) {
    		return options.pascalCase ? toUpperCase(input) : toLowerCase(input);
    	}

    	const hasUpperCase = input !== toLowerCase(input);

    	if (hasUpperCase) {
    		input = preserveCamelCase(input, toLowerCase, toUpperCase);
    	}

    	input = input.replace(LEADING_SEPARATORS, '');

    	if (options.preserveConsecutiveUppercase) {
    		input = preserveConsecutiveUppercase(input, toLowerCase);
    	} else {
    		input = toLowerCase(input);
    	}

    	if (options.pascalCase) {
    		input = toUpperCase(input.charAt(0)) + input.slice(1);
    	}

    	return postProcess(input, toUpperCase);
    };

    camelcase.exports = camelCase$1;
    // TODO: Remove this for the next major release
    camelcase.exports.default = camelCase$1;

    var camelcaseExports = camelcase.exports;

    class QuickLRU {
    	constructor(options = {}) {
    		if (!(options.maxSize && options.maxSize > 0)) {
    			throw new TypeError('`maxSize` must be a number greater than 0');
    		}

    		this.maxSize = options.maxSize;
    		this.onEviction = options.onEviction;
    		this.cache = new Map();
    		this.oldCache = new Map();
    		this._size = 0;
    	}

    	_set(key, value) {
    		this.cache.set(key, value);
    		this._size++;

    		if (this._size >= this.maxSize) {
    			this._size = 0;

    			if (typeof this.onEviction === 'function') {
    				for (const [key, value] of this.oldCache.entries()) {
    					this.onEviction(key, value);
    				}
    			}

    			this.oldCache = this.cache;
    			this.cache = new Map();
    		}
    	}

    	get(key) {
    		if (this.cache.has(key)) {
    			return this.cache.get(key);
    		}

    		if (this.oldCache.has(key)) {
    			const value = this.oldCache.get(key);
    			this.oldCache.delete(key);
    			this._set(key, value);
    			return value;
    		}
    	}

    	set(key, value) {
    		if (this.cache.has(key)) {
    			this.cache.set(key, value);
    		} else {
    			this._set(key, value);
    		}

    		return this;
    	}

    	has(key) {
    		return this.cache.has(key) || this.oldCache.has(key);
    	}

    	peek(key) {
    		if (this.cache.has(key)) {
    			return this.cache.get(key);
    		}

    		if (this.oldCache.has(key)) {
    			return this.oldCache.get(key);
    		}
    	}

    	delete(key) {
    		const deleted = this.cache.delete(key);
    		if (deleted) {
    			this._size--;
    		}

    		return this.oldCache.delete(key) || deleted;
    	}

    	clear() {
    		this.cache.clear();
    		this.oldCache.clear();
    		this._size = 0;
    	}

    	* keys() {
    		for (const [key] of this) {
    			yield key;
    		}
    	}

    	* values() {
    		for (const [, value] of this) {
    			yield value;
    		}
    	}

    	* [Symbol.iterator]() {
    		for (const item of this.cache) {
    			yield item;
    		}

    		for (const item of this.oldCache) {
    			const [key] = item;
    			if (!this.cache.has(key)) {
    				yield item;
    			}
    		}
    	}

    	get size() {
    		let oldCacheSize = 0;
    		for (const key of this.oldCache.keys()) {
    			if (!this.cache.has(key)) {
    				oldCacheSize++;
    			}
    		}

    		return Math.min(this._size + oldCacheSize, this.maxSize);
    	}
    }

    var quickLru = QuickLRU;

    const mapObj = mapObjExports;
    const camelCase = camelcaseExports;
    const QuickLru = quickLru;

    const has = (array, key) => array.some(x => {
    	if (typeof x === 'string') {
    		return x === key;
    	}

    	x.lastIndex = 0;
    	return x.test(key);
    });

    const cache = new QuickLru({maxSize: 100000});

    // Reproduces behavior from `map-obj`
    const isObject$2 = value =>
    	typeof value === 'object' &&
    	value !== null &&
    	!(value instanceof RegExp) &&
    	!(value instanceof Error) &&
    	!(value instanceof Date);

    const camelCaseConvert = (input, options) => {
    	if (!isObject$2(input)) {
    		return input;
    	}

    	options = {
    		deep: false,
    		pascalCase: false,
    		...options
    	};

    	const {exclude, pascalCase, stopPaths, deep} = options;

    	const stopPathsSet = new Set(stopPaths);

    	const makeMapper = parentPath => (key, value) => {
    		if (deep && isObject$2(value)) {
    			const path = parentPath === undefined ? key : `${parentPath}.${key}`;

    			if (!stopPathsSet.has(path)) {
    				value = mapObj(value, makeMapper(path));
    			}
    		}

    		if (!(exclude && has(exclude, key))) {
    			const cacheKey = pascalCase ? `${key}_` : key;

    			if (cache.has(cacheKey)) {
    				key = cache.get(cacheKey);
    			} else {
    				const returnValue = camelCase(key, {pascalCase, locale: false});

    				if (key.length < 100) { // Prevent abuse
    					cache.set(cacheKey, returnValue);
    				}

    				key = returnValue;
    			}
    		}

    		return [key, value];
    	};

    	return mapObj(input, makeMapper(undefined));
    };

    var camelcaseKeys = (input, options) => {
    	if (Array.isArray(input)) {
    		return Object.keys(input).map(key => camelCaseConvert(input[key], options));
    	}

    	return camelCaseConvert(input, options);
    };

    var camelCaseKeys = /*@__PURE__*/getDefaultExportFromCjs(camelcaseKeys);

    /**
     * @file Zod camelCase utility.
     */
    // eslint-disable-next-line import/no-extraneous-dependencies
    /**
     * Transforms Zod schema to camelCase.
     *
     * @param zod Zod schema.
     *
     * @returns Zod schema with camelCase properties.
     *
     * @see {@link https://github.com/colinhacks/zod/issues/486#issuecomment-1501097361}
     */
    const zodToCamelCase = (zod) => {
        return zod.transform((val) => camelCaseKeys(val));
    };

    /**
     * @file Base compatibility data schema, which is commonly used in compatibility tables.
     */
    /**
     * Zod schema for boolean values. Accepts both boolean and string values.
     */
    const booleanSchema = z.union([
        z.string().transform((val) => val.trim().toLowerCase() === 'true'),
        z.boolean(),
    ]);
    /**
     * Zod schema for non-empty string values.
     */
    const nonEmptyStringSchema = z
        .string()
        .transform((val) => val.trim())
        .pipe(z.string().min(1));
    /**
     * Zod schema for base compatibility data.
     * Here we use snake_case properties because the compatibility data is stored in YAML files.
     */
    const baseCompatibilityDataSchema = z.object({
        /**
         * Name of the actual entity.
         */
        name: nonEmptyStringSchema,
        /**
         * List of aliases for the entity (if any).
         */
        aliases: z.array(nonEmptyStringSchema).nullable().default(null),
        /**
         * Short description of the actual entity.
         * If not specified or it's value is `null`, then the description is not available.
         */
        description: nonEmptyStringSchema.nullable().default(null),
        /**
         * Link to the documentation. If not specified or it's value is `null`, then the documentation is not available.
         */
        docs: nonEmptyStringSchema.nullable().default(null),
        /**
         * The version of the adblocker in which the entity was added.
         * For AdGuard resources, the version of the library is specified.
         */
        version_added: nonEmptyStringSchema.nullable().default(null),
        /**
         * The version of the adblocker when the entity was removed.
         */
        version_removed: nonEmptyStringSchema.nullable().default(null),
        /**
         * Describes whether the entity is deprecated.
         */
        deprecated: booleanSchema.default(false),
        /**
         * Message that describes why the entity is deprecated.
         * If not specified or it's value is `null`, then the message is not available.
         * It's value is omitted if the entity is not marked as deprecated.
         */
        deprecation_message: nonEmptyStringSchema.nullable().default(null),
        /**
         * Describes whether the entity is removed; for *already removed* features.
         */
        removed: booleanSchema.default(false),
        /**
         * Message that describes why the entity is removed.
         * If not specified or it's value is `null`, then the message is not available.
         * It's value is omitted if the entity is not marked as deprecated.
         */
        removal_message: nonEmptyStringSchema.nullable().default(null),
    });
    /**
     * Zod schema for base compatibility data with camelCase properties.
     */
    zodToCamelCase(baseCompatibilityDataSchema);
    /**
     * Refinement logic for base compatibility data.
     *
     * @param data Base compatibility data.
     * @param ctx Refinement context.
     */
    const baseRefineLogic = (data, ctx) => {
        if (data.deprecated && !data.deprecation_message) {
            ctx.addIssue({
                code: z.ZodIssueCode.custom,
                message: 'deprecation_message is required for deprecated modifiers',
            });
        }
        if (!data.deprecated && data.deprecation_message) {
            ctx.addIssue({
                code: z.ZodIssueCode.custom,
                message: 'deprecation_message is only allowed for deprecated modifiers',
            });
        }
        if (data.aliases && data.aliases.length !== new Set(data.aliases).size) {
            ctx.addIssue({
                code: z.ZodIssueCode.custom,
                message: 'Aliases must be unique',
            });
        }
    };

    /**
     * Checks if error has message.
     *
     * @param error Error object.
     * @returns If param is error.
     */
    function isErrorWithMessage(error) {
        return (typeof error === 'object'
            && error !== null
            && 'message' in error
            && typeof error.message === 'string');
    }
    /**
     * Converts error to the error with message.
     *
     * @param maybeError Possible error.
     * @returns Error with message.
     */
    function toErrorWithMessage(maybeError) {
        if (isErrorWithMessage(maybeError)) {
            return maybeError;
        }
        try {
            return new Error(JSON.stringify(maybeError));
        }
        catch {
            // fallback in case there's an error stringifying the maybeError
            // like with circular references for example.
            return new Error(String(maybeError));
        }
    }
    /**
     * Converts error object to error with message. This method might be helpful to handle thrown errors.
     *
     * @param error Error object.
     *
     * @returns Message of the error.
     */
    function getErrorMessage$1(error) {
        return toErrorWithMessage(error).message;
    }

    /**
     * @file Schema for modifier data.
     */
    /**
     * Known validators that don't need to be validated as regex.
     */
    const KNOWN_VALIDATORS = new Set([
        'domain',
        'pipe_separated_domains',
        'regexp',
        'url',
    ]);
    /**
     * Zod schema for modifier data.
     */
    zodToCamelCase(baseCompatibilityDataSchema.extend({
        /**
         * List of modifiers that are incompatible with the actual one.
         */
        conflicts: z.array(nonEmptyStringSchema).nullable().default(null),
        /**
         * The actual modifier is incompatible with all other modifiers, except the ones listed in `conflicts`.
         */
        inverse_conflicts: booleanSchema.default(false),
        /**
         * Describes whether the actual modifier supports value assignment. For example, `$domain` is assignable,
         * so it can be used like this: `$domain=domain.com\|~subdomain.domain.com`, where `=` is the assignment operator
         * and `domain.com\|~subdomain.domain.com` is the value.
         */
        assignable: booleanSchema.default(false),
        /**
         * Describes whether the actual modifier can be negated. For example, `$third-party` is negatable,
         * so it can be used like this: `$~third-party`.
         */
        negatable: booleanSchema.default(true),
        /**
         * The actual modifier can only be used in blocking rules, it cannot be used in exceptions.
         * If it's value is `true`, then the modifier can be used only in blocking rules.
         * `exception_only` and `block_only` cannot be used together (they are mutually exclusive).
         */
        block_only: booleanSchema.default(false),
        /**
         * The actual modifier can only be used in exceptions, it cannot be used in blocking rules.
         * If it's value is `true`, then the modifier can be used only in exceptions.
         * `exception_only` and `block_only` cannot be used together (they are mutually exclusive).
         */
        exception_only: booleanSchema.default(false),
        /**
         * Describes whether the *assignable* modifier value is required.
         * For example, `$cookie` is assignable but it can be used without a value in exception rules:
         * `@@\|\|example.com^$cookie`.
         * If `false`, the `value_format` is required, e.g. the value of `$app` should always be specified
         */
        value_optional: booleanSchema.default(false),
        /**
         * Describes the format of the value for the *assignable* modifier.
         * Its value can be a regex pattern or a known validator name (e.g. `domain`, `pipe_separated_domains`, etc.).
         */
        value_format: nonEmptyStringSchema.nullable().default(null),
    }).superRefine((data, ctx) => {
        // TODO: find something better, for now we can't add refine logic to the base schema:
        // https://github.com/colinhacks/zod/issues/454#issuecomment-848370721
        baseRefineLogic(data, ctx);
        if (data.block_only && data.exception_only) {
            ctx.addIssue({
                code: z.ZodIssueCode.custom,
                message: 'block_only and exception_only are mutually exclusive',
            });
        }
        if (data.assignable && !data.value_format) {
            ctx.addIssue({
                code: z.ZodIssueCode.custom,
                message: 'value_format is required for assignable modifiers',
            });
        }
        if (data.value_format) {
            const valueFormat = data.value_format.trim();
            // if it is a known validator, we don't need to validate it further
            if (KNOWN_VALIDATORS.has(valueFormat)) {
                return;
            }
            // otherwise, we need to validate it as a regex
            try {
                XRegExp(valueFormat);
            }
            catch (error) {
                ctx.addIssue({
                    code: z.ZodIssueCode.custom,
                    message: getErrorMessage$1(error),
                });
            }
        }
    }));

    /**
     * @file Schema for redirect data.
     */
    /**
     * Zod schema for redirect data.
     */
    zodToCamelCase(baseCompatibilityDataSchema.extend({
        /**
         * Whether the redirect is blocking.
         */
        is_blocking: booleanSchema.default(false),
        /**
         * Resource type(s) belonging to the redirect.
         *
         * @see {@link https://developer.chrome.com/docs/extensions/reference/declarativeNetRequest/#type-ResourceType}
         */
        resource_types: z.array(resourceTypeSchema).default([]),
    }).superRefine(baseRefineLogic));

    /**
     * @file Schema for scriptlet data.
     */
    /**
     * Zod schema for scriptlet parameter data.
     */
    const scriptletParameterSchema = z.object({
        /**
         * Name of the actual parameter.
         */
        name: nonEmptyStringSchema,
        /**
         * Describes whether the parameter is required. Empty parameters are not allowed.
         */
        required: booleanSchema,
        /**
         * Short description of the parameter.
         * If not specified or it's value is `null`,then the description is not available.
         */
        description: nonEmptyStringSchema.nullable().default(null),
        /**
         * Regular expression that matches the value of the parameter.
         * If it's value is `null`, then the parameter value is not checked.
         */
        pattern: nonEmptyStringSchema.nullable().default(null),
        /**
         * Default value of the parameter (if any).
         */
        default: nonEmptyStringSchema.nullable().default(null),
        /**
         * Describes whether the parameter is used only for debugging purposes.
         */
        debug: booleanSchema.default(false),
    });
    /**
     * Zod schema for scriptlet parameters.
     */
    const scriptletParametersSchema = z.array(scriptletParameterSchema);
    /**
     * Zod schema for scriptlet data.
     */
    zodToCamelCase(baseCompatibilityDataSchema.extend({
        /**
         * List of parameters that the scriptlet accepts.
         * **Every** parameter should be listed here, because we check that the scriptlet is used correctly
         * (e.g. that the number of parameters is correct).
         */
        parameters: scriptletParametersSchema.optional(),
    }).superRefine((data, ctx) => {
        // TODO: find something better, for now we can't add refine logic to the base schema:
        // https://github.com/colinhacks/zod/issues/454#issuecomment-848370721
        baseRefineLogic(data, ctx);
        // we don't allow required parameters after optional ones
        if (!data.parameters) {
            return;
        }
        let optionalFound = false;
        for (const parameter of data.parameters) {
            if (optionalFound && parameter.required) {
                ctx.addIssue({
                    code: z.ZodIssueCode.custom,
                    message: 'Required parameters must be before optional ones',
                });
            }
            if (!parameter.required) {
                optionalFound = true;
            }
        }
    }));

    /**
     * @file Scriptlet injection rule converter
     */
    const ABP_SCRIPTLET_PREFIX = 'abp-';
    const UBO_SCRIPTLET_PREFIX = 'ubo-';
    const UBO_SCRIPTLET_PREFIX_LENGTH = UBO_SCRIPTLET_PREFIX.length;
    const UBO_SCRIPTLET_JS_SUFFIX = '.js';
    const UBO_SCRIPTLET_JS_SUFFIX_LENGTH = UBO_SCRIPTLET_JS_SUFFIX.length;
    const COMMA_SEPARATOR = ',';
    const ADG_SET_CONSTANT_NAME = 'set-constant';
    const ADG_SET_CONSTANT_EMPTY_STRING = '';
    const ADG_SET_CONSTANT_EMPTY_ARRAY = 'emptyArr';
    const ADG_SET_CONSTANT_EMPTY_OBJECT = 'emptyObj';
    const UBO_SET_CONSTANT_EMPTY_STRING = '\'\'';
    const UBO_SET_CONSTANT_EMPTY_ARRAY = '[]';
    const UBO_SET_CONSTANT_EMPTY_OBJECT = '{}';
    const ADG_PREVENT_FETCH_NAME = 'prevent-fetch';
    const ADG_PREVENT_FETCH_EMPTY_STRING = '';
    const ADG_PREVENT_FETCH_WILDCARD = '*';
    const UBO_NO_FETCH_IF_WILDCARD = '/^/';
    const UBO_REMOVE_CLASS_NAME = 'remove-class.js';
    const UBO_REMOVE_ATTR_NAME = 'remove-attr.js';
    const setConstantAdgToUboMap = {
        [ADG_SET_CONSTANT_EMPTY_STRING]: UBO_SET_CONSTANT_EMPTY_STRING,
        [ADG_SET_CONSTANT_EMPTY_ARRAY]: UBO_SET_CONSTANT_EMPTY_ARRAY,
        [ADG_SET_CONSTANT_EMPTY_OBJECT]: UBO_SET_CONSTANT_EMPTY_OBJECT,
    };
    const REMOVE_ATTR_CLASS_APPLYING = new Set([
        'asap',
        'stay',
        'complete',
    ]);
    /**
     * Scriptlet injection rule converter class
     *
     * @todo Implement `convertToUbo` and `convertToAbp`
     */
    class ScriptletRuleConverter extends RuleConverterBase {
        /**
         * Converts a scriptlet injection rule to AdGuard format, if possible.
         *
         * @param rule Rule node to convert
         * @returns An object which follows the {@link NodeConversionResult} interface. Its `result` property contains
         * the array of converted rule nodes, and its `isConverted` flag indicates whether the original rule was converted.
         * If the rule was not converted, the result array will contain the original node with the same object reference
         * @throws If the rule is invalid or cannot be converted
         */
        static convertToAdg(rule) {
            // Ignore AdGuard rules
            if (rule.syntax === AdblockSyntax.Adg) {
                return createNodeConversionResult([rule], false);
            }
            const separator = rule.separator.value;
            let convertedSeparator = separator;
            convertedSeparator = rule.exception
                ? CosmeticRuleSeparator.AdgJsInjectionException
                : CosmeticRuleSeparator.AdgJsInjection;
            const convertedScriptlets = [];
            for (const scriptlet of rule.body.children) {
                // Clone the node to avoid any side effects
                const scriptletClone = cloneScriptletRuleNode(scriptlet);
                // Remove possible quotes just to make it easier to work with the scriptlet name
                const scriptletName = QuoteUtils.setStringQuoteType(getScriptletName(scriptletClone), QuoteType.None);
                // Add prefix if it's not already there
                let prefix;
                // In uBO / ABP syntax, if a parameter contains the separator character, it should be escaped,
                // but during the conversion, we need to unescape them, because AdGuard syntax uses quotes to
                // distinguish between parameters.
                let charToUnescape;
                switch (rule.syntax) {
                    case AdblockSyntax.Abp:
                        prefix = ABP_SCRIPTLET_PREFIX;
                        charToUnescape = SPACE;
                        break;
                    case AdblockSyntax.Ubo:
                        prefix = UBO_SCRIPTLET_PREFIX;
                        charToUnescape = COMMA_SEPARATOR;
                        break;
                    default:
                        prefix = EMPTY;
                }
                if (!scriptletName.startsWith(prefix)) {
                    setScriptletName(scriptletClone, `${prefix}${scriptletName}`);
                }
                if (!isUndefined$1(charToUnescape)) {
                    transformAllScriptletArguments(scriptletClone, (value) => {
                        if (!isNull$1(value)) {
                            return QuoteUtils.unescapeSingleEscapedOccurrences(value, charToUnescape);
                        }
                        return value;
                    });
                }
                if (rule.syntax === AdblockSyntax.Ubo) {
                    const scriptletData = scriptletsCompatibilityTable.getFirst(scriptletName, GenericPlatform.UboAny);
                    // Some scriptlets have special values that need to be converted
                    if (scriptletData
                        && (scriptletData.name === UBO_REMOVE_CLASS_NAME
                            || scriptletData.name === UBO_REMOVE_ATTR_NAME)
                        && scriptletClone.children.length > 2) {
                        const selectors = [];
                        let applying = null;
                        let lastArg = scriptletClone.children.pop();
                        // The very last argument might be the 'applying' parameter
                        if (lastArg) {
                            if (REMOVE_ATTR_CLASS_APPLYING.has(lastArg.value)) {
                                applying = lastArg.value;
                            }
                            else {
                                selectors.push(lastArg.value);
                            }
                        }
                        while (scriptletClone.children.length > 2) {
                            lastArg = scriptletClone.children.pop();
                            if (lastArg) {
                                selectors.push(lastArg.value.trim());
                            }
                        }
                        // Set last arg to be the combined selectors (in reverse order, because we popped them)
                        if (selectors.length > 0) {
                            scriptletClone.children.push({
                                type: 'Value',
                                value: selectors.reverse().join(', '),
                            });
                        }
                        // Push back the 'applying' parameter if it was found previously
                        if (!isNull$1(applying)) {
                            // If we don't have any selectors,
                            // we need to add an empty parameter before the 'applying' one
                            if (selectors.length === 0) {
                                scriptletClone.children.push({
                                    type: 'Value',
                                    value: EMPTY,
                                });
                            }
                            scriptletClone.children.push({
                                type: 'Value',
                                value: applying,
                            });
                        }
                    }
                }
                // ADG scriptlet parameters should be quoted, and single quoted are preferred
                setScriptletQuoteType(scriptletClone, QuoteType.Single);
                convertedScriptlets.push(scriptletClone);
            }
            if (rule.body.children.length === 0) {
                const convertedScriptletNode = {
                    category: rule.category,
                    type: rule.type,
                    syntax: AdblockSyntax.Adg,
                    exception: rule.exception,
                    domains: cloneDomainListNode(rule.domains),
                    separator: {
                        type: 'Value',
                        value: convertedSeparator,
                    },
                    body: {
                        type: rule.body.type,
                        children: [],
                    },
                };
                if (rule.modifiers) {
                    convertedScriptletNode.modifiers = cloneModifierListNode(rule.modifiers);
                }
                return createNodeConversionResult([convertedScriptletNode], true);
            }
            return createNodeConversionResult(convertedScriptlets.map((scriptlet) => {
                const res = {
                    category: rule.category,
                    type: rule.type,
                    syntax: AdblockSyntax.Adg,
                    exception: rule.exception,
                    domains: cloneDomainListNode(rule.domains),
                    separator: {
                        type: 'Value',
                        value: convertedSeparator,
                    },
                    body: {
                        type: rule.body.type,
                        children: [scriptlet],
                    },
                };
                if (rule.modifiers) {
                    res.modifiers = cloneModifierListNode(rule.modifiers);
                }
                return res;
            }), true);
        }
        /**
         * Converts a scriptlet injection rule to uBlock format, if possible.
         *
         * @param rule Rule node to convert
         * @returns An object which follows the {@link NodeConversionResult} interface. Its `result` property contains
         * the array of converted rule nodes, and its `isConverted` flag indicates whether the original rule was converted.
         * If the rule was not converted, the result array will contain the original node with the same object reference
         * @throws If the rule is invalid or cannot be converted
         */
        static convertToUbo(rule) {
            // Ignore uBlock rules
            if (rule.syntax === AdblockSyntax.Ubo) {
                return createNodeConversionResult([rule], false);
            }
            const separator = rule.separator.value;
            let convertedSeparator = separator;
            convertedSeparator = rule.exception
                ? CosmeticRuleSeparator.ElementHidingException
                : CosmeticRuleSeparator.ElementHiding;
            const convertedScriptlets = [];
            for (const scriptlet of rule.body.children) {
                // Clone the node to avoid any side effects
                const scriptletClone = cloneScriptletRuleNode(scriptlet);
                // Remove possible quotes just to make it easier to work with the scriptlet name
                const scriptletName = QuoteUtils.setStringQuoteType(getScriptletName(scriptletClone), QuoteType.None);
                let uboScriptletName;
                if (rule.syntax === AdblockSyntax.Adg && scriptletName.startsWith(UBO_SCRIPTLET_PREFIX)) {
                    // Special case: AdGuard syntax 'preserves' the original scriptlet name,
                    // so we need to convert it back by removing the uBO prefix
                    uboScriptletName = scriptletName.slice(UBO_SCRIPTLET_PREFIX_LENGTH);
                }
                else {
                    // Otherwise, try to find the corresponding uBO scriptlet name, or use the original one if not found
                    const uboScriptlet = scriptletsCompatibilityTable.getFirst(scriptletName, GenericPlatform.UboAny);
                    uboScriptletName = uboScriptlet?.name ?? scriptletName;
                }
                // Remove the '.js' suffix if it's there - its presence is not mandatory
                if (uboScriptletName.endsWith(UBO_SCRIPTLET_JS_SUFFIX)) {
                    uboScriptletName = uboScriptletName.slice(0, -UBO_SCRIPTLET_JS_SUFFIX_LENGTH);
                }
                setScriptletName(scriptletClone, uboScriptletName);
                setScriptletQuoteType(scriptletClone, QuoteType.None);
                // Escape unescaped commas in parameters, because uBlock Origin uses them as separators.
                // For example, the following AdGuard rule:
                //
                // example.com#%#//scriptlet('spoof-css', '.adsbygoogle, #ads', 'visibility', 'visible')
                //
                //      ↓↓ should be converted to ↓↓
                //
                // example.com##+js(spoof-css.js, .adsbygoogle\, #ads, visibility, visible)
                //                  ------------  -------------------  ----------  -------
                //                    arg 0              arg 1           arg 2      arg 3
                //
                // and we need to escape the comma in the second argument to prevent it from being treated
                // as two separate arguments.
                transformAllScriptletArguments(scriptletClone, (value) => {
                    if (!isNull$1(value)) {
                        return QuoteUtils.escapeUnescapedOccurrences(value, COMMA_SEPARATOR);
                    }
                    return value;
                });
                // Unescape spaces in parameters, because uBlock Origin doesn't treat them as separators.
                if (rule.syntax === AdblockSyntax.Abp) {
                    transformAllScriptletArguments(scriptletClone, (value) => {
                        if (!isNull$1(value)) {
                            return QuoteUtils.unescapeSingleEscapedOccurrences(value, SPACE);
                        }
                        return value;
                    });
                }
                // Some scriptlets have special values that need to be converted
                switch (scriptletName) {
                    case ADG_SET_CONSTANT_NAME:
                        transformNthScriptletArgument(scriptletClone, 2, (value) => {
                            if (!isNull$1(value)) {
                                return setConstantAdgToUboMap[value] ?? value;
                            }
                            return value;
                        });
                        break;
                    case ADG_PREVENT_FETCH_NAME:
                        transformNthScriptletArgument(scriptletClone, 1, (value) => {
                            if (value === ADG_PREVENT_FETCH_EMPTY_STRING || value === ADG_PREVENT_FETCH_WILDCARD) {
                                return UBO_NO_FETCH_IF_WILDCARD;
                            }
                            return value;
                        });
                        break;
                }
                convertedScriptlets.push(scriptletClone);
            }
            // TODO: Refactor redundant code
            if (rule.body.children.length === 0) {
                const convertedScriptletNode = {
                    category: rule.category,
                    type: rule.type,
                    syntax: AdblockSyntax.Ubo,
                    exception: rule.exception,
                    domains: cloneDomainListNode(rule.domains),
                    separator: {
                        type: 'Value',
                        value: convertedSeparator,
                    },
                    body: {
                        type: rule.body.type,
                        children: [],
                    },
                };
                if (rule.modifiers) {
                    convertedScriptletNode.modifiers = cloneModifierListNode(rule.modifiers);
                }
                return createNodeConversionResult([convertedScriptletNode], true);
            }
            return createNodeConversionResult(convertedScriptlets.map((scriptlet) => {
                const res = {
                    category: rule.category,
                    type: rule.type,
                    syntax: AdblockSyntax.Ubo,
                    exception: rule.exception,
                    domains: cloneDomainListNode(rule.domains),
                    separator: {
                        type: 'Value',
                        value: convertedSeparator,
                    },
                    body: {
                        type: rule.body.type,
                        children: [scriptlet],
                    },
                };
                if (rule.modifiers) {
                    res.modifiers = cloneModifierListNode(rule.modifiers);
                }
                return res;
            }), true);
        }
    }

    /**
     * @file Utility functions for working with modifier nodes
     */
    /**
     * Creates a modifier node
     *
     * @param name Name of the modifier
     * @param value Value of the modifier
     * @param exception Whether the modifier is an exception
     * @returns Modifier node
     */
    function createModifierNode(name, value = undefined, exception = false) {
        const result = {
            type: 'Modifier',
            exception,
            name: {
                type: 'Value',
                value: name,
            },
        };
        if (!isUndefined$1(value)) {
            result.value = {
                type: 'Value',
                value,
            };
        }
        return result;
    }
    /**
     * Creates a modifier list node
     *
     * @param modifiers Modifiers to put in the list (optional, defaults to an empty list)
     * @returns Modifier list node
     */
    function createModifierListNode(modifiers = []) {
        const result = {
            type: 'ModifierList',
            // We need to clone the modifiers to avoid side effects
            children: modifiers.length ? clone(modifiers) : [],
        };
        return result;
    }

    /**
     * A very simple map extension that allows to store multiple values for the same key
     * by storing them in an array.
     *
     * @todo Add more methods if needed
     */
    class MultiValueMap extends Map {
        /**
         * Adds a value to the map. If the key already exists, the value will be appended to the existing array,
         * otherwise a new array will be created for the key.
         *
         * @param key Key to add
         * @param values Value(s) to add
         */
        add(key, ...values) {
            let currentValues = super.get(key);
            if (isUndefined$1(currentValues)) {
                currentValues = [];
                super.set(key, values);
            }
            currentValues.push(...values);
        }
    }

    /**
     * @file Cosmetic rule modifier converter from uBO to ADG
     */
    const UBO_MATCHES_PATH_OPERATOR = 'matches-path';
    const ADG_PATH_MODIFIER = 'path';
    /**
     * Special characters in modifier regexps that should be escaped
     */
    const SPECIAL_MODIFIER_REGEX_CHARS = new Set([
        OPEN_SQUARE_BRACKET,
        CLOSE_SQUARE_BRACKET,
        COMMA,
        ESCAPE_CHARACTER,
    ]);
    /**
     * Helper class for converting cosmetic rule modifiers from uBO to ADG
     */
    class AdgCosmeticRuleModifierConverter {
        /**
         * Converts a uBO cosmetic rule modifier list to ADG, if possible.
         *
         * @param modifierList Cosmetic rule modifier list node to convert
         * @returns An object which follows the {@link ConversionResult} interface. Its `result` property contains
         * the converted node, and its `isConverted` flag indicates whether the original node was converted.
         * If the node was not converted, the result will contain the original node with the same object reference
         * @throws If the modifier list cannot be converted
         * @see {@link https://github.com/gorhill/uBlock/wiki/Procedural-cosmetic-filters#cosmetic-filter-operators}
         */
        static convertFromUbo(modifierList) {
            const conversionMap = new MultiValueMap();
            modifierList.children.forEach((modifier, index) => {
                // :matches-path
                if (modifier.name.value === UBO_MATCHES_PATH_OPERATOR) {
                    if (!modifier.value) {
                        throw new RuleConversionError(`'${UBO_MATCHES_PATH_OPERATOR}' operator requires a value`);
                    }
                    const value = RegExpUtils.isRegexPattern(modifier.value.value)
                        ? StringUtils.escapeCharacters(modifier.value.value, SPECIAL_MODIFIER_REGEX_CHARS)
                        : modifier.value.value;
                    // Convert uBO's `:matches-path(...)` operator to ADG's `$path=...` modifier
                    conversionMap.add(index, createModifierNode(ADG_PATH_MODIFIER, 
                    // We should negate the regexp if the modifier is an exception
                    modifier.exception
                        // eslint-disable-next-line max-len
                        ? `${REGEX_MARKER}${RegExpUtils.negateRegexPattern(RegExpUtils.patternToRegexp(value))}${REGEX_MARKER}`
                        : value));
                }
            });
            // Check if we have any converted modifiers
            if (conversionMap.size) {
                const modifierListClone = clone(modifierList);
                // Replace the original modifiers with the converted ones
                modifierListClone.children = modifierListClone.children.map((modifier, index) => {
                    const convertedModifier = conversionMap.get(index);
                    return convertedModifier ?? modifier;
                }).flat();
                return createConversionResult(modifierListClone, true);
            }
            // Otherwise, just return the original modifier list
            return createConversionResult(modifierList, false);
        }
    }

    const ERROR_MESSAGES$1 = {
        // eslint-disable-next-line max-len
        INVALID_ATTRIBUTE_VALUE: `Expected '${getFormattedTokenName(TokenType$1.Ident)}' or '${getFormattedTokenName(TokenType$1.String)}' as attribute value, but got '%s' with value '%s`,
    };
    var PseudoClasses;
    (function (PseudoClasses) {
        PseudoClasses["AbpContains"] = "-abp-contains";
        PseudoClasses["AbpHas"] = "-abp-has";
        PseudoClasses["Contains"] = "contains";
        PseudoClasses["Has"] = "has";
        PseudoClasses["HasText"] = "has-text";
        PseudoClasses["MatchesCss"] = "matches-css";
        PseudoClasses["MatchesCssAfter"] = "matches-css-after";
        PseudoClasses["MatchesCssBefore"] = "matches-css-before";
        PseudoClasses["Not"] = "not";
    })(PseudoClasses || (PseudoClasses = {}));
    var PseudoElements;
    (function (PseudoElements) {
        PseudoElements["After"] = "after";
        PseudoElements["Before"] = "before";
    })(PseudoElements || (PseudoElements = {}));
    const PSEUDO_ELEMENT_NAMES = new Set([
        PseudoElements.After,
        PseudoElements.Before,
    ]);
    /**
     * CSS selector converter
     *
     * @todo Implement `convertToUbo` and `convertToAbp`
     */
    class CssSelectorConverter extends ConverterBase {
        /**
         * Converts Extended CSS elements to AdGuard-compatible ones
         *
         * @param selectorList Selector list to convert
         * @returns An object which follows the {@link ConversionResult} interface. Its `result` property contains
         * the converted node, and its `isConverted` flag indicates whether the original node was converted.
         * If the node was not converted, the result will contain the original node with the same object reference
         * @throws If the rule is invalid or incompatible
         */
        static convertToAdg(selectorList) {
            const stream = selectorList instanceof CssTokenStream
                ? selectorList
                : new CssTokenStream(selectorList);
            const converted = [];
            const convertAndPushPseudo = (pseudo) => {
                switch (pseudo) {
                    case PseudoClasses.AbpContains:
                    case PseudoClasses.HasText:
                        converted.push(PseudoClasses.Contains);
                        converted.push(OPEN_PARENTHESIS);
                        break;
                    case PseudoClasses.AbpHas:
                        converted.push(PseudoClasses.Has);
                        converted.push(OPEN_PARENTHESIS);
                        break;
                    // a bit special case:
                    // - `:matches-css-before(...)` → `:matches-css(before, ...)`
                    // - `:matches-css-after(...)`  → `:matches-css(after, ...)`
                    case PseudoClasses.MatchesCssBefore:
                    case PseudoClasses.MatchesCssAfter:
                        converted.push(PseudoClasses.MatchesCss);
                        converted.push(OPEN_PARENTHESIS);
                        converted.push(pseudo.substring(PseudoClasses.MatchesCss.length + 1));
                        converted.push(COMMA);
                        break;
                    default:
                        converted.push(pseudo);
                        converted.push(OPEN_PARENTHESIS);
                        break;
                }
            };
            while (!stream.isEof()) {
                const token = stream.getOrFail();
                if (token.type === TokenType$1.Colon) {
                    // Advance colon
                    stream.advance();
                    converted.push(COLON);
                    const tempToken = stream.getOrFail();
                    // Double colon is a pseudo-element
                    if (tempToken.type === TokenType$1.Colon) {
                        stream.advance();
                        converted.push(COLON);
                        continue;
                    }
                    if (tempToken.type === TokenType$1.Ident) {
                        const name = stream.source.slice(tempToken.start, tempToken.end);
                        if (PSEUDO_ELEMENT_NAMES.has(name)) {
                            // Add an extra colon to the name
                            converted.push(COLON);
                            converted.push(name);
                        }
                        else {
                            // Add the name as is
                            converted.push(name);
                        }
                        // Advance the names
                        stream.advance();
                    }
                    else if (tempToken.type === TokenType$1.Function) {
                        const name = stream.source.slice(tempToken.start, tempToken.end - 1); // omit the last parenthesis
                        // :-abp-contains(...) → :contains(...)
                        // :has-text(...)      → :contains(...)
                        // :-abp-has(...)      → :has(...)
                        convertAndPushPseudo(name);
                        // Advance the function name
                        stream.advance();
                    }
                }
                else if (token.type === TokenType$1.OpenSquareBracket) {
                    let tempToken;
                    const { start } = token;
                    stream.advance();
                    // Converts legacy Extended CSS selectors to the modern Extended CSS syntax.
                    // For example:
                    // - `[-ext-has=...]`                  → `:has(...)`
                    // - `[-ext-contains=...]`             → `:contains(...)`
                    // - `[-ext-matches-css-before=...]`   → `:matches-css(before, ...)`
                    stream.skipWhitespace();
                    stream.expect(TokenType$1.Ident);
                    tempToken = stream.getOrFail();
                    let attr = stream.source.slice(tempToken.start, tempToken.end);
                    // Skip if the attribute name is not a legacy Extended CSS one
                    if (!(attr.startsWith(LEGACY_EXT_CSS_ATTRIBUTE_PREFIX) || attr.startsWith(ABP_EXT_CSS_PREFIX))) {
                        converted.push(stream.source.slice(start, tempToken.end));
                        stream.advance();
                        continue;
                    }
                    if (attr.startsWith(LEGACY_EXT_CSS_ATTRIBUTE_PREFIX)) {
                        attr = attr.slice(LEGACY_EXT_CSS_ATTRIBUTE_PREFIX.length);
                    }
                    stream.advance();
                    stream.skipWhitespace();
                    // Next token should be an equality operator (=), because Extended CSS attribute selectors
                    // do not support other operators
                    stream.expect(TokenType$1.Delim, { value: EQUALS });
                    stream.advance();
                    // Skip optional whitespace after the operator
                    stream.skipWhitespace();
                    // Parse attribute value
                    tempToken = stream.getOrFail();
                    // According to the spec, attribute value should be an identifier or a string
                    if (tempToken.type !== TokenType$1.Ident && tempToken.type !== TokenType$1.String) {
                        throw new Error(sprintf.sprintf(ERROR_MESSAGES$1.INVALID_ATTRIBUTE_VALUE, getFormattedTokenName(tempToken.type), stream.source.slice(tempToken.start, tempToken.end)));
                    }
                    const value = stream.source.slice(tempToken.start, tempToken.end);
                    // Advance the attribute value
                    stream.advance();
                    // Skip optional whitespace after the attribute value
                    stream.skipWhitespace();
                    // Next character should be a closing square bracket
                    // We don't allow flags for Extended CSS attribute selectors
                    stream.expect(TokenType$1.CloseSquareBracket);
                    stream.advance();
                    converted.push(COLON);
                    convertAndPushPseudo(attr);
                    let processedValue = value.slice(1, -1); // omit the quotes
                    if (attr === PseudoClasses.Has) {
                        // TODO: Optimize this to avoid double tokenization
                        processedValue = CssSelectorConverter.convertToAdg(processedValue).result;
                    }
                    converted.push(processedValue);
                    converted.push(CLOSE_PARENTHESIS);
                }
                else {
                    converted.push(stream.source.slice(token.start, token.end));
                    // Advance the token
                    stream.advance();
                }
            }
            const convertedSelectorList = converted.join(EMPTY);
            return createConversionResult(convertedSelectorList, stream.source !== convertedSelectorList);
        }
    }

    /**
     * @file CSS injection rule converter
     */
    /**
     * CSS injection rule converter class
     *
     * @todo Implement `convertToUbo` and `convertToAbp`
     */
    class CssInjectionRuleConverter extends RuleConverterBase {
        /**
         * Converts a CSS injection rule to AdGuard format, if possible.
         *
         * @param rule Rule node to convert
         * @returns An object which follows the {@link NodeConversionResult} interface. Its `result` property contains
         * the array of converted rule nodes, and its `isConverted` flag indicates whether the original rule was converted.
         * If the rule was not converted, the result array will contain the original node with the same object reference
         * @throws If the rule is invalid or cannot be converted
         */
        static convertToAdg(rule) {
            const separator = rule.separator.value;
            let convertedSeparator = separator;
            const stream = new CssTokenStream(rule.body.selectorList.value);
            const convertedSelectorList = CssSelectorConverter.convertToAdg(stream);
            // Change the separator if the rule contains ExtendedCSS elements,
            // but do not force non-extended CSS separator if the rule does not contain any ExtendedCSS selectors,
            // because sometimes we use it to force executing ExtendedCSS library.
            if (stream.hasAnySelectorExtendedCssNodeStrict() || rule.body.remove) {
                convertedSeparator = rule.exception
                    ? CosmeticRuleSeparator.AdgExtendedCssInjectionException
                    : CosmeticRuleSeparator.AdgExtendedCssInjection;
            }
            else if (rule.syntax !== AdblockSyntax.Adg) {
                // If the original rule syntax is not AdGuard, use the default separator
                // e.g. if the input rule is from uBO, we need to convert ## to #$#.
                convertedSeparator = rule.exception
                    ? CosmeticRuleSeparator.AdgCssInjectionException
                    : CosmeticRuleSeparator.AdgCssInjection;
            }
            // Check if the rule needs to be converted
            if (!(rule.syntax === AdblockSyntax.Common || rule.syntax === AdblockSyntax.Adg)
                || separator !== convertedSeparator
                || convertedSelectorList.isConverted) {
                // TODO: Replace with custom clone method
                const ruleClone = clone(rule);
                ruleClone.syntax = AdblockSyntax.Adg;
                ruleClone.separator.value = convertedSeparator;
                ruleClone.body.selectorList.value = convertedSelectorList.result;
                return createNodeConversionResult([ruleClone], true);
            }
            // Otherwise, return the original rule
            return createNodeConversionResult([rule], false);
        }
    }

    /**
     * @file Element hiding rule converter
     */
    /**
     * Element hiding rule converter class
     *
     * @todo Implement `convertToUbo` and `convertToAbp`
     */
    class ElementHidingRuleConverter extends RuleConverterBase {
        /**
         * Converts an element hiding rule to AdGuard format, if possible.
         *
         * @param rule Rule node to convert
         * @returns An object which follows the {@link NodeConversionResult} interface. Its `result` property contains
         * the array of converted rule nodes, and its `isConverted` flag indicates whether the original rule was converted.
         * If the rule was not converted, the result array will contain the original node with the same object reference
         * @throws If the rule is invalid or cannot be converted
         */
        static convertToAdg(rule) {
            const separator = rule.separator.value;
            let convertedSeparator = separator;
            const stream = new CssTokenStream(rule.body.selectorList.value);
            const convertedSelectorList = CssSelectorConverter.convertToAdg(stream);
            // Change the separator if the rule contains ExtendedCSS elements,
            // but do not force non-extended CSS separator if the rule does not contain any ExtendedCSS selectors,
            // because sometimes we use it to force executing ExtendedCSS library.
            if (stream.hasAnySelectorExtendedCssNodeStrict()) {
                convertedSeparator = rule.exception
                    ? CosmeticRuleSeparator.ExtendedElementHidingException
                    : CosmeticRuleSeparator.ExtendedElementHiding;
            }
            // Check if the rule needs to be converted
            if (!(rule.syntax === AdblockSyntax.Common || rule.syntax === AdblockSyntax.Adg)
                || separator !== convertedSeparator
                || convertedSelectorList.isConverted) {
                // TODO: Replace with custom clone method
                const ruleClone = clone(rule);
                ruleClone.syntax = AdblockSyntax.Adg;
                ruleClone.separator.value = convertedSeparator;
                ruleClone.body.selectorList.value = convertedSelectorList.result;
                return createNodeConversionResult([ruleClone], true);
            }
            // Otherwise, return the original rule
            return createNodeConversionResult([rule], false);
        }
    }

    /**
     * @file Utility functions for working with network rule nodes
     */
    /**
     * Creates a network rule node
     *
     * @param pattern Rule pattern
     * @param modifiers Rule modifiers (optional, default: undefined)
     * @param exception Exception rule flag (optional, default: false)
     * @param syntax Adblock syntax (optional, default: Common)
     * @returns Network rule node
     */
    function createNetworkRuleNode(pattern, modifiers = undefined, exception = false, syntax = AdblockSyntax.Common) {
        const result = {
            category: RuleCategory.Network,
            type: NetworkRuleType.NetworkRule,
            syntax,
            exception,
            pattern: {
                type: 'Value',
                value: pattern,
            },
        };
        if (!isUndefined$1(modifiers)) {
            result.modifiers = clone(modifiers);
        }
        return result;
    }

    /**
     * @file Converter for request header removal rules
     */
    const UBO_RESPONSEHEADER_FN = 'responseheader';
    const ADG_REMOVEHEADER_MODIFIER = 'removeheader';
    const ERROR_MESSAGES = {
        EMPTY_PARAMETER: `Empty parameter for '${UBO_RESPONSEHEADER_FN}' function`,
        EXPECTED_END_OF_RULE: "Expected end of rule, but got '%s'",
        MULTIPLE_DOMAINS_NOT_SUPPORTED: 'Multiple domains are not supported yet',
    };
    /**
     * Converter for request header removal rules
     *
     * @todo Implement `convertToUbo` (ABP currently doesn't support header removal rules)
     */
    class HeaderRemovalRuleConverter extends RuleConverterBase {
        /**
         * Converts a header removal rule to AdGuard syntax, if possible.
         *
         * @param rule Rule node to convert
         * @returns An object which follows the {@link NodeConversionResult} interface. Its `result` property contains
         * the array of converted rule nodes, and its `isConverted` flag indicates whether the original rule was converted.
         * If the rule was not converted, the result array will contain the original node with the same object reference
         * @throws If the rule is invalid or cannot be converted
         * @example
         * If the input rule is:
         * ```adblock
         * example.com##^responseheader(header-name)
         * ```
         * The output will be:
         * ```adblock
         * ||example.com^$removeheader=header-name
         * ```
         */
        static convertToAdg(rule) {
            // TODO: Add support for ABP syntax once it starts supporting header removal rules
            // Leave the rule as is if it's not a header removal rule
            if (rule.category !== RuleCategory.Cosmetic || rule.type !== CosmeticRuleType.HtmlFilteringRule) {
                return createNodeConversionResult([rule], false);
            }
            const stream = new CssTokenStream(rule.body.value);
            let token;
            // Skip leading whitespace
            stream.skipWhitespace();
            // Next token should be the `^` followed by a `responseheader` function
            token = stream.get();
            if (!token || token.type !== TokenType$1.Delim || rule.body.value[token.start] !== UBO_HTML_MASK) {
                return createNodeConversionResult([rule], false);
            }
            stream.advance();
            token = stream.get();
            if (!token) {
                return createNodeConversionResult([rule], false);
            }
            const functionName = rule.body.value.slice(token.start, token.end - 1);
            if (functionName !== UBO_RESPONSEHEADER_FN) {
                return createNodeConversionResult([rule], false);
            }
            // Parse the parameter
            const paramStart = token.end;
            stream.skipUntilBalanced();
            const paramEnd = stream.getOrFail().end;
            const param = rule.body.value.slice(paramStart, paramEnd - 1).trim();
            // Do not allow empty parameter
            if (param.length === 0) {
                throw new RuleConversionError(ERROR_MESSAGES.EMPTY_PARAMETER);
            }
            stream.expect(TokenType$1.CloseParenthesis);
            stream.advance();
            // Skip trailing whitespace after the function call
            stream.skipWhitespace();
            // Expect the end of the rule - so nothing should be left in the stream
            if (!stream.isEof()) {
                token = stream.getOrFail();
                throw new RuleConversionError(sprintf.sprintf(ERROR_MESSAGES.EXPECTED_END_OF_RULE, getFormattedTokenName(token.type)));
            }
            // Prepare network rule pattern
            const pattern = [];
            if (rule.domains.children.length === 1) {
                // If the rule has only one domain, we can use a simple network rule pattern:
                // ||single-domain-from-the-rule^
                pattern.push(ADBLOCK_URL_START, rule.domains.children[0].value, ADBLOCK_URL_SEPARATOR);
            }
            else if (rule.domains.children.length > 1) {
                // TODO: Add support for multiple domains, for example:
                // example.com,example.org,example.net##^responseheader(header-name)
                // We should consider allowing $domain with $removeheader modifier,
                // for example:
                // $removeheader=header-name,domain=example.com|example.org|example.net
                throw new RuleConversionError(ERROR_MESSAGES.MULTIPLE_DOMAINS_NOT_SUPPORTED);
            }
            // Prepare network rule modifiers
            const modifiers = createModifierListNode();
            modifiers.children.push(createModifierNode(ADG_REMOVEHEADER_MODIFIER, param));
            // Construct the network rule
            return createNodeConversionResult([
                createNetworkRuleNode(pattern.join(EMPTY), modifiers, 
                // Copy the exception flag
                rule.exception, AdblockSyntax.Adg),
            ], true);
        }
    }

    /**
     * @file Cosmetic rule converter
     */
    /**
     * Cosmetic rule converter class (also known as "non-basic rule converter")
     *
     * @todo Implement `convertToUbo` and `convertToAbp`
     */
    class CosmeticRuleConverter extends RuleConverterBase {
        /**
         * Converts a cosmetic rule to AdGuard syntax, if possible.
         *
         * @param rule Rule node to convert
         * @returns An object which follows the {@link NodeConversionResult} interface. Its `result` property contains
         * the array of converted rule nodes, and its `isConverted` flag indicates whether the original rule was converted.
         * If the rule was not converted, the result array will contain the original node with the same object reference
         * @throws If the rule is invalid or cannot be converted
         */
        static convertToAdg(rule) {
            let subconverterResult;
            // Convert cosmetic rule based on its type
            switch (rule.type) {
                case CosmeticRuleType.ElementHidingRule:
                    subconverterResult = ElementHidingRuleConverter.convertToAdg(rule);
                    break;
                case CosmeticRuleType.ScriptletInjectionRule:
                    subconverterResult = ScriptletRuleConverter.convertToAdg(rule);
                    break;
                case CosmeticRuleType.CssInjectionRule:
                    subconverterResult = CssInjectionRuleConverter.convertToAdg(rule);
                    break;
                case CosmeticRuleType.HtmlFilteringRule:
                    // Handle special case: uBO response header filtering rule
                    // TODO: Optimize double CSS tokenization here
                    subconverterResult = HeaderRemovalRuleConverter.convertToAdg(rule);
                    if (subconverterResult.isConverted) {
                        break;
                    }
                    subconverterResult = HtmlRuleConverter.convertToAdg(rule);
                    break;
                // Note: Currently, only ADG supports JS injection rules, so we don't need to convert them
                case CosmeticRuleType.JsInjectionRule:
                    subconverterResult = createNodeConversionResult([rule], false);
                    break;
                default:
                    throw new RuleConversionError('Unsupported cosmetic rule type');
            }
            let convertedModifiers;
            // Convert cosmetic rule modifiers, if any
            if (rule.modifiers) {
                if (rule.syntax === AdblockSyntax.Ubo) {
                    // uBO doesn't support this rule:
                    // example.com##+js(set-constant.js, foo, bar):matches-path(/baz)
                    if (rule.type === CosmeticRuleType.ScriptletInjectionRule) {
                        throw new RuleConversionError('uBO scriptlet injection rules don\'t support cosmetic rule modifiers');
                    }
                    convertedModifiers = AdgCosmeticRuleModifierConverter.convertFromUbo(rule.modifiers);
                }
                else if (rule.syntax === AdblockSyntax.Abp) {
                    // TODO: Implement once ABP starts supporting cosmetic rule modifiers
                    throw new RuleConversionError('ABP don\'t support cosmetic rule modifiers');
                }
            }
            if ((subconverterResult.result.length > 1 || subconverterResult.isConverted)
                || (convertedModifiers && convertedModifiers.isConverted)) {
                // Add modifier list to the subconverter result rules
                subconverterResult.result.forEach((subconverterRule) => {
                    if (convertedModifiers && subconverterRule.category === RuleCategory.Cosmetic) {
                        // eslint-disable-next-line no-param-reassign
                        subconverterRule.modifiers = convertedModifiers.result;
                    }
                });
                return subconverterResult;
            }
            return createNodeConversionResult([rule], false);
        }
        /**
         * Converts a cosmetic rule to uBlock Origin syntax, if possible.
         *
         * @param rule Rule node to convert
         * @returns An object which follows the {@link NodeConversionResult} interface. Its `result` property contains
         * the array of converted rule nodes, and its `isConverted` flag indicates whether the original rule was converted.
         * If the rule was not converted, the result array will contain the original node with the same object reference
         * @throws If the rule is invalid or cannot be converted
         */
        // TODO: Add support for other cosmetic rule types
        static convertToUbo(rule) {
            // Convert cosmetic rule based on its type
            if (rule.type === CosmeticRuleType.ScriptletInjectionRule) {
                if (rule.syntax === AdblockSyntax.Adg && rule.modifiers?.children.length) {
                    // e.g. example.com##+js(set-constant.js, foo, bar):matches-path(/baz)
                    throw new RuleConversionError('uBO scriptlet injection rules do not support cosmetic rule modifiers');
                }
                return ScriptletRuleConverter.convertToUbo(rule);
            }
            return createNodeConversionResult([rule], false);
        }
    }

    /**
     * @file Network rule modifier list converter.
     */
    /**
     * @see {@link https://adguard.com/kb/general/ad-filtering/create-own-filters/#csp-modifier}
     */
    const CSP_MODIFIER = 'csp';
    const CSP_SEPARATOR = SEMICOLON + SPACE;
    /**
     * @see {@link https://adguard.com/kb/general/ad-filtering/create-own-filters/#csp-modifier}
     * @see {@link https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy}
     */
    const COMMON_CSP_PARAMS = '\'self\' \'unsafe-eval\' http: https: data: blob: mediastream: filesystem:';
    /**
     * @see {@link https://help.adblockplus.org/hc/en-us/articles/360062733293#rewrite}
     */
    const ABP_REWRITE_MODIFIER = 'rewrite';
    /**
     * @see {@link https://adguard.com/kb/general/ad-filtering/create-own-filters/#redirect-modifier}
     */
    const REDIRECT_MODIFIER = 'redirect';
    /**
     * @see {@link https://adguard.com/kb/general/ad-filtering/create-own-filters/#redirect-rule-modifier}
     */
    const REDIRECT_RULE_MODIFIER = 'redirect-rule';
    /**
     * @see {@link https://github.com/gorhill/uBlock/wiki/Resources-Library#empty-redirect-resources}
     */
    const UBO_NOOP_TEXT_RESOURCE = 'noop.txt';
    /**
     * Redirect-related modifiers.
     */
    const REDIRECT_MODIFIERS = new Set([
        ABP_REWRITE_MODIFIER,
        REDIRECT_MODIFIER,
        REDIRECT_RULE_MODIFIER,
    ]);
    /**
     * Conversion map for ADG network rule modifiers.
     */
    const ADG_CONVERSION_MAP = new Map([
        ['1p', [{ name: () => 'third-party', exception: (actual) => !actual }]],
        ['3p', [{ name: () => 'third-party' }]],
        ['css', [{ name: () => 'stylesheet' }]],
        ['doc', [{ name: () => 'document' }]],
        ['ehide', [{ name: () => 'elemhide' }]],
        ['empty', [{ name: () => 'redirect', value: () => 'nooptext' }]],
        ['first-party', [{ name: () => 'third-party', exception: (actual) => !actual }]],
        ['frame', [{ name: () => 'subdocument' }]],
        ['ghide', [{ name: () => 'generichide' }]],
        ['inline-font', [{ name: () => CSP_MODIFIER, value: () => `font-src ${COMMON_CSP_PARAMS}` }]],
        ['inline-script', [{ name: () => CSP_MODIFIER, value: () => `script-src ${COMMON_CSP_PARAMS}` }]],
        ['mp4', [{ name: () => 'redirect', value: () => 'noopmp4-1s' }, { name: () => 'media', value: () => undefined }]],
        ['queryprune', [{ name: () => 'removeparam' }]],
        ['shide', [{ name: () => 'specifichide' }]],
        ['xhr', [{ name: () => 'xmlhttprequest' }]],
    ]);
    /**
     * Helper class for converting network rule modifier lists.
     *
     * @todo Implement `convertToUbo` and `convertToAbp`
     */
    class NetworkRuleModifierListConverter extends ConverterBase {
        /**
         * Converts a network rule modifier list to AdGuard format, if possible.
         *
         * @param modifierList Network rule modifier list node to convert
         * @param isException If `true`, the rule is an exception rule
         * @returns An object which follows the {@link ConversionResult} interface. Its `result` property contains
         * the converted node, and its `isConverted` flag indicates whether the original node was converted.
         * If the node was not converted, the result will contain the original node with the same object reference
         * @throws If the conversion is not possible
         */
        static convertToAdg(modifierList, isException = false) {
            const conversionMap = new MultiValueMap();
            // Special case: $csp modifier
            let cspCount = 0;
            modifierList.children.forEach((modifierNode, index) => {
                const modifierConversions = ADG_CONVERSION_MAP.get(modifierNode.name.value);
                if (modifierConversions) {
                    for (const modifierConversion of modifierConversions) {
                        const name = modifierConversion.name(modifierNode.name.value);
                        const exception = modifierConversion.exception
                            // If the exception value is undefined in the original modifier, it
                            // means that the modifier isn't negated
                            ? modifierConversion.exception(modifierNode.exception || false)
                            : modifierNode.exception;
                        const value = modifierConversion.value
                            ? modifierConversion.value(modifierNode.value?.value)
                            : modifierNode.value?.value;
                        // Check if the name or the value is different from the original modifier
                        // If so, add the converted modifier to the list
                        if (name !== modifierNode.name.value || value !== modifierNode.value?.value) {
                            conversionMap.add(index, createModifierNode(name, value, exception));
                        }
                        // Special case: $csp modifier
                        if (name === CSP_MODIFIER) {
                            cspCount += 1;
                        }
                    }
                    return;
                }
                // Handle special case: resource redirection modifiers
                if (REDIRECT_MODIFIERS.has(modifierNode.name.value)) {
                    // Redirect modifiers can't be negated
                    if (modifierNode.exception === true) {
                        throw new RuleConversionError(`Modifier '${modifierNode.name.value}' cannot be negated`);
                    }
                    // Convert the redirect resource name to ADG format
                    const redirectResource = modifierNode.value?.value;
                    // Special case: for exception rules, $redirect without value is allowed,
                    // and in this case it means an exception for all redirects
                    if (!redirectResource && !isException) {
                        throw new RuleConversionError(`No redirect resource specified for '${modifierNode.name.value}' modifier`);
                    }
                    // Leave $redirect and $redirect-rule modifiers as is, but convert $rewrite to $redirect
                    const modifierName = modifierNode.name.value === ABP_REWRITE_MODIFIER
                        ? REDIRECT_MODIFIER
                        : modifierNode.name.value;
                    const convertedRedirectResource = redirectResource
                        ? redirectsCompatibilityTable.getFirst(redirectResource, GenericPlatform.AdgAny)?.name
                        : undefined;
                    // Check if the modifier name or the redirect resource name is different from the original modifier.
                    // If so, add the converted modifier to the list
                    if (modifierName !== modifierNode.name.value
                        || (convertedRedirectResource !== undefined && convertedRedirectResource !== redirectResource)) {
                        conversionMap.add(index, createModifierNode(modifierName, 
                        // If the redirect resource name is unknown, fall back to the original one
                        // Later, the validator will throw an error if the resource name is invalid
                        convertedRedirectResource || redirectResource, modifierNode.exception));
                    }
                }
            });
            // Prepare the result if there are any converted modifiers or $csp modifiers
            if (conversionMap.size || cspCount) {
                const modifierListClone = cloneModifierListNode(modifierList);
                // Replace the original modifiers with the converted ones
                // One modifier may be replaced with multiple modifiers, so we need to flatten the array
                modifierListClone.children = modifierListClone.children.map((modifierNode, index) => {
                    const conversionRecord = conversionMap.get(index);
                    if (conversionRecord) {
                        return conversionRecord;
                    }
                    return modifierNode;
                }).flat();
                // Special case: $csp modifier: merge multiple $csp modifiers into one
                // and put it at the end of the modifier list
                if (cspCount) {
                    const cspValues = [];
                    modifierListClone.children = modifierListClone.children.filter((modifierNode) => {
                        if (modifierNode.name.value === CSP_MODIFIER) {
                            if (!modifierNode.value?.value) {
                                throw new RuleConversionError('$csp modifier value is missing');
                            }
                            cspValues.push(modifierNode.value?.value);
                            return false;
                        }
                        return true;
                    });
                    modifierListClone.children.push(createModifierNode(CSP_MODIFIER, cspValues.join(CSP_SEPARATOR)));
                }
                // Before returning the result, remove duplicated modifiers
                modifierListClone.children = modifierListClone.children.filter((modifierNode, index, self) => self.findIndex((m) => m.name.value === modifierNode.name.value
                    && m.exception === modifierNode.exception
                    && m.value?.value === modifierNode.value?.value) === index);
                return createConversionResult(modifierListClone, true);
            }
            return createConversionResult(modifierList, false);
        }
        /**
         * Converts a network rule modifier list to uBlock format, if possible.
         *
         * @param modifierList Network rule modifier list node to convert
         * @param isException If `true`, the rule is an exception rule
         * @returns An object which follows the {@link ConversionResult} interface. Its `result` property contains
         * the converted node, and its `isConverted` flag indicates whether the original node was converted.
         * If the node was not converted, the result will contain the original node with the same object reference
         * @throws If the conversion is not possible
         */
        // TODO: Optimize
        static convertToUbo(modifierList, isException = false) {
            const conversionMap = new MultiValueMap();
            const resourceTypeModifiersToAdd = new Set();
            modifierList.children.forEach((modifierNode, index) => {
                const originalModifierName = modifierNode.name.value;
                const modifierData = modifiersCompatibilityTable.getFirst(originalModifierName, GenericPlatform.UboAny);
                // Handle special case: resource redirection modifiers
                if (REDIRECT_MODIFIERS.has(originalModifierName)) {
                    // Redirect modifiers cannot be negated
                    if (modifierNode.exception === true) {
                        throw new RuleConversionError(`Modifier '${modifierNode.name.value}' cannot be negated`);
                    }
                    // Convert the redirect resource name to uBO format
                    const redirectResourceName = modifierNode.value?.value;
                    // Special case: for exception rules, $redirect without value is allowed,
                    // and in this case it means an exception for all redirects
                    if (!redirectResourceName && !isException) {
                        throw new RuleConversionError(`No redirect resource specified for '${modifierNode.name.value}' modifier`);
                    }
                    if (!redirectResourceName) {
                        // Jump to the next modifier if the redirect resource is not specified
                        return;
                    }
                    // Leave $redirect and $redirect-rule modifiers as is, but convert $rewrite to $redirect
                    const modifierName = modifierNode.name.value === ABP_REWRITE_MODIFIER
                        ? REDIRECT_MODIFIER
                        : modifierNode.name.value;
                    const convertedRedirectResourceData = redirectsCompatibilityTable.getFirst(redirectResourceName, GenericPlatform.UboAny);
                    const convertedRedirectResourceName = convertedRedirectResourceData?.name ?? redirectResourceName;
                    // uBlock requires the $redirect modifier to have a resource type
                    // https://github.com/AdguardTeam/Scriptlets/issues/101
                    if (convertedRedirectResourceData?.resourceTypes?.length) {
                        // Convert the resource types to uBO modifiers
                        const uboResourceTypeModifiers = redirectsCompatibilityTable.getResourceTypeModifiers(convertedRedirectResourceData, GenericPlatform.UboAny);
                        // Special case: noop text resource
                        // If any of resource type is already present, we don't need to add other resource types,
                        // otherwise, add all resource types
                        // TODO: Optimize this logic
                        // Check if the current resource is the noop text resource
                        const isNoopTextResource = convertedRedirectResourceName === UBO_NOOP_TEXT_RESOURCE;
                        // Determine if there are any valid resource types already present
                        const hasValidResourceType = modifierList.children.some((modifier) => {
                            const name = modifier.name.value;
                            if (!isValidResourceType(name)) {
                                return false;
                            }
                            const convertedModifierData = modifiersCompatibilityTable.getFirst(name, GenericPlatform.UboAny);
                            return uboResourceTypeModifiers.has(convertedModifierData?.name ?? name);
                        });
                        // If it's not the noop text resource or if no valid resource types are present
                        if (!isNoopTextResource || !hasValidResourceType) {
                            uboResourceTypeModifiers.forEach((resourceType) => {
                                resourceTypeModifiersToAdd.add(resourceType);
                            });
                        }
                    }
                    // Check if the modifier name or the redirect resource name is different from the original modifier.
                    // If so, add the converted modifier to the list
                    if (modifierName !== originalModifierName
                        || (!isUndefined$1(convertedRedirectResourceName)
                            && convertedRedirectResourceName !== redirectResourceName)) {
                        conversionMap.add(index, createModifierNode(modifierName, 
                        // If the redirect resource name is unknown, fall back to the original one
                        // Later, the validator will throw an error if the resource name is invalid
                        convertedRedirectResourceName || redirectResourceName, modifierNode.exception));
                    }
                    return;
                }
                // Generic modifier conversion
                if (modifierData && modifierData.name !== originalModifierName) {
                    conversionMap.add(index, createModifierNode(modifierData.name, modifierNode.value?.value, modifierNode.exception));
                }
            });
            // Prepare the result if there are any converted modifiers or $csp modifiers
            if (conversionMap.size || resourceTypeModifiersToAdd.size) {
                const modifierListClone = cloneModifierListNode(modifierList);
                // Replace the original modifiers with the converted ones
                // One modifier may be replaced with multiple modifiers, so we need to flatten the array
                modifierListClone.children = modifierListClone.children.map((modifierNode, index) => {
                    const conversionRecord = conversionMap.get(index);
                    if (conversionRecord) {
                        return conversionRecord;
                    }
                    return modifierNode;
                }).flat();
                // Before returning the result, remove duplicated modifiers
                modifierListClone.children = modifierListClone.children.filter((modifierNode, index, self) => self.findIndex((m) => m.name.value === modifierNode.name.value
                    && m.exception === modifierNode.exception
                    && m.value?.value === modifierNode.value?.value) === index);
                if (resourceTypeModifiersToAdd.size) {
                    const modifierNameSet = new Set(modifierList.children.map((m) => m.name.value));
                    resourceTypeModifiersToAdd.forEach((resourceType) => {
                        if (!modifierNameSet.has(resourceType)) {
                            modifierListClone.children.push(createModifierNode(resourceType));
                        }
                    });
                }
                return createConversionResult(modifierListClone, true);
            }
            return createConversionResult(modifierList, false);
        }
    }

    /**
     * @file Network rule converter
     */
    /**
     * Network rule converter class (also known as "basic rule converter")
     *
     * @todo Implement `convertToUbo` and `convertToAbp`
     */
    class NetworkRuleConverter extends RuleConverterBase {
        /**
         * Converts a network rule to AdGuard format, if possible.
         *
         * @param rule Rule node to convert
         * @returns An object which follows the {@link NodeConversionResult} interface. Its `result` property contains
         * the array of converted rule nodes, and its `isConverted` flag indicates whether the original rule was converted.
         * If the rule was not converted, the result array will contain the original node with the same object reference
         * @throws If the rule is invalid or cannot be converted
         */
        static convertToAdg(rule) {
            // TODO: add support for host rules
            if (rule.type !== NetworkRuleType.NetworkRule) {
                throw new Error(`Invalid rule type: ${rule.type}`);
            }
            if (rule.modifiers) {
                const modifiers = NetworkRuleModifierListConverter.convertToAdg(rule.modifiers, rule.exception);
                // If the object reference is different, it means that the modifiers were converted
                // In this case, we should clone the entire rule and replace the modifiers with the converted ones
                if (modifiers.isConverted) {
                    return {
                        result: [{
                                category: RuleCategory.Network,
                                type: NetworkRuleType.NetworkRule,
                                syntax: rule.syntax,
                                exception: rule.exception,
                                pattern: {
                                    type: 'Value',
                                    value: rule.pattern.value,
                                },
                                modifiers: modifiers.result,
                            }],
                        isConverted: true,
                    };
                }
            }
            // If the modifiers were not converted, return the original rule
            return createNodeConversionResult([rule], false);
        }
        /**
         * Converts a network rule to uBlock format, if possible.
         *
         * @param rule Rule node to convert
         * @returns An object which follows the {@link NodeConversionResult} interface. Its `result` property contains
         * the array of converted rule nodes, and its `isConverted` flag indicates whether the original rule was converted.
         * If the rule was not converted, the result array will contain the original node with the same object reference
         * @throws If the rule is invalid or cannot be converted
         */
        static convertToUbo(rule) {
            // TODO: add support for host rules
            if (rule.type !== NetworkRuleType.NetworkRule) {
                throw new Error(`Invalid rule type: ${rule.type}`);
            }
            if (rule.modifiers) {
                const modifiers = NetworkRuleModifierListConverter.convertToUbo(rule.modifiers, rule.exception);
                // If the object reference is different, it means that the modifiers were converted
                // In this case, we should clone the entire rule and replace the modifiers with the converted ones
                if (modifiers.isConverted) {
                    return {
                        result: [{
                                category: RuleCategory.Network,
                                type: NetworkRuleType.NetworkRule,
                                syntax: rule.syntax,
                                exception: rule.exception,
                                pattern: {
                                    type: 'Value',
                                    value: rule.pattern.value,
                                },
                                modifiers: modifiers.result,
                            }],
                        isConverted: true,
                    };
                }
            }
            // If the modifiers were not converted, return the original rule
            return createNodeConversionResult([rule], false);
        }
    }

    /**
     * @file Adblock rule converter
     *
     * This file is the entry point for all rule converters
     * which automatically detects the rule type and calls
     * the corresponding "sub-converter".
     */
    /**
     * Adblock filtering rule converter class
     *
     * @todo Implement `convertToUbo` and `convertToAbp`
     */
    class RuleConverter extends RuleConverterBase {
        /**
         * Converts an adblock filtering rule to AdGuard format, if possible.
         *
         * @param rule Rule node to convert
         * @returns An object which follows the {@link NodeConversionResult} interface. Its `result` property contains
         * the array of converted rule nodes, and its `isConverted` flag indicates whether the original rule was converted.
         * If the rule was not converted, the result array will contain the original node with the same object reference
         * @throws If the rule is invalid or cannot be converted
         */
        static convertToAdg(rule) {
            // Delegate conversion to the corresponding sub-converter
            // based on the rule category
            switch (rule.category) {
                case RuleCategory.Comment:
                    return CommentRuleConverter.convertToAdg(rule);
                case RuleCategory.Cosmetic:
                    return CosmeticRuleConverter.convertToAdg(rule);
                case RuleCategory.Network:
                    // TODO: Handle hosts rules later
                    if (rule.type === NetworkRuleType.HostRule) {
                        return createConversionResult([rule], false);
                    }
                    return NetworkRuleConverter.convertToAdg(rule);
                case RuleCategory.Invalid:
                case RuleCategory.Empty:
                    // Just forward the rule as is
                    return createConversionResult([rule], false);
                default:
                    // Never happens during normal operation
                    throw new RuleConversionError('Unknown rule category');
            }
        }
        /**
         * Converts an adblock filtering rule to uBlock Origin format, if possible.
         *
         * @param rule Rule node to convert
         * @returns An object which follows the {@link NodeConversionResult} interface. Its `result` property contains
         * the array of converted rule nodes, and its `isConverted` flag indicates whether the original rule was converted.
         * If the rule was not converted, the result array will contain the original node with the same object reference
         * @throws If the rule is invalid or cannot be converted
         */
        // TODO: Add support for other rule types
        static convertToUbo(rule) {
            if (rule.category === RuleCategory.Cosmetic) {
                return CosmeticRuleConverter.convertToUbo(rule);
            }
            if (rule.category === RuleCategory.Network) {
                return NetworkRuleConverter.convertToUbo(rule);
            }
            return createConversionResult([rule], false);
        }
    }

    /**
     * Validates event type
     *
     * @param type event type
     * @returns true if type is valid
     */
    var validateType = function validateType(type) {
      // https://github.com/AdguardTeam/Scriptlets/issues/125
      return typeof type !== 'undefined';
    };

    /**
     * Validates event listener
     *
     * @param listener event listener
     * @returns true if listener callback is valid
     */
    var validateListener = function validateListener(listener) {
      // https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener#parameters
      return typeof listener !== 'undefined' && (typeof listener === 'function' || typeof listener === 'object'
      // https://github.com/AdguardTeam/Scriptlets/issues/76
      && listener !== null && 'handleEvent' in listener && typeof listener.handleEvent === 'function');
    };

    /**
     * Serialize valid event listener
     * https://developer.mozilla.org/en-US/docs/Web/API/EventListener
     *
     * @param listener valid listener
     * @returns listener string
     */
    var listenerToString = function listenerToString(listener) {
      return typeof listener === 'function' ? listener.toString() : listener.handleEvent.toString();
    };

    /**
     * Determines whether the passed value is NaN
     * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/isNaN
     *
     * @param num arbitrary value
     * @returns if provided value is NaN
     */
    var nativeIsNaN = function nativeIsNaN(num) {
      // eslint-disable-next-line no-restricted-properties
      var native = Number.isNaN || window.isNaN;
      return native(num);
    };
    /**
     * Determines whether the passed value is a finite number
     * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/isFinite
     *
     * @param num arbitrary value
     * @returns if provided value is finite
     */
    var nativeIsFinite = function nativeIsFinite(num) {
      // eslint-disable-next-line no-restricted-properties
      var native = Number.isFinite || window.isFinite;
      return native(num);
    };

    /**
     * Parses string for a number, if possible, otherwise returns null.
     *
     * @param rawString arbitrary string
     * @returns number or null if string not parsable
     */
    var getNumberFromString = function getNumberFromString(rawString) {
      var parsedDelay = parseInt(rawString, 10);
      var validDelay = nativeIsNaN(parsedDelay) ? null : parsedDelay;
      return validDelay;
    };

    /**
     * Generate a random integer between two values, inclusive
     * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/random#getting_a_random_integer_between_two_values_inclusive
     *
     * @param min range minimum
     * @param max range maximum
     * @returns random number
     */
    function getRandomIntInclusive(min, max) {
      min = Math.ceil(min);
      max = Math.floor(max);
      return Math.floor(Math.random() * (max - min + 1) + min);
    }

    var shouldMatchAnyDelay = function shouldMatchAnyDelay(delay) {
      return delay === '*';
    };

    /**
     * Handles input delay value
     *
     * @param delay matchDelay argument of adjust-* scriptlets
     * @returns proper number delay value
     */
    var getMatchDelay = function getMatchDelay(delay) {
      var DEFAULT_DELAY = 1000;
      var parsedDelay = parseInt(delay, 10);
      var delayMatch = nativeIsNaN(parsedDelay) ? DEFAULT_DELAY // default scriptlet value
      : parsedDelay;
      return delayMatch;
    };

    /**
     * Checks delay match condition
     *
     * @param inputDelay matchDelay argument of adjust-* scriptlets
     * @param realDelay delay argument of setTimeout/setInterval
     * @returns  if given delays match
     */
    var isDelayMatched = function isDelayMatched(inputDelay, realDelay) {
      return shouldMatchAnyDelay(inputDelay) || realDelay === getMatchDelay(inputDelay);
    };

    /**
     * Handles input boost value
     *
     * @param boost boost argument of adjust-* scriptlets
     * @returns proper number boost multiplier value
     */
    var getBoostMultiplier = function getBoostMultiplier(boost) {
      var DEFAULT_MULTIPLIER = 0.05;
      // https://github.com/AdguardTeam/Scriptlets/issues/262
      var MIN_MULTIPLIER = 0.001;
      var MAX_MULTIPLIER = 50;
      var parsedBoost = parseFloat(boost);
      var boostMultiplier = nativeIsNaN(parsedBoost) || !nativeIsFinite(parsedBoost) ? DEFAULT_MULTIPLIER // default scriptlet value
      : parsedBoost;
      if (boostMultiplier < MIN_MULTIPLIER) {
        boostMultiplier = MIN_MULTIPLIER;
      }
      if (boostMultiplier > MAX_MULTIPLIER) {
        boostMultiplier = MAX_MULTIPLIER;
      }
      return boostMultiplier;
    };

    /**
     * Some browsers do not support Array.prototype.flat()
     * for example, Opera 42 which is used for browserstack tests
     * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/flat
     *
     * @param input arbitrary array
     * @returns flattened array
     */
    var flatten = function flatten(input) {
      var stack = [];
      input.forEach(function (el) {
        return stack.push(el);
      });
      var res = [];
      while (stack.length) {
        // pop value from stack
        var next = stack.pop();
        if (Array.isArray(next)) {
          // push back array items, won't modify the original input
          next.forEach(function (el) {
            return stack.push(el);
          });
        } else {
          res.push(next);
        }
      }
      // reverse to restore input order
      return res.reverse();
    };

    /**
     * Converts NodeList to array
     *
     * @param {NodeList} nodeList arbitrary NodeList
     * @returns {Node[Array]} array of nodes
     */
    var nodeListToArray = function nodeListToArray(nodeList) {
      var nodes = [];
      for (var i = 0; i < nodeList.length; i += 1) {
        nodes.push(nodeList[i]);
      }
      return nodes;
    };

    /**
     * Conditionally logs message to console.
     * Convention is to log messages by source.verbose if such log
     * is not a part of scriptlet's functionality, eg on invalid input,
     * and use 'forced' argument otherwise.
     *
     * @param source required, scriptlet properties
     * @param message required, message to log
     * @param forced to log message unconditionally
     * @param convertMessageToString to convert message to string
     */
    var logMessage = function logMessage(source, message) {
      var forced = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
      var convertMessageToString = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : true;
      var name = source.name,
        verbose = source.verbose;
      if (!forced && !verbose) {
        return;
      }

      // eslint-disable-next-line no-console
      var nativeConsole = console.log;
      if (!convertMessageToString) {
        // Template literals convert object to string,
        // so 'message' should not be passed to template literals
        // as it will not be logged correctly
        nativeConsole("".concat(name, ":"), message);
        return;
      }
      nativeConsole("".concat(name, ": ").concat(message));
    };

    /* eslint-disable no-console, no-underscore-dangle */

    /**
     * Hit used only for debug purposes now
     *
     * @param source scriptlet properties
     * use LOG_MARKER = 'log: ' at the start of a message
     * for logging scriptlets
     */
    var hit = function hit(source) {
      var ADGUARD_PREFIX = '[AdGuard]';
      if (!source.verbose) {
        return;
      }
      try {
        var trace = console.trace.bind(console);
        var label = "".concat(ADGUARD_PREFIX, " ");
        if (source.engine === 'corelibs') {
          // rule text will be available for corelibs
          label += source.ruleText;
        } else {
          if (source.domainName) {
            label += "".concat(source.domainName);
          }
          if (source.args) {
            label += "#%#//scriptlet('".concat(source.name, "', '").concat(source.args.join("', '"), "')");
          } else {
            label += "#%#//scriptlet('".concat(source.name, "')");
          }
        }
        if (trace) {
          trace(label);
        }
      } catch (e) {
        // try catch for Edge 15
        // In according to this issue https://developer.microsoft.com/en-us/microsoft-edge/platform/issues/14495220/
        // console.log throws an error
      }

      // This is necessary for unit-tests only!
      if (typeof window.__debug === 'function') {
        window.__debug(source);
      }
    };

    /**
     * Sets attribute with given value to given element.
     *
     * @param elem Element to set attribute to.
     * @param attribute Attribute name to set.
     * @param value Attribute value to set.
     */
    var defaultAttributeSetter = function defaultAttributeSetter(elem, attribute, value) {
      return elem.setAttribute(attribute, value);
    };

    /**
     * Sets attribute with given value to all elements matching given selector
     *
     * @param source source
     * @param selector CSS selector
     * @param attribute attribute name to set
     * @param value attribute value to set
     * @param attributeSetter function to apply to each element,
     * defaults to native .setAttribute
     */
    var setAttributeBySelector = function setAttributeBySelector(source, selector, attribute, value) {
      var attributeSetter = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : defaultAttributeSetter;
      var elements;
      try {
        elements = document.querySelectorAll(selector);
      } catch (_unused) {
        logMessage(source, "Failed to find elements matching selector \"".concat(selector, "\""));
        return;
      }
      if (!elements || elements.length === 0) {
        return;
      }
      try {
        elements.forEach(function (elem) {
          return attributeSetter(elem, attribute, value);
        });
        hit(source);
      } catch (_unused2) {
        logMessage(source, "Failed to set [".concat(attribute, "=\"").concat(value, "\"] to each of selected elements."));
      }
    };

    /**
     * Parsed attribute data type.
     */

    /**
     * Parses attribute pairs string into an array of objects with name and value properties.
     *
     * @param input Attribute pairs string.
     *
     * @returns Array of objects with name and value properties.
     * @throws Error if input is invalid.
     */
    var parseAttributePairs = function parseAttributePairs(input) {
      if (!input) {
        return [];
      }
      var NAME_VALUE_SEPARATOR = '=';
      var PAIRS_SEPARATOR = ' ';
      var SINGLE_QUOTE = "'";
      var DOUBLE_QUOTE = '"';
      var BACKSLASH = '\\';
      var pairs = [];
      for (var i = 0; i < input.length; i += 1) {
        var name = '';
        var value = '';

        // collect the name
        while (i < input.length && input[i] !== NAME_VALUE_SEPARATOR && input[i] !== PAIRS_SEPARATOR) {
          name += input[i];
          i += 1;
        }
        if (i < input.length && input[i] === NAME_VALUE_SEPARATOR) {
          // skip the '='
          i += 1;
          var quote = null;
          if (input[i] === SINGLE_QUOTE || input[i] === DOUBLE_QUOTE) {
            quote = input[i];
            // Skip the opening quote
            i += 1;
            for (; i < input.length; i += 1) {
              if (input[i] === quote) {
                if (input[i - 1] === BACKSLASH) {
                  // remove the backslash and save the quote to the value
                  value = "".concat(value.slice(0, -1)).concat(quote);
                } else {
                  // Skip the closing quote
                  i += 1;
                  quote = null;
                  break;
                }
              } else {
                value += input[i];
              }
            }
            if (quote !== null) {
              throw new Error("Unbalanced quote for attribute value: '".concat(input, "'"));
            }
          } else {
            throw new Error("Attribute value should be quoted: \"".concat(input.slice(i), "\""));
          }
        }
        name = name.trim();
        value = value.trim();
        if (!name) {
          if (!value) {
            // skip multiple spaces between pairs, e.g.
            // 'name1="value1"  name2="value2"'
            continue;
          }
          throw new Error("Attribute name before '=' should be specified: '".concat(input, "'"));
        }
        pairs.push({
          name,
          value
        });
        if (input[i] && input[i] !== PAIRS_SEPARATOR) {
          throw new Error("No space before attribute: '".concat(input.slice(i), "'"));
        }
      }
      return pairs;
    };

    /**
     * Checks whether the input path is supported
     *
     * @param rawPath input path
     * @returns if cookie path is valid
     */
    var isValidCookiePath = function isValidCookiePath(rawPath) {
      return rawPath === '/' || rawPath === 'none';
    };

    /**
     * Returns 'path=/' if rawPath is '/'
     * or empty string '' for other cases, `rawPath === 'none'` included
     *
     * @param rawPath path argument of *set-cookie-* scriptlets
     * @returns cookie path
     */
    var getCookiePath = function getCookiePath(rawPath) {
      if (rawPath === '/') {
        return 'path=/';
      }
      // otherwise do not set path as invalid
      // the same for pathArg === 'none'
      return '';
    };

    /**
     * Combines input cookie name, value, and path into string.
     *
     * @param name name argument of *set-cookie-* scriptlets
     * @param rawValue value argument of *set-cookie-* scriptlets
     * @param rawPath path argument of *set-cookie-* scriptlets
     * @param domainValue domain argument of *set-cookie-* scriptlets
     * @param shouldEncodeValue if cookie value should be encoded. Default is `true`
     *
     * @returns string OR `null` if name or value is invalid
     */
    var serializeCookie = function serializeCookie(name, rawValue, rawPath) {
      var domainValue = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : '';
      var shouldEncodeValue = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : true;
      var HOST_PREFIX = '__Host-';
      var SECURE_PREFIX = '__Secure-';
      var COOKIE_BREAKER = ';';

      // semicolon will cause the cookie to break
      if (!shouldEncodeValue && "".concat(rawValue).includes(COOKIE_BREAKER) || name.includes(COOKIE_BREAKER)) {
        return null;
      }
      var value = shouldEncodeValue ? encodeURIComponent(rawValue) : rawValue;
      var resultCookie = "".concat(name, "=").concat(value);
      if (name.startsWith(HOST_PREFIX)) {
        // Cookie with "__Host-" prefix requires "secure" flag, path must be "/",
        // and must not have a domain specified
        // https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie#attributes
        // https://github.com/AdguardTeam/Scriptlets/issues/448
        resultCookie += '; path=/; secure';
        if (domainValue) {
          // eslint-disable-next-line no-console
          console.debug("Domain value: \"".concat(domainValue, "\" has been ignored, because is not allowed for __Host- prefixed cookies"));
        }
        return resultCookie;
      }
      var path = getCookiePath(rawPath);
      if (path) {
        resultCookie += "; ".concat(path);
      }
      if (name.startsWith(SECURE_PREFIX)) {
        // Cookie with "__Secure-" prefix requires "secure" flag
        resultCookie += '; secure';
      }
      if (domainValue) {
        resultCookie += "; domain=".concat(domainValue);
      }
      return resultCookie;
    };

    /**
     * Gets supported cookie value
     *
     * @param value input cookie value
     * @returns valid cookie string if ok OR null if not
     */
    var getLimitedCookieValue = function getLimitedCookieValue(value) {
      if (!value) {
        return null;
      }
      var allowedCookieValues = new Set(['true', 't', 'false', 'f', 'yes', 'y', 'no', 'n', 'ok', 'on', 'off', 'accept', 'accepted', 'notaccepted', 'reject', 'rejected', 'allow', 'allowed', 'disallow', 'deny', 'enable', 'enabled', 'disable', 'disabled', 'necessary', 'required', 'hide', 'hidden', 'essential', 'nonessential', 'checked', 'unchecked']);
      var validValue;
      if (allowedCookieValues.has(value.toLowerCase())) {
        validValue = value;
      } else if (/^\d+$/.test(value)) {
        validValue = parseFloat(value);
        if (nativeIsNaN(validValue)) {
          return null;
        }
        if (Math.abs(validValue) < 0 || Math.abs(validValue) > 32767) {
          return null;
        }
      } else {
        return null;
      }
      return validValue;
    };

    /**
     * Object to represent document.cookie-like string
     */

    /**
     * Parses cookie string into object
     *
     * @param cookieString string that conforms to document.cookie format
     * @returns key:value object that corresponds with incoming cookies keys and values
     */
    var parseCookieString = function parseCookieString(cookieString) {
      var COOKIE_DELIMITER = '=';
      var COOKIE_PAIRS_DELIMITER = ';';

      // Get raw cookies
      var cookieChunks = cookieString.split(COOKIE_PAIRS_DELIMITER);
      var cookieData = {};
      cookieChunks.forEach(function (singleCookie) {
        var cookieKey;
        var cookieValue = '';
        var delimiterIndex = singleCookie.indexOf(COOKIE_DELIMITER);
        if (delimiterIndex === -1) {
          cookieKey = singleCookie.trim();
        } else {
          cookieKey = singleCookie.slice(0, delimiterIndex).trim();
          cookieValue = singleCookie.slice(delimiterIndex + 1);
        }
        // Save cookie key=value data with null instead of empty ('') values
        cookieData[cookieKey] = cookieValue || null;
      });
      return cookieData;
    };

    /**
     * Check if cookie with specified name and value is present in a cookie string
     *
     * @param cookieString 'document.cookie'-like string
     * @param name name argument of *set-cookie-* scriptlets
     * @param value value argument of *set-cookie-* scriptlets
     * @returns if cookie is already set
     */
    var isCookieSetWithValue = function isCookieSetWithValue(cookieString, name, value) {
      return cookieString.split(';').some(function (cookieStr) {
        var pos = cookieStr.indexOf('=');
        if (pos === -1) {
          return false;
        }
        var cookieName = cookieStr.slice(0, pos).trim();
        var cookieValue = cookieStr.slice(pos + 1).trim();
        return name === cookieName && value === cookieValue;
      });
    };

    /**
     * Returns parsed offset expired number of ms or null if `offsetExpiresSec` is invalid
     *
     * @param offsetExpiresSec input offset param in seconds
     * @returns number is milliseconds OR null
     */
    var getTrustedCookieOffsetMs = function getTrustedCookieOffsetMs(offsetExpiresSec) {
      var ONE_YEAR_EXPIRATION_KEYWORD = '1year';
      var ONE_DAY_EXPIRATION_KEYWORD = '1day';
      var MS_IN_SEC = 1000;
      var SECONDS_IN_YEAR = 365 * 24 * 60 * 60;
      var SECONDS_IN_DAY = 24 * 60 * 60;
      var parsedSec;
      // Set predefined expire value if corresponding keyword was passed
      if (offsetExpiresSec === ONE_YEAR_EXPIRATION_KEYWORD) {
        parsedSec = SECONDS_IN_YEAR;
      } else if (offsetExpiresSec === ONE_DAY_EXPIRATION_KEYWORD) {
        parsedSec = SECONDS_IN_DAY;
      } else {
        parsedSec = Number.parseInt(offsetExpiresSec, 10);
        // If offsetExpiresSec has been parsed to NaN - do not set cookie at all
        if (Number.isNaN(parsedSec)) {
          return null;
        }
      }
      return parsedSec * MS_IN_SEC;
    };

    /**
     * Noop function
     */
    var noopFunc = function noopFunc() {};

    /**
     * Function returns noopFunc
     *
     * @returns noopFunc
     */
    var noopCallbackFunc = function noopCallbackFunc() {
      return noopFunc;
    };

    /**
     * Function returns null
     *
     * @returns null
     */
    var noopNull = function noopNull() {
      return null;
    };

    /**
     * Function returns true
     *
     * @returns true
     */
    var trueFunc = function trueFunc() {
      return true;
    };

    /**
     * Function returns false
     *
     * @returns false
     */
    var falseFunc = function falseFunc() {
      return false;
    };

    /**
     * Function returns this
     *
     * @returns this object
     */
    function noopThis() {
      // eslint-disable-next-line @typescript-eslint/ban-ts-comment
      // @ts-ignore
      return this;
    }

    /**
     * Function returns empty string
     *
     * @returns empty string
     */
    var noopStr = function noopStr() {
      return '';
    };

    /**
     * Function returns empty array
     *
     * @returns empty array
     */
    var noopArray = function noopArray() {
      return [];
    };

    /**
     * Function returns empty object
     *
     * @returns empty object
     */
    var noopObject = function noopObject() {
      return {};
    };

    /**
     * Function throws an error
     *
     * @throws
     */
    var throwFunc = function throwFunc() {
      throw new Error();
    };

    /**
     * Function returns Promise.resolve()
     *
     * @returns promise which resolves to void
     */
    var noopResolveVoid = function noopResolveVoid() {
      return Promise.resolve(undefined);
    };

    /**
     * Function returns Promise.resolve(null)
     *
     * @returns promise which resolves to null
     */
    var noopResolveNull = function noopResolveNull() {
      return Promise.resolve(null);
    };

    /**
     * Function returns Promise.reject()
     *
     * @returns rejected Promise
     */
    var noopPromiseReject = function noopPromiseReject() {
      return Promise.reject();
    };

    /**
     * Returns Promise object that is resolved with specified props
     *
     * @param responseBody value to set as responseBody
     * @param responseUrl value to set as responseUrl
     * @param responseType value to set as responseType
     * @returns resolved Promise or undefined if Response interface is not available
     */
    var noopPromiseResolve = function noopPromiseResolve() {
      var responseBody = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : '{}';
      var responseUrl = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : '';
      var responseType = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 'basic';
      if (typeof Response === 'undefined') {
        return;
      }
      var response = new Response(responseBody, {
        status: 200,
        statusText: 'OK'
      });

      /**
       * If responseType is opaque, then by default
       * body is null, status is 0, statusText and url are empty strings,
       * as per https://fetch.spec.whatwg.org/#concept-filtered-response-opaque
       * It's required to mock these properties to avoid adblock detection
       * https://github.com/AdguardTeam/Scriptlets/issues/364
       */
      if (responseType === 'opaque') {
        Object.defineProperties(response, {
          body: {
            value: null
          },
          status: {
            value: 0
          },
          statusText: {
            value: ''
          },
          url: {
            value: ''
          },
          type: {
            value: responseType
          }
        });
      } else {
        // Mock response' url & type to avoid adb checks
        // https://github.com/AdguardTeam/Scriptlets/issues/216
        Object.defineProperties(response, {
          url: {
            value: responseUrl
          },
          type: {
            value: responseType
          }
        });
      }

      // eslint-disable-next-line consistent-return
      return Promise.resolve(response);
    };

    /**
     * Checks whether the obj is an empty object
     *
     * @param obj arbitrary object
     * @returns if object is empty
     */
    var isEmptyObject = function isEmptyObject(obj) {
      return Object.keys(obj).length === 0 && !obj.prototype;
    };

    /**
     * Safely retrieve property descriptor
     *
     * @param obj target object
     * @param  prop target property
     * @returns descriptor or null if it's not available or non-configurable
     */
    var safeGetDescriptor = function safeGetDescriptor(obj, prop) {
      var descriptor = Object.getOwnPropertyDescriptor(obj, prop);
      if (descriptor && descriptor.configurable) {
        return descriptor;
      }
      return null;
    };

    /**
     * Set getter and setter to property if it's configurable
     *
     * @param  object target object with property
     * @param property property name
     * @param descriptor contains getter and setter functions
     * @returns is operation successful
     */
    function setPropertyAccess(object, property, descriptor) {
      var currentDescriptor = Object.getOwnPropertyDescriptor(object, property);
      if (currentDescriptor && !currentDescriptor.configurable) {
        return false;
      }
      Object.defineProperty(object, property, descriptor);
      return true;
    }

    /**
     * Checks whether the value is an arbitrary object
     *
     * @param value arbitrary value
     * @returns true, if value is an arbitrary object
     */
    function isArbitraryObject(value) {
      return value !== null && typeof value === 'object' && !Array.isArray(value) && !(value instanceof RegExp);
    }

    /**
     * Escapes special chars in string
     *
     * @param str raw string
     * @returns string with escaped special characters
     */
    var escapeRegExp = function escapeRegExp(str) {
      return str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
    };

    /**
     * Converts string to the regexp,
     * if string contains valid regexp flags it will be converted to regexp with flags
     * TODO think about nested dependencies, but be careful with dependency loops
     *
     * @param rawInput literal string or regexp pattern; defaults to '' (empty string)
     * @returns regular expression; defaults to /.?/
     */
    var toRegExp = function toRegExp(rawInput) {
      var input = rawInput || '';
      var DEFAULT_VALUE = '.?';
      var FORWARD_SLASH = '/';
      if (input === '') {
        return new RegExp(DEFAULT_VALUE);
      }
      var delimiterIndex = input.lastIndexOf(FORWARD_SLASH);
      var flagsPart = input.substring(delimiterIndex + 1);
      var regExpPart = input.substring(0, delimiterIndex + 1);

      /**
       * Checks whether the string is a valid regexp flag
       *
       * @param flag string
       * @returns True if regexp flag is valid, otherwise false.
       */
      var isValidRegExpFlag = function isValidRegExpFlag(flag) {
        if (!flag) {
          return false;
        }
        try {
          // eslint-disable-next-line no-new
          new RegExp('', flag);
          return true;
        } catch (ex) {
          return false;
        }
      };

      /**
       * Checks whether the text string contains valid regexp flags,
       * and returns `flagsStr` if valid, otherwise empty string.
       *
       * @param regExpStr string
       * @param flagsStr string
       * @returns `flagsStr` if it is valid, otherwise empty string.
       */
      var getRegExpFlags = function getRegExpFlags(regExpStr, flagsStr) {
        if (regExpStr.startsWith(FORWARD_SLASH) && regExpStr.endsWith(FORWARD_SLASH)
        // Not a correct regex if ends with '\\/'
        && !regExpStr.endsWith('\\/') && isValidRegExpFlag(flagsStr)) {
          return flagsStr;
        }
        return '';
      };
      var flags = getRegExpFlags(regExpPart, flagsPart);
      if (input.startsWith(FORWARD_SLASH) && input.endsWith(FORWARD_SLASH) || flags) {
        var regExpInput = flags ? regExpPart : input;
        return new RegExp(regExpInput.slice(1, -1), flags);
      }
      var escaped = input
      // remove quotes' escapes for cases where scriptlet rule argument has own escaped quotes
      // e.g #%#//scriptlet('prevent-setTimeout', '.css(\'display\',\'block\');')
      .replace(/\\'/g, '\'').replace(/\\"/g, '"')
      // escape special characters for following RegExp construction
      .replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
      return new RegExp(escaped);
    };

    /**
     * Checks whether the input string can be converted to regexp
     *
     * @param input literal string or regexp pattern
     * @returns if input can be converted to regexp
     */
    var isValidStrPattern = function isValidStrPattern(input) {
      var FORWARD_SLASH = '/';
      var str = escapeRegExp(input);
      if (input[0] === FORWARD_SLASH && input[input.length - 1] === FORWARD_SLASH) {
        str = input.slice(1, -1);
      }
      var isValid;
      try {
        isValid = new RegExp(str);
        isValid = true;
      } catch (e) {
        isValid = false;
      }
      return isValid;
    };
    var substringAfter = function substringAfter(str, separator) {
      if (!str) {
        return str;
      }
      var index = str.indexOf(separator);
      return index < 0 ? '' : str.substring(index + separator.length);
    };
    var substringBefore = function substringBefore(str, separator) {
      if (!str || !separator) {
        return str;
      }
      var index = str.indexOf(separator);
      return index < 0 ? str : str.substring(0, index);
    };

    /**
     * Prepares RTCPeerConnection config as string for proper logging
     *
     * @param config RTC config
     * @returns stringified config
     */
    var convertRtcConfigToString = function convertRtcConfigToString(config) {
      var UNDEF_STR = 'undefined';
      var str = UNDEF_STR;
      if (config === null) {
        str = 'null';
      } else if (config instanceof Object) {
        var SERVERS_PROP_NAME = 'iceServers';
        var URLS_PROP_NAME = 'urls';
        /*
            const exampleConfig = {
                'iceServers': [
                    'urls': ['stun:35.66.206.188:443'],
                ],
            };
        */
        if (Object.prototype.hasOwnProperty.call(config, SERVERS_PROP_NAME) && config[SERVERS_PROP_NAME] && Object.prototype.hasOwnProperty.call(config[SERVERS_PROP_NAME][0], URLS_PROP_NAME) && !!config[SERVERS_PROP_NAME][0][URLS_PROP_NAME]) {
          str = config[SERVERS_PROP_NAME][0][URLS_PROP_NAME].toString();
        }
      }
      return str;
    };

    /**
     * Checks whether the match input string can be converted to regexp,
     * used for match inputs with possible negation
     *
     * @param match literal string or regexp pattern
     * @returns true if input can be converted to regexp
     */
    var isValidMatchStr = function isValidMatchStr(match) {
      var INVERT_MARKER = '!';
      var str = match;
      if (match !== null && match !== void 0 && match.startsWith(INVERT_MARKER)) {
        str = match.slice(1);
      }
      return isValidStrPattern(str);
    };

    /**
     * Validates the match input number,
     * used for match inputs with possible negation
     *
     * @param match string of match number
     * @returns if match number is valid
     */
    var isValidMatchNumber = function isValidMatchNumber(match) {
      var INVERT_MARKER = '!';
      var str = match;
      if (match !== null && match !== void 0 && match.startsWith(INVERT_MARKER)) {
        str = match.slice(1);
      }
      var num = parseFloat(str);
      return !nativeIsNaN(num) && nativeIsFinite(num);
    };

    /**
     * Parses match arg with possible negation for no matching.
     * Needed for prevent-setTimeout, prevent-setInterval,
     * prevent-requestAnimationFrame and prevent-window-open
     *
     * @param match matching arg
     * @returns data prepared for matching
     */
    var parseMatchArg = function parseMatchArg(match) {
      var INVERT_MARKER = '!';
      // In case if "match" is "undefined" return "false"
      var isInvertedMatch = match ? match === null || match === void 0 ? void 0 : match.startsWith(INVERT_MARKER) : false;
      var matchValue = isInvertedMatch ? match.slice(1) : match;
      var matchRegexp = toRegExp(matchValue);
      return {
        isInvertedMatch,
        matchRegexp,
        matchValue
      };
    };

    /**
     * Parses delay arg with possible negation for no matching.
     * Needed for prevent-setTimeout and prevent-setInterval
     *
     * @param delay scriptlet's delay arg
     * @returns parsed delay data
     */
    var parseDelayArg = function parseDelayArg(delay) {
      var INVERT_MARKER = '!';
      var isInvertedDelayMatch = delay === null || delay === void 0 ? void 0 : delay.startsWith(INVERT_MARKER);
      var delayValue = isInvertedDelayMatch ? delay.slice(1) : delay;
      var parsedDelay = parseInt(delayValue, 10);
      var delayMatch = nativeIsNaN(parsedDelay) ? null : parsedDelay;
      return {
        isInvertedDelayMatch,
        delayMatch
      };
    };

    /**
     * Converts object to string for logging
     *
     * @param obj data object
     * @returns object's string representation
     */
    var objectToString$1 = function objectToString(obj) {
      // In case if the type of passed obj is different than Object
      // https://github.com/AdguardTeam/Scriptlets/issues/282
      if (!obj || typeof obj !== 'object') {
        return String(obj);
      }
      if (isEmptyObject(obj)) {
        return '{}';
      }
      return Object.entries(obj).map(function (pair) {
        var key = pair[0];
        var value = pair[1];
        var recordValueStr = value;
        if (value instanceof Object) {
          recordValueStr = "{ ".concat(objectToString(value), " }");
        }
        return "".concat(key, ":\"").concat(recordValueStr, "\"");
      }).join(' ');
    };

    /**
     * Converts types into a string
     *
     * @param value input value type
     * @returns type's string representation
     */
    var convertTypeToString = function convertTypeToString(value) {
      var output;
      if (typeof value === 'undefined') {
        output = 'undefined';
      } else if (typeof value === 'object') {
        if (value === null) {
          output = 'null';
        } else {
          output = objectToString$1(value);
        }
      } else {
        output = String(value);
      }
      return output;
    };

    /**
     * Generate a random string, a length of the string is provided as an argument
     *
     * @param length output's length
     * @returns random string
     */
    function getRandomStrByLength(length) {
      var result = '';
      var characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789!@#$%^&*()_+=~';
      var charactersLength = characters.length;
      for (var i = 0; i < length; i += 1) {
        result += characters.charAt(Math.floor(Math.random() * charactersLength));
      }
      return result;
    }

    /**
     * Generate a random string
     *
     * @param customResponseText response text to include in output
     * @returns random string or null if passed argument is invalid
     */
    function generateRandomResponse(customResponseText) {
      var customResponse = customResponseText;
      if (customResponse === 'true') {
        // Generate random alphanumeric string of 10 symbols
        customResponse = Math.random().toString(36).slice(-10);
        return customResponse;
      }
      customResponse = customResponse.replace('length:', '');
      var rangeRegex = /^\d+-\d+$/;
      // Return empty string if range is invalid
      if (!rangeRegex.test(customResponse)) {
        return null;
      }
      var rangeMin = getNumberFromString(customResponse.split('-')[0]);
      var rangeMax = getNumberFromString(customResponse.split('-')[1]);
      if (!nativeIsFinite(rangeMin) || !nativeIsFinite(rangeMax)) {
        return null;
      }

      // If rangeMin > rangeMax, swap variables
      if (rangeMin > rangeMax) {
        var temp = rangeMin;
        rangeMin = rangeMax;
        rangeMax = temp;
      }
      var LENGTH_RANGE_LIMIT = 500 * 1000;
      if (rangeMax > LENGTH_RANGE_LIMIT) {
        return null;
      }
      var length = getRandomIntInclusive(rangeMin, rangeMax);
      customResponse = getRandomStrByLength(length);
      return customResponse;
    }

    /**
     * Infers value from string argument
     * Inferring goes from more specific to more ambiguous options
     * Arrays, objects and strings are parsed via JSON.parse
     *
     * @param value arbitrary string
     * @returns converted value
     * @throws an error on unexpected input
     */
    function inferValue(value) {
      if (value === 'undefined') {
        return undefined;
      }
      if (value === 'false') {
        return false;
      }
      if (value === 'true') {
        return true;
      }
      if (value === 'null') {
        return null;
      }
      if (value === 'NaN') {
        return NaN;
      }
      if (value.startsWith('/') && value.endsWith('/')) {
        return toRegExp(value);
      }

      // Number class constructor works 2 times faster than JSON.parse
      // and wont interpret mixed inputs like '123asd' as parseFloat would
      var MAX_ALLOWED_NUM = 32767;
      var numVal = Number(value);
      if (!nativeIsNaN(numVal)) {
        if (Math.abs(numVal) > MAX_ALLOWED_NUM) {
          throw new Error('number values bigger than 32767 are not allowed');
        }
        return numVal;
      }
      var errorMessage = "'".concat(value, "' value type can't be inferred");
      try {
        // Parse strings, arrays and objects represented as JSON strings
        // '[1,2,3,"string"]' > [1, 2, 3, 'string']
        // '"arbitrary string"' > 'arbitrary string'
        var parsableVal = JSON.parse(value);
        if (parsableVal instanceof Object || typeof parsableVal === 'string') {
          return parsableVal;
        }
      } catch (e) {
        errorMessage += ": ".concat(e);
      }
      throw new TypeError(errorMessage);
    }

    /**
     * Determines if type of script is inline or injected
     * and when it's one of them then return true, otherwise false
     * https://github.com/AdguardTeam/Scriptlets/issues/201
     *
     * @param stackMatch input stack value to match
     * @param stackTrace script error stack trace
     * @returns if stacks match
     */
    var shouldAbortInlineOrInjectedScript = function shouldAbortInlineOrInjectedScript(stackMatch, stackTrace) {
      var INLINE_SCRIPT_STRING = 'inlineScript';
      var INJECTED_SCRIPT_STRING = 'injectedScript';
      var INJECTED_SCRIPT_MARKER = '<anonymous>';
      var isInlineScript = function isInlineScript(match) {
        return match.includes(INLINE_SCRIPT_STRING);
      };
      var isInjectedScript = function isInjectedScript(match) {
        return match.includes(INJECTED_SCRIPT_STRING);
      };
      if (!(isInlineScript(stackMatch) || isInjectedScript(stackMatch))) {
        return false;
      }
      var documentURL = window.location.href;
      var pos = documentURL.indexOf('#');
      // Remove URL hash
      // in Chrome, URL in stackTrace doesn't contain hash
      // so, it's necessary to remove it, otherwise location.href
      // will not match with location from stackTrace
      if (pos !== -1) {
        documentURL = documentURL.slice(0, pos);
      }
      var stackSteps = stackTrace.split('\n').slice(2).map(function (line) {
        return line.trim();
      });
      var stackLines = stackSteps.map(function (line) {
        var stack;
        // Get stack trace values
        // in Firefox stack trace looks like this: advanceTaskQueue@http://127.0.0.1:8080/scriptlets/tests/dist/qunit.js:1834:20
        // in Chrome like this: at Assert.throws (http://127.0.0.1:8080/scriptlets/tests/dist/qunit.js:3178:16)
        // so, first group "(.*?@)" is required for Firefox, second group contains URL,
        // third group contains line number, fourth group contains column number
        var getStackTraceValues = /(.*?@)?(\S+)(:\d+)(:\d+)\)?$/.exec(line);
        if (getStackTraceValues) {
          var _stackURL, _stackURL2;
          var stackURL = getStackTraceValues[2];
          var stackLine = getStackTraceValues[3];
          var stackCol = getStackTraceValues[4];
          if ((_stackURL = stackURL) !== null && _stackURL !== void 0 && _stackURL.startsWith('(')) {
            stackURL = stackURL.slice(1);
          }
          if ((_stackURL2 = stackURL) !== null && _stackURL2 !== void 0 && _stackURL2.startsWith(INJECTED_SCRIPT_MARKER)) {
            var _stackFunction;
            stackURL = INJECTED_SCRIPT_STRING;
            var stackFunction = getStackTraceValues[1] !== undefined ? getStackTraceValues[1].slice(0, -1) : line.slice(0, getStackTraceValues.index).trim();
            if ((_stackFunction = stackFunction) !== null && _stackFunction !== void 0 && _stackFunction.startsWith('at')) {
              stackFunction = stackFunction.slice(2).trim();
            }
            stack = "".concat(stackFunction, " ").concat(stackURL).concat(stackLine).concat(stackCol).trim();
          } else if (stackURL === documentURL) {
            stack = "".concat(INLINE_SCRIPT_STRING).concat(stackLine).concat(stackCol).trim();
          } else {
            stack = "".concat(stackURL).concat(stackLine).concat(stackCol).trim();
          }
        } else {
          stack = line;
        }
        return stack;
      });
      if (stackLines) {
        for (var index = 0; index < stackLines.length; index += 1) {
          if (isInlineScript(stackMatch) && stackLines[index].startsWith(INLINE_SCRIPT_STRING) && stackLines[index].match(toRegExp(stackMatch))) {
            return true;
          }
          if (isInjectedScript(stackMatch) && stackLines[index].startsWith(INJECTED_SCRIPT_STRING) && stackLines[index].match(toRegExp(stackMatch))) {
            return true;
          }
        }
      }
      return false;
    };

    /**
     * Finds shadow-dom host (elements with shadowRoot property) in DOM of rootElement.
     *
     * @param rootElement shadow dom root
     * @returns shadow-dom hosts
     */
    var findHostElements = function findHostElements(rootElement) {
      var hosts = [];
      if (rootElement) {
        // Element.querySelectorAll() returns list of elements
        // which are defined in DOM of Element.
        // Meanwhile, inner DOM of the element with shadowRoot property
        // is absolutely another DOM and which can not be reached by querySelectorAll('*')
        var domElems = rootElement.querySelectorAll('*');
        domElems.forEach(function (el) {
          if (el.shadowRoot) {
            hosts.push(el);
          }
        });
      }
      return hosts;
    };

    /**
     * A collection of nodes.
     *
     * @external NodeList
     * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/NodeList NodeList}
     */

    /**
     * Pierces open shadow-dom in order to find:
     * - elements by 'selector' matching
     * - inner shadow-dom hosts
     *
     * @param selector DOM elements selector
     * @param hostElements shadow-dom hosts
     * @returns object with found elements and shadow-dom hosts
     */
    var pierceShadowDom = function pierceShadowDom(selector, hostElements) {
      var targets = [];
      var innerHostsAcc = [];

      // it's possible to get a few hostElements found by baseSelector on the page
      hostElements.forEach(function (host) {
        // check presence of selector element inside base element if it's not in shadow-dom
        var simpleElems = host.querySelectorAll(selector);
        targets = targets.concat([].slice.call(simpleElems));
        var shadowRootElem = host.shadowRoot;
        var shadowChildren = shadowRootElem.querySelectorAll(selector);
        targets = targets.concat([].slice.call(shadowChildren));

        // find inner shadow-dom hosts inside processing shadow-dom
        innerHostsAcc.push(findHostElements(shadowRootElem));
      });

      // if there were more than one host element,
      // innerHostsAcc is an array of arrays and should be flatten
      var innerHosts = flatten(innerHostsAcc);
      return {
        targets,
        innerHosts
      };
    };
    /**
     * Retrieves the first Element that matches the selector, with the ability
     * to select elements from inside open shadow-dom.
     *
     * @param selector A DOMString containing one or more selectors to match.
     * Supports `>>>` combinator to split the selector into shadow host selector,
     * to find the element containing shadow root, and shadow root selector, to find the element inside shadow dom.
     * @param context The Element or Document which is the context for the query.
     * @param context.querySelector The querySelector function to use.
     * @returns The first Element within the document that matches the specified selector, or null if no matches are found.
     */
    function queryShadowSelector(selector) {
      var context = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : document.documentElement;
      var SHADOW_COMBINATOR = ' >>> ';
      var pos = selector.indexOf(SHADOW_COMBINATOR);
      if (pos === -1) {
        return context.querySelector(selector);
      }
      var shadowHostSelector = selector.slice(0, pos).trim();
      var elem = context.querySelector(shadowHostSelector);
      if (!elem || !elem.shadowRoot) {
        return null;
      }
      var shadowRootSelector = selector.slice(pos + SHADOW_COMBINATOR.length).trim();
      return queryShadowSelector(shadowRootSelector, elem.shadowRoot);
    }

    /**
     * Checks whether the passed arg is proper callback
     *
     * @param callback arbitrary callback
     * @returns if callback is valid
     */
    var isValidCallback = function isValidCallback(callback) {
      return callback instanceof Function
      // passing string as 'code' arg is not recommended
      // but it is possible and not restricted
      // https://developer.mozilla.org/en-US/docs/Web/API/setTimeout#parameters
      || typeof callback === 'string';
    };

    /**
     * Parses delay argument of setTimeout / setInterval methods into
     * rounded down number for number/string values or passes on for other types.
     * Needed for prevent-setTimeout and prevent-setInterval
     *
     * @param delay native method delay arg
     * @returns number as parsed delay or any input type if `delay` is not parsable
     */
    var parseRawDelay = function parseRawDelay(delay) {
      var parsedDelay = Math.floor(parseInt(delay, 10));
      return typeof parsedDelay === 'number' && !nativeIsNaN(parsedDelay) ? parsedDelay : delay;
    };
    /**
     * Checks whether 'callback' and 'delay' are matching
     * by given parameters 'matchCallback' and 'matchDelay'.
     * Used for prevent-setTimeout and prevent-setInterval.
     *
     * @param preventData set of data to determine if scriptlet should match
     * @param preventData.callback method's callback arg
     * @param preventData.delay method's delay arg
     * @param preventData.matchCallback scriptlets's callback arg
     * @param preventData.matchDelay scriptlets's delay arg
     * @returns if scriptlet should match
     */
    var isPreventionNeeded = function isPreventionNeeded(_ref) {
      var callback = _ref.callback,
        delay = _ref.delay,
        matchCallback = _ref.matchCallback,
        matchDelay = _ref.matchDelay;
      // if callback is has not valid type
      // scriptlet can not prevent it
      // so no need for more checking and do not call hit() later
      if (!isValidCallback(callback)) {
        return false;
      }
      if (!isValidMatchStr(matchCallback) || matchDelay && !isValidMatchNumber(matchDelay)) {
        return false;
      }
      var _parseMatchArg = parseMatchArg(matchCallback),
        isInvertedMatch = _parseMatchArg.isInvertedMatch,
        matchRegexp = _parseMatchArg.matchRegexp;
      var _parseDelayArg = parseDelayArg(matchDelay),
        isInvertedDelayMatch = _parseDelayArg.isInvertedDelayMatch,
        delayMatch = _parseDelayArg.delayMatch;

      // Parse delay for decimal, string and non-number values
      // https://github.com/AdguardTeam/Scriptlets/issues/247
      var parsedDelay = parseRawDelay(delay);
      var shouldPrevent = false;
      // https://github.com/AdguardTeam/Scriptlets/issues/105
      var callbackStr = String(callback);
      if (delayMatch === null) {
        shouldPrevent = matchRegexp.test(callbackStr) !== isInvertedMatch;
      } else if (!matchCallback) {
        shouldPrevent = parsedDelay === delayMatch !== isInvertedDelayMatch;
      } else {
        shouldPrevent = matchRegexp.test(callbackStr) !== isInvertedMatch && parsedDelay === delayMatch !== isInvertedDelayMatch;
      }
      return shouldPrevent;
    };

    var handleOldReplacement = function handleOldReplacement(replacement) {
      var result;
      // defaults to return noopFunc instead of window.open
      if (!replacement) {
        result = noopFunc;
      } else if (replacement === 'trueFunc') {
        result = trueFunc;
      } else if (replacement.includes('=')) {
        // We should return noopFunc instead of window.open
        // but with some property if website checks it (examples 5, 6)
        // https://github.com/AdguardTeam/Scriptlets/issues/71
        var isProp = replacement.startsWith('{') && replacement.endsWith('}');
        if (isProp) {
          var propertyPart = replacement.slice(1, -1);
          var propertyName = substringBefore(propertyPart, '=');
          var propertyValue = substringAfter(propertyPart, '=');
          if (propertyValue === 'noopFunc') {
            result = {};
            result[propertyName] = noopFunc;
          }
        }
      }
      return result;
    };
    /**
     * Creates a decoy HTML element with a specified URL and delay before removal
     *
     * @param args an object with `replacement`, `url`, and `delay` properties
     * @returns the decoy element that was created and added to the document body
     */
    var createDecoy = function createDecoy(args) {
      var UrlPropNameOf = /*#__PURE__*/function (UrlPropNameOf) {
        UrlPropNameOf["Object"] = "data";
        UrlPropNameOf["Iframe"] = "src";
        return UrlPropNameOf;
      }({});
      var replacement = args.replacement,
        url = args.url,
        delay = args.delay;
      var tag;
      if (replacement === 'obj') {
        tag = "object";
      } else {
        tag = "iframe";
      }
      var decoy = document.createElement(tag);
      if (decoy instanceof HTMLObjectElement) {
        decoy[UrlPropNameOf.Object] = url;
      } else if (decoy instanceof HTMLIFrameElement) {
        decoy[UrlPropNameOf.Iframe] = url;
      }
      decoy.style.setProperty('height', '1px', 'important');
      decoy.style.setProperty('position', 'fixed', 'important');
      decoy.style.setProperty('top', '-1px', 'important');
      decoy.style.setProperty('width', '1px', 'important');
      document.body.appendChild(decoy);
      setTimeout(function () {
        return decoy.remove();
      }, delay * 1000);
      return decoy;
    };
    var getPreventGetter = function getPreventGetter(nativeGetter) {
      var preventGetter = function preventGetter(target, prop) {
        if (prop && prop === 'closed') {
          return false;
        }
        if (typeof nativeGetter === 'function') {
          return noopFunc;
        }
        return prop && target[prop];
      };
      return preventGetter;
    };

    /**
     * Check if the property exists in the base object (recursively).
     * Similar to getPropertyInChain but upgraded for json-prune:
     * handle wildcard properties and does not define nonexistent base property as 'undefined'
     *
     * @param base object that owns chain
     * @param chain chain of owner properties
     * @param lookThrough should the method look through it's props in order to find wildcard
     * @param output result acc
     * @returns list of ChainInfo objects
     */
    function getWildcardPropertyInChain(base, chain) {
      var lookThrough = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
      var output = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : [];
      var pos = chain.indexOf('.');
      if (pos === -1) {
        // for paths like 'a.b.*' every final nested prop should be processed
        if (chain === '*' || chain === '[]') {
          // eslint-disable-next-line no-restricted-syntax
          for (var key in base) {
            // to process each key in base except inherited ones
            if (Object.prototype.hasOwnProperty.call(base, key)) {
              output.push({
                base,
                prop: key
              });
            }
          }
        } else {
          output.push({
            base,
            prop: chain
          });
        }
        return output;
      }
      var prop = chain.slice(0, pos);
      var shouldLookThrough = prop === '[]' && Array.isArray(base) || prop === '*' && base instanceof Object;
      if (shouldLookThrough) {
        var nextProp = chain.slice(pos + 1);
        var baseKeys = Object.keys(base);

        // if there is a wildcard prop in input chain (e.g. 'ad.*.src' for 'ad.0.src ad.1.src'),
        // each one of base keys should be considered as a potential chain prop in final path
        baseKeys.forEach(function (key) {
          var item = base[key];
          getWildcardPropertyInChain(item, nextProp, lookThrough, output);
        });
      }

      // If base is an Array check elements in array
      // https://github.com/AdguardTeam/Scriptlets/issues/345
      if (Array.isArray(base)) {
        base.forEach(function (key) {
          var nextBase = key;
          if (nextBase !== undefined) {
            getWildcardPropertyInChain(nextBase, chain, lookThrough, output);
          }
        });
      }
      var nextBase = base[prop];
      chain = chain.slice(pos + 1);
      if (nextBase !== undefined) {
        getWildcardPropertyInChain(nextBase, chain, lookThrough, output);
      }
      return output;
    }

    /**
     * Returns the native `RegExp.prototype.test` method if it exists.
     *
     * @returns The native `RegExp.prototype.test` method.
     * @throws If `RegExp.prototype.test` is not a function.
     */
    var getNativeRegexpTest = function getNativeRegexpTest() {
      var descriptor = Object.getOwnPropertyDescriptor(RegExp.prototype, 'test');
      var nativeRegexTest = descriptor === null || descriptor === void 0 ? void 0 : descriptor.value;
      if (descriptor && typeof descriptor.value === 'function') {
        return nativeRegexTest;
      }
      throw new Error('RegExp.prototype.test is not a function');
    };

    /**
     * Retrieves the values of the global RegExp.$1, …, RegExp.$9 properties
     * The problem is that RegExp.$1 is modified by scriptlet and according
     * to https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/n#description
     * the values of $1, …, $9 update whenever a RegExp instance makes a successful match
     * so we need to save these values and then change them back.
     * Related issue - https://github.com/AdguardTeam/Scriptlets/issues/384
     *
     * @returns {Array} An array containing the values of the RegExp.$1, …, RegExp.$9 properties.
     */
    var backupRegExpValues = function backupRegExpValues() {
      try {
        var arrayOfRegexpValues = [];
        for (var index = 1; index < 10; index += 1) {
          var value = "$".concat(index);
          if (!RegExp[value]) {
            break;
          }
          arrayOfRegexpValues.push(RegExp[value]);
        }
        return arrayOfRegexpValues;
      } catch (error) {
        return [];
      }
    };

    /**
     * Sets previous values of the RegExp.$1, …, RegExp.$9 properties.
     *
     * @param {Array} array
     * @returns {void}
     */
    var restoreRegExpValues = function restoreRegExpValues(array) {
      if (!array.length) {
        return;
      }
      try {
        var stringPattern = '';
        if (array.length === 1) {
          stringPattern = "(".concat(array[0], ")");
        } else {
          // Create a string pattern with a capturing group from passed array,
          // e.g. ['foo', 'bar', 'baz'] will create '(foo),(bar),(baz)' string
          stringPattern = array.reduce(function (accumulator, currentValue, currentIndex) {
            if (currentIndex === 1) {
              return "(".concat(accumulator, "),(").concat(currentValue, ")");
            }
            return "".concat(accumulator, ",(").concat(currentValue, ")");
          });
        }
        var regExpGroup = new RegExp(stringPattern);
        array.toString().replace(regExpGroup, '');
      } catch (error) {
        var message = "Failed to restore RegExp values: ".concat(error);
        // eslint-disable-next-line no-console
        console.log(message);
      }
    };

    /**
     * Checks if the stackTrace contains stackRegexp
     * https://github.com/AdguardTeam/Scriptlets/issues/82
     *
     * @param stackMatch - input stack value to match
     * @param stackTrace - script error stack trace
     * @returns if the stackTrace contains stackRegexp
     */
    var matchStackTrace = function matchStackTrace(stackMatch, stackTrace) {
      if (!stackMatch || stackMatch === '') {
        return true;
      }
      var regExpValues = backupRegExpValues();
      if (shouldAbortInlineOrInjectedScript(stackMatch, stackTrace)) {
        if (regExpValues.length && regExpValues[0] !== RegExp.$1) {
          restoreRegExpValues(regExpValues);
        }
        return true;
      }
      var stackRegexp = toRegExp(stackMatch);
      var refinedStackTrace = stackTrace.split('\n').slice(2) // get rid of our own functions in the stack trace
      .map(function (line) {
        return line.trim();
      }) // trim the lines
      .join('\n');
      if (regExpValues.length && regExpValues[0] !== RegExp.$1) {
        restoreRegExpValues(regExpValues);
      }
      return getNativeRegexpTest().call(stackRegexp, refinedStackTrace);
    };

    /**
     * Checks if prunning is required
     *
     * @param source required, scriptlet properties
     * @param root object which should be pruned or logged
     * @param prunePaths array with string of space-separated property chains to remove
     * @param requiredPaths array with string of space-separated propertiy chains
     * @param stack string which should be matched by stack trace
     * @param nativeObjects reference to native objects, required for a trusted-prune-inbound-object to fix infinite loop
     * which must be all present for the pruning to occur
     * @returns true if prunning is required
     */
    function isPruningNeeded(source, root, prunePaths, requiredPaths, stack, nativeObjects) {
      if (!root) {
        return false;
      }
      var nativeStringify = nativeObjects.nativeStringify;
      var shouldProcess;

      // Only log hostname and matched JSON payload if only second argument is present
      if (prunePaths.length === 0 && requiredPaths.length > 0) {
        var rootString = nativeStringify(root);
        var matchRegex = toRegExp(requiredPaths.join(''));
        var shouldLog = matchRegex.test(rootString);
        if (shouldLog) {
          logMessage(source, "".concat(window.location.hostname, "\n").concat(nativeStringify(root, null, 2), "\nStack trace:\n").concat(new Error().stack), true);
          if (root && typeof root === 'object') {
            logMessage(source, root, true, false);
          }
          shouldProcess = false;
          return shouldProcess;
        }
      }
      if (stack && !matchStackTrace(stack, new Error().stack || '')) {
        shouldProcess = false;
        return shouldProcess;
      }
      var wildcardSymbols = ['.*.', '*.', '.*', '.[].', '[].', '.[]'];
      var _loop = function _loop() {
        var requiredPath = requiredPaths[i];
        var lastNestedPropName = requiredPath.split('.').pop();
        var hasWildcard = wildcardSymbols.some(function (symbol) {
          return requiredPath.includes(symbol);
        });

        // if the path has wildcard, getPropertyInChain should 'look through' chain props
        var details = getWildcardPropertyInChain(root, requiredPath, hasWildcard);

        // Do not prune if details is an empty Array
        // https://github.com/AdguardTeam/Scriptlets/issues/345
        if (!details.length) {
          shouldProcess = false;
          return {
            v: shouldProcess
          };
        }

        // start value of 'shouldProcess' due to checking below
        shouldProcess = !hasWildcard;
        for (var j = 0; j < details.length; j += 1) {
          var hasRequiredProp = typeof lastNestedPropName === 'string' && details[j].base[lastNestedPropName] !== undefined;
          if (hasWildcard) {
            // if there is a wildcard,
            // at least one (||) of props chain should be present in object
            shouldProcess = hasRequiredProp || shouldProcess;
          } else {
            // otherwise each one (&&) of them should be there
            shouldProcess = hasRequiredProp && shouldProcess;
          }
        }
      };
      for (var i = 0; i < requiredPaths.length; i += 1) {
        var _ret = _loop();
        if (typeof _ret === "object") return _ret.v;
      }
      return shouldProcess;
    }

    /**
     * Prunes properties of 'root' object
     *
     * @param source required, scriptlet properties
     * @param root object which should be pruned or logged
     * @param prunePaths array with string of space-separated properties to remove
     * @param requiredPaths array with string of space-separated properties
     * @param stack string which should be matched by stack trace
     * @param nativeObjects reference to native objects, required for a trusted-prune-inbound-object to fix infinite loop
     * which must be all present for the pruning to occur
     * @returns pruned root
     */
    var jsonPruner = function jsonPruner(source, root, prunePaths, requiredPaths, stack, nativeObjects) {
      var nativeStringify = nativeObjects.nativeStringify;
      if (prunePaths.length === 0 && requiredPaths.length === 0) {
        logMessage(source, "".concat(window.location.hostname, "\n").concat(nativeStringify(root, null, 2), "\nStack trace:\n").concat(new Error().stack), true);
        if (root && typeof root === 'object') {
          logMessage(source, root, true, false);
        }
        return root;
      }
      try {
        if (isPruningNeeded(source, root, prunePaths, requiredPaths, stack, nativeObjects) === false) {
          return root;
        }

        // if pruning is needed, we check every input pathToRemove
        // and delete it if root has it
        prunePaths.forEach(function (path) {
          var ownerObjArr = getWildcardPropertyInChain(root, path, true);
          ownerObjArr.forEach(function (ownerObj) {
            if (ownerObj !== undefined && ownerObj.base) {
              delete ownerObj.base[ownerObj.prop];
              hit(source);
            }
          });
        });
      } catch (e) {
        logMessage(source, e);
      }
      return root;
    };

    /**
     * Checks if props is a string and returns array of properties
     * or empty array if props is not a string
     *
     * @param props string of space-separated properties or undefined
     * @returns array of properties or empty array if props is not a string
     */
    var getPrunePath = function getPrunePath(props) {
      var validPropsString = typeof props === 'string' && props !== undefined && props !== '';
      return validPropsString ? props.split(/ +/) : [];
    };

    /**
     * Modifies original response with the given replacement data.
     *
     * @param origResponse Original response.
     * @param replacement Replacement data for response with possible keys:
     * - `body`: optional, string, default to '{}';
     * - `type`: optional, string, original response type is used if not specified.
     *
     * @returns Modified response.
     */
    var modifyResponse = function modifyResponse(origResponse) {
      var _origResponse$headers;
      var replacement = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {
        body: '{}'
      };
      var headers = {};
      origResponse === null || origResponse === void 0 ? void 0 : (_origResponse$headers = origResponse.headers) === null || _origResponse$headers === void 0 ? void 0 : _origResponse$headers.forEach(function (value, key) {
        headers[key] = value;
      });
      var modifiedResponse = new Response(replacement.body, {
        status: origResponse.status,
        statusText: origResponse.statusText,
        headers
      });

      // Mock response url and type to avoid adblocker detection
      // https://github.com/AdguardTeam/Scriptlets/issues/216
      Object.defineProperties(modifiedResponse, {
        url: {
          value: origResponse.url
        },
        type: {
          value: replacement.type || origResponse.type
        }
      });
      return modifiedResponse;
    };

    /**
     * Create new Response object using original response' properties
     * and given text as body content
     *
     * @param response original response to copy properties from
     * @param textContent text to set as body content
     */
    var forgeResponse = function forgeResponse(response, textContent) {
      var bodyUsed = response.bodyUsed,
        headers = response.headers,
        ok = response.ok,
        redirected = response.redirected,
        status = response.status,
        statusText = response.statusText,
        type = response.type,
        url = response.url;
      var forgedResponse = new Response(textContent, {
        status,
        statusText,
        headers
      });

      // Manually set properties which can't be set by Response constructor
      Object.defineProperties(forgedResponse, {
        url: {
          value: url
        },
        type: {
          value: type
        },
        ok: {
          value: ok
        },
        bodyUsed: {
          value: bodyUsed
        },
        redirected: {
          value: redirected
        }
      });
      return forgedResponse;
    };

    /**
     * Aggregates fetch and XMLHttpRequest.open arguments
     * to operate on arbitrary request data objects
     */

    /**
     * Object which is populated with request data from scriptlet arguments
     */

    /**
     * Derivative of ParsedMatchProps with its values being
     * converted to RegExp
     */

    /**
     * Fetch and xhr.open options that are valid props
     * to match for (trusted-)prevent-(fetch|xhr) scriptlets
     *
     * This type is being derived from getRequestProps return type
     * as enums would be lost at build time disregarding 'const'
     */

    /**
     * Returns array of request props that are supported by fetch/xhr scriptlets.
     * Includes common 'url' and 'method' props and all other fetch-specific props
     *
     * @returns list of request props
     */
    var getRequestProps = function getRequestProps() {
      return ['url', 'method', 'headers', 'body', 'credentials', 'cache', 'redirect', 'referrer', 'referrerPolicy', 'integrity', 'keepalive', 'signal', 'mode'];
    };

    /**
     * Collects Request options to object
     *
     * @param request Request instance to collect properties from
     * @returns data object
     */
    var getRequestData = function getRequestData(request) {
      var requestInitOptions = getRequestProps();
      var entries = requestInitOptions.map(function (key) {
        // if request has no such option, value will be undefined
        var value = request[key];
        return [key, value];
      });
      return Object.fromEntries(entries);
    };

    /**
     * Collects fetch args to object
     *
     * @param args fetch args
     * @returns data object
     */
    var getFetchData = function getFetchData(args, nativeRequestClone) {
      var fetchPropsObj = {};
      var resource = args[0];
      var fetchUrl;
      var fetchInit;
      if (resource instanceof Request) {
        // Get real properties in case if data URL was used
        // and properties were set by Object.defineProperty
        // https://github.com/AdguardTeam/Scriptlets/issues/367
        var realData = nativeRequestClone.call(resource);
        // if Request passed to fetch, it will be in array
        var requestData = getRequestData(realData);
        fetchUrl = requestData.url;
        fetchInit = requestData;
      } else {
        fetchUrl = resource; // eslint-disable-line prefer-destructuring
        fetchInit = args[1]; // eslint-disable-line prefer-destructuring
      }

      fetchPropsObj.url = fetchUrl;
      if (fetchInit instanceof Object) {
        var props = Object.keys(fetchInit);
        props.forEach(function (prop) {
          fetchPropsObj[prop] = fetchInit[prop];
        });
      }
      return fetchPropsObj;
    };

    /**
     * Collect xhr.open arguments to object
     *
     * @param method request method
     * @param url request url
     * @param async request async prop
     * @param user request user prop
     * @param password request password prop
     * @returns aggregated request data
     */
    var getXhrData = function getXhrData(method, url, async, user, password) {
      return {
        method,
        url,
        async,
        user,
        password
      };
    };

    /**
     * Parse propsToMatch input string into object;
     * used for prevent-fetch and prevent-xhr
     *
     * @param propsToMatchStr string of space-separated request properties to match
     * @returns object where 'key' is prop name and 'value' is prop value
     */
    var parseMatchProps = function parseMatchProps(propsToMatchStr) {
      var PROPS_DIVIDER = ' ';
      var PAIRS_MARKER = ':';
      var isRequestProp = function isRequestProp(prop) {
        return getRequestProps().includes(prop);
      };
      var propsObj = {};
      var props = propsToMatchStr.split(PROPS_DIVIDER);
      props.forEach(function (prop) {
        var dividerInd = prop.indexOf(PAIRS_MARKER);
        var key = prop.slice(0, dividerInd);
        if (isRequestProp(key)) {
          var value = prop.slice(dividerInd + 1);
          propsObj[key] = value;
        } else {
          // Escape multiple colons in prop
          // i.e regex value and/or url with protocol specified, with or without 'url:' match prop
          // https://github.com/AdguardTeam/Scriptlets/issues/216#issuecomment-1178591463
          propsObj.url = prop;
        }
      });
      return propsObj;
    };

    /**
     * Validates parsed data values
     *
     * @param data request data
     * @returns if data is valid
     */
    var isValidParsedData = function isValidParsedData(data) {
      return Object.values(data).every(function (value) {
        return isValidStrPattern(value);
      });
    };

    /**
     * Converts valid parsed data to data obj for further matching
     *
     * @param data parsed request data
     * @returns data obj ready for matching
     */
    var getMatchPropsData = function getMatchPropsData(data) {
      var matchData = {};
      // Assertion is required, as Object.keys always returns string[]
      var dataKeys = Object.keys(data);
      dataKeys.forEach(function (key) {
        matchData[key] = toRegExp(data[key]);
      });
      return matchData;
    };

    /**
     * Sets item to a specified storage, if storage isn't full.
     *
     * @param source scriptlet's configuration
     * @param storage storage instance to set item into
     * @param key storage key
     * @param  value staroge value
     */
    var setStorageItem = function setStorageItem(source, storage, key, value) {
      // setItem() may throw an exception if the storage is full.
      try {
        storage.setItem(key, value);
      } catch (e) {
        var message = "Unable to set sessionStorage item due to: ".concat(e.message);
        logMessage(source, message);
      }
    };

    /**
     * Removes the key/value pair with the given `key` from the `storage`.
     * If unable to remove, logs the reason to console in debug mode.
     *
     * @param source scriptlet's configuration
     * @param storage storage instance from which item has to be removed
     * @param key storage key
     */
    var removeStorageItem = function removeStorageItem(source, storage, key) {
      try {
        if (key.startsWith('/') && (key.endsWith('/') || key.endsWith('/i')) && isValidStrPattern(key)) {
          var regExpKey = toRegExp(key);
          var storageKeys = Object.keys(storage);
          storageKeys.forEach(function (storageKey) {
            if (regExpKey.test(storageKey)) {
              storage.removeItem(storageKey);
            }
          });
        } else {
          storage.removeItem(key);
        }
      } catch (e) {
        var message = "Unable to remove storage item due to: ".concat(e.message);
        logMessage(source, message);
      }
    };

    /**
     * Gets supported storage item value
     *
     * @param  value input item value
     * @returns valid item value if ok OR null if not
     */
    var getLimitedStorageItemValue = function getLimitedStorageItemValue(value) {
      if (typeof value !== 'string') {
        throw new Error('Invalid value');
      }
      var allowedStorageValues = new Set(['undefined', 'false', 'true', 'null', '', 'yes', 'no', 'on', 'off', 'accept', 'accepted', 'reject', 'rejected', 'allowed', 'denied']);
      var validValue;
      if (allowedStorageValues.has(value.toLowerCase())) {
        validValue = value;
      } else if (value === 'emptyArr') {
        validValue = '[]';
      } else if (value === 'emptyObj') {
        validValue = '{}';
      } else if (/^\d+$/.test(value)) {
        validValue = parseFloat(value);
        if (nativeIsNaN(validValue)) {
          throw new Error('Invalid value');
        }
        if (Math.abs(validValue) > 32767) {
          throw new Error('Invalid value');
        }
      } else if (value === '$remove$') {
        validValue = '$remove$';
      } else {
        throw new Error('Invalid value');
      }
      return validValue;
    };

    /**
     * Generate random seven symbols id
     *
     * @returns randomized id
     */
    function randomId() {
      return Math.random().toString(36).slice(2, 9);
    }

    /**
     * Generates function which silents global errors on page generated by scriptlet
     * If error doesn't belong to our error we transfer it to the native onError handler
     *
     * @param rid - unique identifier of scriptlet
     * @returns window.onerror handler
     */
    function createOnErrorHandler(rid) {
      // eslint-disable-next-line consistent-return
      var nativeOnError = window.onerror;
      return function onError(error) {
        if (typeof error === 'string' && error.includes(rid)) {
          return true;
        }
        if (nativeOnError instanceof Function) {
          for (var _len = arguments.length, args = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
            args[_key - 1] = arguments[_key];
          }
          return nativeOnError.apply(window, [error, ...args]);
        }
        return false;
      };
    }

    /**
     * Silently aborts currently running script
     * TODO use this for other abort scriptlets
     *
     * @returns abort function
     */
    function getAbortFunc() {
      var rid = randomId();
      var isErrorHandlerSet = false;
      return function abort() {
        if (!isErrorHandlerSet) {
          window.onerror = createOnErrorHandler(rid);
          isErrorHandlerSet = true;
        }
        throw new ReferenceError(rid);
      };
    }

    /**
     * Prevents infinite loops when trapping props that could be used by scriptlet's own helpers
     * Example: window.RegExp, that is used by matchStackTrace > toRegExp
     *
     * https://github.com/AdguardTeam/Scriptlets/issues/251
     * https://github.com/AdguardTeam/Scriptlets/issues/226
     * https://github.com/AdguardTeam/Scriptlets/issues/232
     *
     * @returns descriptor addon
     */
    function getDescriptorAddon() {
      return {
        isAbortingSuspended: false,
        isolateCallback(cb) {
          this.isAbortingSuspended = true;
          // try...catch is required in case there are more than one inline scripts
          // which should be aborted,
          // so after the first successful abortion, `cb(...args);` will throw error,
          // and we should not stop on that and continue to abort other scripts
          try {
            for (var _len = arguments.length, args = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
              args[_key - 1] = arguments[_key];
            }
            var result = cb(...args);
            this.isAbortingSuspended = false;
            return result;
          } catch (_unused) {
            var rid = randomId();
            this.isAbortingSuspended = false;
            // It's necessary to throw error
            // otherwise script will be not aborted
            throw new ReferenceError(rid);
          }
        }
      };
    }

    /**
     * Converts error object to error with message. This method might be helpful to handle thrown errors.
     *
     * @param error Error object.
     *
     * @returns Message of the error.
     */
    var getErrorMessage = function getErrorMessage(error) {
      /**
       * Checks if error has message.
       *
       * @param e Error object.
       *
       * @returns True if error has message, false otherwise.
       */
      var isErrorWithMessage = function isErrorWithMessage(e) {
        return typeof e === 'object' && e !== null && 'message' in e && typeof e.message === 'string';
      };
      if (isErrorWithMessage(error)) {
        return error.message;
      }
      try {
        return new Error(JSON.stringify(error)).message;
      } catch (_unused) {
        // fallback in case there's an error stringifying the error
        // like with circular references for example.
        return new Error(String(error)).message;
      }
    };

    /**
     * Check if the property exists in the base object (recursively)
     *
     * If property doesn't exist in base object,
     * defines this property as 'undefined'
     * and returns base, property name and remaining part of property chain
     *
     * @param base object that owns chain
     * @param chain chain of owner properties
     * @returns chain info object
     */
    function getPropertyInChain(base, chain) {
      var pos = chain.indexOf('.');
      if (pos === -1) {
        return {
          base,
          prop: chain
        };
      }
      var prop = chain.slice(0, pos);

      // https://github.com/AdguardTeam/Scriptlets/issues/128
      if (base === null) {
        // if base is null, return 'null' as base.
        // it's needed for triggering the reason logging while debugging
        return {
          base,
          prop,
          chain
        };
      }
      var nextBase = base[prop];
      chain = chain.slice(pos + 1);
      if ((base instanceof Object || typeof base === 'object') && isEmptyObject(base)) {
        // for empty objects in chain
        return {
          base,
          prop,
          chain
        };
      }
      if (nextBase === null) {
        return {
          base,
          prop,
          chain
        };
      }
      if (nextBase !== undefined) {
        return getPropertyInChain(nextBase, chain);
      }
      Object.defineProperty(base, prop, {
        configurable: true
      });
      return {
        base,
        prop,
        chain
      };
    }

    /**
     * Checks if given propsToMatch string matches with given request data
     * This is used by prevent-xhr, prevent-fetch, trusted-replace-xhr-response
     * and  trusted-replace-fetch-response scriptlets
     *
     * @param source scriptlet properties
     * @param propsToMatch string of space-separated request properties to match
     * @param requestData object with standard properties of fetch/xhr like url, method etc
     * @returns if request properties match
     */
    var matchRequestProps = function matchRequestProps(source, propsToMatch, requestData) {
      if (propsToMatch === '' || propsToMatch === '*') {
        return true;
      }
      var isMatched;
      var parsedData = parseMatchProps(propsToMatch);
      if (!isValidParsedData(parsedData)) {
        logMessage(source, "Invalid parameter: ".concat(propsToMatch));
        isMatched = false;
      } else {
        var matchData = getMatchPropsData(parsedData);
        var matchKeys = Object.keys(matchData);
        // prevent only if all props match
        isMatched = matchKeys.every(function (matchKey) {
          var matchValue = matchData[matchKey];
          var dataValue = requestData[matchKey];
          return Object.prototype.hasOwnProperty.call(requestData, matchKey) && typeof dataValue === 'string' && (matchValue === null || matchValue === void 0 ? void 0 : matchValue.test(dataValue));
        });
      }
      return isMatched;
    };

    /**
     * Returns a wrapper, passing the call to 'method' at maximum once per 'delay' milliseconds.
     * Those calls that fall into the "cooldown" period, are ignored
     *
     * @param cb callback
     * @param delay - milliseconds
     * @returns throttled callback
     */
    var throttle = function throttle(cb, delay) {
      var wait = false;
      var savedArgs;
      var wrapper = function wrapper() {
        for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
          args[_key] = arguments[_key];
        }
        if (wait) {
          savedArgs = args;
          return;
        }
        cb(...args);
        wait = true;
        setTimeout(function () {
          wait = false;
          if (savedArgs) {
            // "savedArgs" might contains few arguments, so it's necessary to use spread operator
            // https://github.com/AdguardTeam/Scriptlets/issues/284#issuecomment-1419464354
            wrapper(...savedArgs);
            savedArgs = null;
          }
        }, delay);
      };
      return wrapper;
    };

    /**
     * DOM tree changes observer.
     *
     * @param callback function to call on each mutation
     * @param observeAttrs if observer should observe attributes changes
     * @param attrsToObserve list of attributes to observe
     */
    var observeDOMChanges = function observeDOMChanges(callback) {
      var observeAttrs = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
      var attrsToObserve = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : [];
      /**
       * 'delay' in milliseconds for 'throttle' method
       */
      var THROTTLE_DELAY_MS = 20;
      /**
       * Used for remove-class
       */
      // eslint-disable-next-line @typescript-eslint/no-use-before-define
      var observer = new MutationObserver(throttle(callbackWrapper, THROTTLE_DELAY_MS));
      var connect = function connect() {
        if (attrsToObserve.length > 0) {
          observer.observe(document.documentElement, {
            childList: true,
            subtree: true,
            attributes: observeAttrs,
            attributeFilter: attrsToObserve
          });
        } else {
          observer.observe(document.documentElement, {
            childList: true,
            subtree: true,
            attributes: observeAttrs
          });
        }
      };
      var disconnect = function disconnect() {
        observer.disconnect();
      };

      /**
       * Callback wrapper to prevent loops
       * when callback tinkers with attributes
       */
      function callbackWrapper() {
        disconnect();
        callback();
        connect();
      }
      connect();
    };

    /**
     * Returns the list of added nodes from the list of mutations
     *
     * @param mutations list of mutations
     * @returns list of added nodes
     */
    var getAddedNodes = function getAddedNodes(mutations) {
      var nodes = [];
      for (var i = 0; i < mutations.length; i += 1) {
        var addedNodes = mutations[i].addedNodes;
        for (var j = 0; j < addedNodes.length; j += 1) {
          nodes.push(addedNodes[j]);
        }
      }
      return nodes;
    };

    /**
     * Creates and runs a MutationObserver on the document element with optional
     * throttling and disconnect timeout.
     *
     * @param {Function} callback MutationObserver callback
     * @param {object} options MutationObserver options
     * @param timeout Disconnect timeout in ms
     */
    var observeDocumentWithTimeout = function observeDocumentWithTimeout(callback) {
      var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {
        subtree: true,
        childList: true
      };
      var timeout = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 10000;
      var documentObserver = new MutationObserver(function (mutations, observer) {
        observer.disconnect();
        callback(mutations, observer);
        observer.observe(document.documentElement, options);
      });
      documentObserver.observe(document.documentElement, options);
      if (typeof timeout === 'number') {
        setTimeout(function () {
          return documentObserver.disconnect();
        }, timeout);
      }
    };

    /**
     * Behaviour flags string parser
     *
     * @param flags required, 'applying' argument string
     * @returns object with parsed flags
     */
    var parseFlags = function parseFlags(flags) {
      // !IMPORTANT: Do not move constants outside of this function
      var FLAGS_DIVIDER = ' ';
      var ASAP_FLAG = 'asap';
      var COMPLETE_FLAG = 'complete';
      var STAY_FLAG = 'stay';
      var VALID_FLAGS = new Set([ASAP_FLAG, COMPLETE_FLAG, STAY_FLAG]);
      var passedFlags = new Set(flags.trim().split(FLAGS_DIVIDER).filter(function (flag) {
        return VALID_FLAGS.has(flag);
      }));
      return {
        ASAP: ASAP_FLAG,
        COMPLETE: COMPLETE_FLAG,
        STAY: STAY_FLAG,
        hasFlag: function hasFlag(flag) {
          return passedFlags.has(flag);
        }
      };
    };

    /**
     * Modifies passed keyword value according to its purpose.
     * Returns initial value if it's not a keyword.
     *
     * Supported keywords:
     *   - '$now$' - returns current time in ms, e.g 1667915146503
     *   - '$currentDate$' - returns current date e.g 'Tue Nov 08 2022 13:53:19 GMT+0300'
     *
     * @param rawValue keyword
     * @returns parsed value
     */
    var parseKeywordValue = function parseKeywordValue(rawValue) {
      // !IMPORTANT: Do not move constants outside of this function
      var NOW_VALUE_KEYWORD = '$now$';
      var CURRENT_DATE_KEYWORD = '$currentDate$';
      var CURRENT_ISO_DATE_KEYWORD = '$currentISODate$';
      var parsedValue = rawValue;
      if (rawValue === NOW_VALUE_KEYWORD) {
        // Set to current time in ms, e.g 1667915146503
        parsedValue = Date.now().toString();
      } else if (rawValue === CURRENT_DATE_KEYWORD) {
        // Set to current date e.g 'Tue Nov 08 2022 13:53:19 GMT+0300'
        parsedValue = Date();
      } else if (rawValue === CURRENT_ISO_DATE_KEYWORD) {
        // Set to current date e.g '2022-11-08T13:53:19.650Z'
        parsedValue = new Date().toISOString();
      }
      return parsedValue;
    };

    /**
     * Makes arbitrary operations on shadow root element,
     * to be passed as callback to hijackAttachShadow
     */

    /**
     * Overrides attachShadow method of Element API on a given context
     * to pass retrieved shadowRoots to callback
     *
     * @param context e.g global window object or contentWindow of an iframe
     * @param hostSelector selector to determine if callback should be called on current shadow subtree
     * @param callback callback to call on shadow root
     */
    var hijackAttachShadow = function hijackAttachShadow(context, hostSelector, callback) {
      var handlerWrapper = function handlerWrapper(target, thisArg, args) {
        var shadowRoot = Reflect.apply(target, thisArg, args);
        if (thisArg && thisArg.matches(hostSelector || '*')) {
          callback(shadowRoot);
        }
        return shadowRoot;
      };
      var attachShadowHandler = {
        apply: handlerWrapper
      };
      context.Element.prototype.attachShadow = new Proxy(context.Element.prototype.attachShadow, attachShadowHandler);
    };

    /**
     * Grabs existing nodes and passes them to a given handler.
     *
     * @param selector CSS selector to find nodes by
     * @param handler handler to pass nodes to
     */
    var handleExistingNodes = function handleExistingNodes(selector, handler) {
      var nodeList = document.querySelectorAll(selector);
      var nodes = nodeListToArray(nodeList);
      handler(nodes);
    };

    /**
     * Extracts added nodes from mutations and passes them to a given handler.
     *
     * @param mutations mutations to find eligible nodes in
     * @param handler handler to pass eligible nodes to
     */
    var handleMutations = function handleMutations(mutations, handler) {
      var addedNodes = getAddedNodes(mutations);
      handler(addedNodes);
    };

    /**
     * Checks if given node's text content should be replaced
     *
     * @param node  node to check
     * @param nodeNameMatch regexp or string to match node name
     * @param textContentMatch regexp or string to match node's text content
     * @returns true if node's text content should be replaced
     */
    var isTargetNode = function isTargetNode(node, nodeNameMatch, textContentMatch) {
      var nodeName = node.nodeName,
        textContent = node.textContent;
      var nodeNameLowerCase = nodeName.toLowerCase();
      return textContent !== null && textContent !== '' && (nodeNameMatch instanceof RegExp ? nodeNameMatch.test(nodeNameLowerCase) : nodeNameMatch === nodeNameLowerCase) && (textContentMatch instanceof RegExp ? textContentMatch.test(textContent) : textContent.includes(textContentMatch));
    };

    /**
     * Replaces given node's text content with a given replacement.
     *
     * @param source source of the scriptlet
     * @param node node to replace text content in
     * @param pattern pattern to match text content
     * @param replacement replacement for matched text content
     */
    var replaceNodeText = function replaceNodeText(source, node, pattern, replacement) {
      var textContent = node.textContent;
      if (textContent) {
        node.textContent = textContent.replace(pattern, replacement);
        hit(source);
      }
    };

    /**
     * Modifies arguments for trusted-replace-node-text and remove-node-text scriptlets
     *
     * @param nodeName string or stringified regexp to match node name
     * @param textMatch string or stringified regexp to match node's text content
     * @param pattern string or stringified regexp to match replace pattern
     * @returns derivative params
     */
    var parseNodeTextParams = function parseNodeTextParams(nodeName, textMatch) {
      var pattern = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : null;
      var REGEXP_START_MARKER = '/';
      var isStringNameMatch = !(nodeName.startsWith(REGEXP_START_MARKER) && nodeName.endsWith(REGEXP_START_MARKER));
      var selector = isStringNameMatch ? nodeName : '*';
      var nodeNameMatch = isStringNameMatch ? nodeName : toRegExp(nodeName);
      var textContentMatch = !textMatch.startsWith(REGEXP_START_MARKER) ? textMatch : toRegExp(textMatch);
      var patternMatch;
      if (pattern) {
        patternMatch = !pattern.startsWith(REGEXP_START_MARKER) ? pattern : toRegExp(pattern);
      }
      return {
        selector,
        nodeNameMatch,
        textContentMatch,
        patternMatch
      };
    };

    /**
     * Matches an arbitrary value by matcher value.
     * Supported value types and corresponding matchers:
     * - string – exact string, part of the string or regexp pattern. Empty string `""` to match an empty string.
     * - number, boolean, null, undefined – exact value,
     * - object – partial of the object with the values as mentioned above,
     *         i.e by another object, that includes property names and values to be matched,
     * - array – partial of the array with the values to be included in the incoming array,
     *         without considering the order of values,
     * - function – not supported.
     *
     * @param value arbitrary value
     * @param matcher value matcher
     * @returns true, if incoming value matches the matcher value
     */
    function isValueMatched(value, matcher) {
      if (typeof value === 'function') {
        return false;
      }
      if (nativeIsNaN(value)) {
        return nativeIsNaN(matcher);
      }
      if (value === null || typeof value === 'undefined' || typeof value === 'number' || typeof value === 'boolean') {
        return value === matcher;
      }
      if (typeof value === 'string') {
        if (typeof matcher === 'string' || matcher instanceof RegExp) {
          // eslint-disable-next-line @typescript-eslint/no-use-before-define
          return isStringMatched(value, matcher);
        }
        return false;
      }
      if (Array.isArray(value) && Array.isArray(matcher)) {
        // eslint-disable-next-line @typescript-eslint/no-use-before-define
        return isArrayMatched(value, matcher);
      }
      if (isArbitraryObject(value) && isArbitraryObject(matcher)) {
        // eslint-disable-next-line @typescript-eslint/no-use-before-define
        return isObjectMatched(value, matcher);
      }
      return false;
    }

    /**
     * Matches string by substring or regexp pattern.
     *
     * @param str incoming string
     * @param matcher string matcher
     * @returns true, if incoming string includes the matcher or matches the regexp pattern
     */
    function isStringMatched(str, matcher) {
      if (typeof matcher === 'string') {
        if (matcher === '') {
          return str === matcher;
        }
        return str.includes(matcher);
      }
      if (matcher instanceof RegExp) {
        return matcher.test(str);
      }
      return false;
    }

    /**
     * Matches incoming object by partial of the object, i.e by another object,
     * that includes property names and values to be matched.
     *
     * @param obj incoming object
     * @param matcher object matcher
     * @returns true, if incoming object includes all properties and corresponding values from the matcher
     */
    function isObjectMatched(obj, matcher) {
      var matcherKeys = Object.keys(matcher);
      for (var i = 0; i < matcherKeys.length; i += 1) {
        var key = matcherKeys[i];
        var value = obj[key];
        if (!isValueMatched(value, matcher[key])) {
          return false;
        }
        continue;
      }
      return true;
    }

    /**
     * Matches array by partial of the array with the values to be included in the incoming array,
     * without considering the order of values.
     *
     * @param array incoming array
     * @param matcher array matcher
     * @returns true, if incoming array includes all values from the matcher
     */
    function isArrayMatched(array, matcher) {
      if (array.length === 0) {
        return matcher.length === 0;
      }

      // Empty array matcher matches empty array, which is not the case after the previous check
      if (matcher.length === 0) {
        return false;
      }
      var _loop = function _loop() {
        var matcherValue = matcher[i];
        var isMatching = array.some(function (arrItem) {
          return isValueMatched(arrItem, matcherValue);
        });
        if (!isMatching) {
          return {
            v: false
          };
        }
        return "continue";
      };
      for (var i = 0; i < matcher.length; i += 1) {
        var _ret = _loop();
        if (_ret === "continue") continue;
        if (typeof _ret === "object") return _ret.v;
      }
      return true;
    }

    /* eslint-disable max-len */
    /**
     * @trustedScriptlet trusted-click-element
     *
     * @description
     * Clicks selected elements in a strict sequence, ordered by selectors passed,
     * and waiting for them to render in the DOM first.
     * Deactivates after all elements have been clicked or by 10s timeout.
     *
     * ### Syntax
     *
     * ```text
     * example.com#%#//scriptlet('trusted-click-element', selectors[, extraMatch[, delay[, reload]]])
     * ```
     * <!-- markdownlint-disable-next-line line-length -->
     * - `selectors` — required, string with query selectors delimited by comma. The scriptlet supports `>>>` combinator to select elements inside open shadow DOM. For usage, see example below.
     * - `extraMatch` — optional, extra condition to check on a page;
     *    allows to match `cookie`, `localStorage` and specified text;
     * can be set as `name:key[=value]` where `value` is optional.
     * If `cookie`/`localStorage` starts with `!` then the element will only be clicked
     * if specified `cookie`/`localStorage` item does not exist.
     * Multiple conditions are allowed inside one `extraMatch` but they should be delimited by comma
     * and each of them should match the syntax. Possible `names`:
     *     - `cookie` — test string or regex against cookies on a page
     *     - `localStorage` — check if localStorage item is present
     *     - `containsText` — check if clicked element contains specified text
     * - `delay` — optional, time in ms to delay scriptlet execution, defaults to instant execution.
     *             Must be a number less than 10000 ms (10s)
     * - `reload` — optional, string with reloadAfterClick marker and optional value. Possible values:
     *     - `reloadAfterClick` - reloads the page after all elements have been clicked,
     *        with default delay — 500ms
     *     - colon-separated pair `reloadAfterClick:value` where
     *         - `value` — time delay in milliseconds before reloading the page, after all elements
     *            have been clicked. Must be a number less than 10000 ms (10s)
     *
     * <!-- markdownlint-disable line-length -->
     *
     * ### Examples
     *
     * 1. Click single element by selector
     *
     *     ```adblock
     *     example.com#%#//scriptlet('trusted-click-element', 'button[name="agree"]')
     *     ```
     *
     * 1. Delay click execution by 500ms
     *
     *     ```adblock
     *     example.com#%#//scriptlet('trusted-click-element', 'button[name="agree"]', '', '500')
     *     ```
     *
     * 1. Click multiple elements by selector with a delay
     *
     *     <!-- markdownlint-disable line-length -->
     *
     *     ```adblock
     *     example.com#%#//scriptlet('trusted-click-element', 'button[name="agree"], button[name="check"], input[type="submit"][value="akkoord"]', '', '500')
     *     ```
     *
     * 1. Match cookies by keys using regex and string
     *
     *     ```adblock
     *     example.com#%#//scriptlet('trusted-click-element', 'button[name="agree"]', 'cookie:userConsentCommunity, cookie:/cmpconsent|cmp/')
     *     ```
     *
     * 1. Match by cookie key=value pairs using regex and string
     *
     *     ```adblock
     *     example.com#%#//scriptlet('trusted-click-element', 'button[name="agree"]', 'cookie:userConsentCommunity=true, cookie:/cmpconsent|cmp/=/[a-z]{1,5}/')
     *     ```
     *
     * 1. Match by localStorage item 'promo' key
     *
     *     ```adblock
     *     example.com#%#//scriptlet('trusted-click-element', 'button[name="agree"]', 'localStorage:promo')
     *     ```
     *
     * 1. Click multiple elements with delay and matching by both cookie string and localStorage item
     *
     *     ```adblock
     *     example.com#%#//scriptlet('trusted-click-element', 'button[name="agree"], input[type="submit"][value="akkoord"]', 'cookie:cmpconsent, localStorage:promo', '250')
     *     ```
     *
     * 1. Click element only if clicked element contains text `Accept cookie`
     *
     *     ```adblock
     *     example.com#%#//scriptlet('trusted-click-element', 'button', 'containsText:Accept cookie')
     *     ```
     *
     * 1. Click element only if cookie with name `cmpconsent` does not exist
     *
     *     ```adblock
     *     example.com#%#//scriptlet('trusted-click-element', 'button[name="agree"]', '!cookie:cmpconsent')
     *     ```
     *
     * 1. Click element only if specified cookie string and localStorage item does not exist
     *
     *     ```adblock
     *     example.com#%#//scriptlet('trusted-click-element', 'button[name="agree"]', '!cookie:consent, !localStorage:promo')
     *     ```
     *
     * 1. Click element inside open shadow DOM, which could be selected by `div > button`, but is inside shadow host element with host element selected by `article .container`
     *
     *    ```adblock
     *    example.com#%#//scriptlet('trusted-click-element', 'article .container > div#host >>> div > button')
     *    ```
     *
     * 1. Click elements after 1000ms delay and reload page after all elements have been clicked with 200ms delay
     *
     *    ```adblock
     *    example.com#%#//scriptlet('trusted-click-element', 'button[name="agree"], button[name="check"], input[type="submit"][value="akkoord"]', '', '1000', 'reloadAfterClick:200')
     *    ```
     *
     * <!-- markdownlint-enable line-length -->
     *
     * @added v1.7.3.
     */
    /* eslint-enable max-len */
    function trustedClickElement$1(source, selectors) {
      var extraMatch = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : '';
      var delay = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : NaN;
      var reload = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : '';
      if (!selectors) {
        return;
      }
      var SHADOW_COMBINATOR = ' >>> ';
      var OBSERVER_TIMEOUT_MS = 10000;
      var THROTTLE_DELAY_MS = 20;
      var STATIC_CLICK_DELAY_MS = 150;
      var STATIC_RELOAD_DELAY_MS = 500;
      var COOKIE_MATCH_MARKER = 'cookie:';
      var LOCAL_STORAGE_MATCH_MARKER = 'localStorage:';
      var TEXT_MATCH_MARKER = 'containsText:';
      var RELOAD_ON_FINAL_CLICK_MARKER = 'reloadAfterClick';
      var SELECTORS_DELIMITER = ',';
      var COOKIE_STRING_DELIMITER = ';';
      var COLON = ':';
      // Regex to split match pairs by commas, avoiding the ones included in regexes
      var EXTRA_MATCH_DELIMITER = /(,\s*){1}(?=!?cookie:|!?localStorage:|containsText:)/;
      var sleep = function sleep(delayMs) {
        return new Promise(function (resolve) {
          return setTimeout(resolve, delayMs);
        });
      };

      // If shadow combinator is present in selector, then override attachShadow and set mode to 'open'
      if (selectors.includes(SHADOW_COMBINATOR)) {
        var attachShadowWrapper = function attachShadowWrapper(target, thisArg, argumentsList) {
          var _argumentsList$;
          var mode = (_argumentsList$ = argumentsList[0]) === null || _argumentsList$ === void 0 ? void 0 : _argumentsList$.mode;
          if (mode === 'closed') {
            argumentsList[0].mode = 'open';
          }
          return Reflect.apply(target, thisArg, argumentsList);
        };
        var attachShadowHandler = {
          apply: attachShadowWrapper
        };
        window.Element.prototype.attachShadow = new Proxy(window.Element.prototype.attachShadow, attachShadowHandler);
      }
      var parsedDelay;
      if (delay) {
        parsedDelay = parseInt(String(delay), 10);
        var isValidDelay = !Number.isNaN(parsedDelay) || parsedDelay < OBSERVER_TIMEOUT_MS;
        if (!isValidDelay) {
          // eslint-disable-next-line max-len
          var message = "Passed delay '".concat(delay, "' is invalid or bigger than ").concat(OBSERVER_TIMEOUT_MS, " ms");
          logMessage(source, message);
          return;
        }
      }
      var canClick = !parsedDelay;
      var cookieMatches = [];
      var localStorageMatches = [];
      var textMatches = '';
      var isInvertedMatchCookie = false;
      var isInvertedMatchLocalStorage = false;
      if (extraMatch) {
        // Get all match marker:value pairs from argument
        var parsedExtraMatch = extraMatch.split(EXTRA_MATCH_DELIMITER).map(function (matchStr) {
          return matchStr.trim();
        });

        // Filter match pairs by marker
        parsedExtraMatch.forEach(function (matchStr) {
          if (matchStr.includes(COOKIE_MATCH_MARKER)) {
            var _parseMatchArg = parseMatchArg(matchStr),
              isInvertedMatch = _parseMatchArg.isInvertedMatch,
              matchValue = _parseMatchArg.matchValue;
            isInvertedMatchCookie = isInvertedMatch;
            var cookieMatch = matchValue.replace(COOKIE_MATCH_MARKER, '');
            cookieMatches.push(cookieMatch);
          }
          if (matchStr.includes(LOCAL_STORAGE_MATCH_MARKER)) {
            var _parseMatchArg2 = parseMatchArg(matchStr),
              _isInvertedMatch = _parseMatchArg2.isInvertedMatch,
              _matchValue = _parseMatchArg2.matchValue;
            isInvertedMatchLocalStorage = _isInvertedMatch;
            var localStorageMatch = _matchValue.replace(LOCAL_STORAGE_MATCH_MARKER, '');
            localStorageMatches.push(localStorageMatch);
          }
          if (matchStr.includes(TEXT_MATCH_MARKER)) {
            var _parseMatchArg3 = parseMatchArg(matchStr),
              _matchValue2 = _parseMatchArg3.matchValue;
            var textMatch = _matchValue2.replace(TEXT_MATCH_MARKER, '');
            textMatches = textMatch;
          }
        });
      }
      if (cookieMatches.length > 0) {
        var parsedCookieMatches = parseCookieString(cookieMatches.join(COOKIE_STRING_DELIMITER));
        var parsedCookies = parseCookieString(document.cookie);
        var cookieKeys = Object.keys(parsedCookies);
        if (cookieKeys.length === 0) {
          return;
        }
        var cookiesMatched = Object.keys(parsedCookieMatches).every(function (key) {
          // Avoid getting /.?/ result from toRegExp on undefined
          // as cookie may be set without value,
          // on which cookie parsing will return cookieKey:undefined pair
          var valueMatch = parsedCookieMatches[key] ? toRegExp(parsedCookieMatches[key]) : null;
          var keyMatch = toRegExp(key);
          return cookieKeys.some(function (cookieKey) {
            var keysMatched = keyMatch.test(cookieKey);
            if (!keysMatched) {
              return false;
            }

            // Key matching is enough if cookie value match is not specified
            if (!valueMatch) {
              return true;
            }
            var parsedCookieValue = parsedCookies[cookieKey];
            if (!parsedCookieValue) {
              return false;
            }
            return valueMatch.test(parsedCookieValue);
          });
        });
        var shouldRun = cookiesMatched !== isInvertedMatchCookie;
        if (!shouldRun) {
          return;
        }
      }
      if (localStorageMatches.length > 0) {
        var localStorageMatched = localStorageMatches.every(function (str) {
          var itemValue = window.localStorage.getItem(str);
          return itemValue || itemValue === '';
        });
        var _shouldRun = localStorageMatched !== isInvertedMatchLocalStorage;
        if (!_shouldRun) {
          return;
        }
      }
      var textMatchRegexp = textMatches ? toRegExp(textMatches) : null;

      /**
       * Checks if an element contains the specified text.
       *
       * @param element - The element to check.
       * @param matchRegexp - The text to match.
       * @returns True if the element contains the specified text, otherwise false.
       */
      var doesElementContainText = function doesElementContainText(element, matchRegexp) {
        var textContent = element.textContent;
        if (!textContent) {
          return false;
        }
        return matchRegexp.test(textContent);
      };

      /**
       * Create selectors array and swap selectors to null on finding it's element
       *
       * Selectors / nulls should not be (re)moved from array to:
       * - keep track of selectors order
       * - always know on what index corresponding element should be put
       * - prevent selectors from being queried multiple times
       */
      var selectorsSequence = selectors.split(SELECTORS_DELIMITER).map(function (selector) {
        return selector.trim();
      });
      var createElementObj = function createElementObj(element) {
        return {
          element: element || null,
          clicked: false
        };
      };
      var elementsSequence = Array(selectorsSequence.length).fill(createElementObj(null));

      // Flag indicating if the reload is set
      var shouldReloadAfterClick = false;
      // Value used for reload timing
      var reloadDelayMs = STATIC_RELOAD_DELAY_MS;
      if (reload) {
        // split reload option by colon
        var _reload$split = reload.split(COLON),
          _reload$split2 = _slicedToArray$1(_reload$split, 2),
          reloadMarker = _reload$split2[0],
          reloadValue = _reload$split2[1];
        if (reloadMarker !== RELOAD_ON_FINAL_CLICK_MARKER) {
          logMessage(source, "Passed reload option '".concat(reload, "' is invalid"));
          return;
        }

        // if reload value is set, will be used as a delay
        // if reload value is not set, default value will be used
        if (reloadValue) {
          var passedReload = Number(reloadValue);

          // check if passed reload value is a number
          if (Number.isNaN(passedReload)) {
            logMessage(source, "Passed reload delay value '".concat(passedReload, "' is invalid"));
            return;
          }

          // check if passed reload value is less than 10s
          if (passedReload > OBSERVER_TIMEOUT_MS) {
            // eslint-disable-next-line max-len
            logMessage(source, "Passed reload delay value '".concat(passedReload, "' is bigger than maximum ").concat(OBSERVER_TIMEOUT_MS, " ms"));
            return;
          }
          reloadDelayMs = passedReload;
        }
        shouldReloadAfterClick = true;
      }

      /**
       * Go through elementsSequence from left to right, clicking on found elements
       *
       * Element should not be clicked if it is already clicked,
       * or a previous element is not found or clicked yet
       */
      var canReload = true;
      var clickElementsBySequence = async function clickElementsBySequence() {
        for (var i = 0; i < elementsSequence.length; i += 1) {
          var elementObj = elementsSequence[i];

          // Add a delay between clicks to every element except the first one
          // https://github.com/AdguardTeam/Scriptlets/issues/284
          if (i >= 1) {
            await sleep(STATIC_CLICK_DELAY_MS);
          }

          // Stop clicking if that pos element is not found yet
          if (!elementObj.element) {
            break;
          }

          // Skip already clicked elements
          if (!elementObj.clicked) {
            if (textMatchRegexp && !doesElementContainText(elementObj.element, textMatchRegexp)) {
              continue;
            }
            elementObj.element.click();
            elementObj.clicked = true;
          }
        }
        var allElementsClicked = elementsSequence.every(function (elementObj) {
          return elementObj.clicked === true;
        });
        if (allElementsClicked) {
          if (shouldReloadAfterClick && canReload) {
            canReload = false;
            setTimeout(function () {
              window.location.reload();
            }, reloadDelayMs);
          }
          hit(source);
        }
      };
      var handleElement = function handleElement(element, i) {
        var elementObj = createElementObj(element);
        elementsSequence[i] = elementObj;
        if (canClick) {
          clickElementsBySequence();
        }
      };

      /**
       * Processes a sequence of selectors, handling elements found in DOM (and shadow DOM),
       * and updates the sequence.
       *
       * @returns {string[]} The updated selectors sequence, with fulfilled selectors set to null.
       */
      var fulfillAndHandleSelectors = function fulfillAndHandleSelectors() {
        var fulfilledSelectors = [];
        selectorsSequence.forEach(function (selector, i) {
          if (!selector) {
            return;
          }
          var element = queryShadowSelector(selector);
          if (!element) {
            return;
          }
          handleElement(element, i);
          fulfilledSelectors.push(selector);
        });

        // selectorsSequence should be modified after the loop to not break loop indexation
        selectorsSequence = selectorsSequence.map(function (selector) {
          return selector && fulfilledSelectors.includes(selector) ? null : selector;
        });
        return selectorsSequence;
      };

      /**
       * Queries all selectors from queue on each mutation
       *
       * We start looking for elements before possible delay is over, to avoid cases
       * when delay is getting off after the last mutation took place.
       *
       */
      var findElements = function findElements(mutations, observer) {
        // TODO: try to make the function cleaner — avoid usage of selectorsSequence from the outer scope
        selectorsSequence = fulfillAndHandleSelectors();

        // Disconnect observer after finding all elements
        var allSelectorsFulfilled = selectorsSequence.every(function (selector) {
          return selector === null;
        });
        if (allSelectorsFulfilled) {
          observer.disconnect();
        }
      };

      /**
       * Initializes a `MutationObserver` to watch for changes in the DOM.
       * The observer is set up to monitor changes in attributes, child nodes, and subtree.
       * A timeout is set to disconnect the observer if no elements are found within the specified time.
       */
      var initializeMutationObserver = function initializeMutationObserver() {
        var observer = new MutationObserver(throttle(findElements, THROTTLE_DELAY_MS));
        observer.observe(document.documentElement, {
          attributes: true,
          childList: true,
          subtree: true
        });

        // Set timeout to disconnect observer if elements are not found within the specified time
        setTimeout(function () {
          return observer.disconnect();
        }, OBSERVER_TIMEOUT_MS);
      };

      /**
       * Checks if elements are already present in the DOM.
       * If elements are found, they are clicked.
       * If elements are not found, the observer is initialized.
       */
      var checkInitialElements = function checkInitialElements() {
        var foundElements = selectorsSequence.every(function (selector) {
          if (!selector) {
            return false;
          }
          var element = queryShadowSelector(selector);
          return !!element;
        });
        if (foundElements) {
          // Click previously collected elements
          fulfillAndHandleSelectors();
        } else {
          // Initialize MutationObserver if elements were not found initially
          initializeMutationObserver();
        }
      };

      // Run the initial check
      checkInitialElements();

      // If there's a delay before clicking elements, use a timeout
      if (parsedDelay) {
        setTimeout(function () {
          // Click previously collected elements
          clickElementsBySequence();
          canClick = true;
        }, parsedDelay);
      }
    }
    trustedClickElement$1.names = ['trusted-click-element'
    // trusted scriptlets support no aliases
    ];

    trustedClickElement$1.injections = [hit, toRegExp, parseCookieString, throttle, logMessage, parseMatchArg, queryShadowSelector];

    /* eslint-disable max-len */
    /**
     * @scriptlet abort-on-property-read
     *
     * @description
     * Aborts a script when it attempts to **read** the specified property.
     *
     * Related UBO scriptlet:
     * https://github.com/gorhill/uBlock/wiki/Resources-Library#abort-on-property-readjs-
     *
     * Related ABP source:
     * https://gitlab.com/eyeo/snippets/-/blob/main/source/behavioral/abort-on-property-read.js
     *
     * ### Syntax
     *
     * ```text
     * example.org#%#//scriptlet('abort-on-property-read', property)
     * ```
     *
     * - `property` — required, path to a property (joined with `.` if needed). The property must be attached to `window`
     *
     * ### Examples
     *
     * ```adblock
     * ! Aborts script when it tries to access `window.alert`
     * example.org#%#//scriptlet('abort-on-property-read', 'alert')
     *
     * ! Aborts script when it tries to access `navigator.language`
     * example.org#%#//scriptlet('abort-on-property-read', 'navigator.language')
     * ```
     *
     * @added v1.0.4.
     */
    /* eslint-enable max-len */
    function abortOnPropertyRead$1(source, property) {
      if (!property) {
        return;
      }
      var rid = randomId();
      var abort = function abort() {
        hit(source);
        throw new ReferenceError(rid);
      };
      var setChainPropAccess = function setChainPropAccess(owner, property) {
        var chainInfo = getPropertyInChain(owner, property);
        var base = chainInfo.base;
        var prop = chainInfo.prop,
          chain = chainInfo.chain;
        if (chain) {
          var setter = function setter(a) {
            base = a;
            if (a instanceof Object) {
              setChainPropAccess(a, chain);
            }
          };
          Object.defineProperty(owner, prop, {
            get: function get() {
              return base;
            },
            set: setter
          });
          return;
        }
        setPropertyAccess(base, prop, {
          get: abort,
          set: function set() {}
        });
      };
      setChainPropAccess(window, property);
      window.onerror = createOnErrorHandler(rid).bind();
    }
    abortOnPropertyRead$1.names = ['abort-on-property-read',
    // aliases are needed for matching the related scriptlet converted into our syntax
    'abort-on-property-read.js', 'ubo-abort-on-property-read.js', 'aopr.js', 'ubo-aopr.js', 'ubo-abort-on-property-read', 'ubo-aopr', 'abp-abort-on-property-read'];
    abortOnPropertyRead$1.injections = [randomId, setPropertyAccess, getPropertyInChain, createOnErrorHandler, hit, isEmptyObject];

    /* eslint-disable max-len */
    /**
     * @scriptlet abort-on-property-write
     *
     * @description
     * Aborts a script when it attempts to **write** the specified property.
     *
     * Related UBO scriptlet:
     * https://github.com/gorhill/uBlock/wiki/Resources-Library#abort-on-property-writejs-
     *
     * Related ABP source:
     * https://gitlab.com/eyeo/snippets/-/blob/main/source/behavioral/abort-on-property-write.js
     *
     * ### Syntax
     *
     * ```text
     * example.org#%#//scriptlet('abort-on-property-write', property)
     * ```
     *
     * - `property` — required, path to a property (joined with `.` if needed).
     *   The property must be attached to `window`
     *
     * ### Examples
     *
     * ```adblock
     * ! Aborts script when it tries to set `window.adblock` value
     * example.org#%#//scriptlet('abort-on-property-write', 'adblock')
     * ```
     *
     * @added v1.0.4.
     */
    /* eslint-enable max-len */
    function abortOnPropertyWrite$1(source, property) {
      if (!property) {
        return;
      }
      var rid = randomId();
      var abort = function abort() {
        hit(source);
        throw new ReferenceError(rid);
      };
      var setChainPropAccess = function setChainPropAccess(owner, property) {
        var chainInfo = getPropertyInChain(owner, property);
        var base = chainInfo.base;
        var prop = chainInfo.prop,
          chain = chainInfo.chain;
        if (chain) {
          var setter = function setter(a) {
            base = a;
            if (a instanceof Object) {
              setChainPropAccess(a, chain);
            }
          };
          Object.defineProperty(owner, prop, {
            get: function get() {
              return base;
            },
            set: setter
          });
          return;
        }
        setPropertyAccess(base, prop, {
          set: abort
        });
      };
      setChainPropAccess(window, property);
      window.onerror = createOnErrorHandler(rid).bind();
    }
    abortOnPropertyWrite$1.names = ['abort-on-property-write',
    // aliases are needed for matching the related scriptlet converted into our syntax
    'abort-on-property-write.js', 'ubo-abort-on-property-write.js', 'aopw.js', 'ubo-aopw.js', 'ubo-abort-on-property-write', 'ubo-aopw', 'abp-abort-on-property-write'];
    abortOnPropertyWrite$1.injections = [randomId, setPropertyAccess, getPropertyInChain, createOnErrorHandler, hit, isEmptyObject];

    /* eslint-disable max-len */
    /**
     * @scriptlet prevent-setTimeout
     *
     * @description
     * Prevents a `setTimeout` call if:
     *
     * 1. The text of the callback is matching the specified `matchCallback` string/regexp which does not start with `!`;
     *    otherwise mismatched calls should be defused.
     * 1. The delay is matching the specified `matchDelay`; otherwise mismatched calls should be defused.
     *
     * Related UBO scriptlet:
     * https://github.com/gorhill/uBlock/wiki/Resources-Library#no-settimeout-ifjs-
     *
     * ### Syntax
     *
     * ```text
     * example.org#%#//scriptlet('prevent-setTimeout'[, matchCallback[, matchDelay]])
     * ```
     *
     * > Call with no arguments will log all setTimeout calls (`log-setTimeout` superseding),
     * > it may be useful for debugging but it is not allowed for prod versions of filter lists.
     *
     * - `matchCallback` — optional, string or regular expression;
     *   invalid regular expression will be skipped and all callbacks will be matched.
     *   If starts with `!`, scriptlet will not match the stringified callback but all other will be defused.
     *   If do not start with `!`, the stringified callback will be matched.
     *   If not set, prevents all `setTimeout` calls due to specified `matchDelay`.
     * - `matchDelay` — optional, must be an integer.
     *   If starts with `!`, scriptlet will not match the delay but all other will be defused.
     *   If do not start with `!`, the delay passed to the `setTimeout` call will be matched.
     *   Decimal delay values will be rounded down, e.g `10.95` will be matched by `matchDelay` with value `10`.
     *
     * > If `prevent-setTimeout` log looks like `setTimeout(undefined, 1000)`,
     * > it means that no callback was passed to setTimeout() and that's not scriptlet issue
     * > and obviously it can not be matched by `matchCallback`.
     *
     * ### Examples
     *
     * 1. Prevents `setTimeout` calls if the callback matches `/\.test/` regardless of the delay
     *
     *     ```adblock
     *     example.org#%#//scriptlet('prevent-setTimeout', '/\.test/')
     *     ```
     *
     *     For instance, the following call will be prevented:
     *
     *     ```javascript
     *     setTimeout(function () {
     *         window.test = "value";
     *     }, 100);
     *     ```
     *
     * 1. Prevents `setTimeout` calls if the callback does not contain `value`
     *
     *     ```adblock
     *     example.org#%#//scriptlet('prevent-setTimeout', '!value')
     *     ```
     *
     *     For instance, only the first of the following calls will be prevented:
     *
     *     ```javascript
     *     setTimeout(function () {
     *         window.test = "test -- prevented";
     *     }, 300);
     *     setTimeout(function () {
     *         window.test = "value -- executed";
     *     }, 400);
     *     setTimeout(function () {
     *         window.value = "test -- executed";
     *     }, 500);
     *     ```
     *
     * 1. Prevents `setTimeout` calls if the callback contains `value` and the delay is not set to `300`
     *
     *     ```adblock
     *     example.org#%#//scriptlet('prevent-setTimeout', 'value', '!300')
     *     ```
     *
     *     For instance, only the first of the following calls will not be prevented:
     *
     *     ```javascript
     *     setTimeout(function () {
     *         window.test = "value 1 -- executed";
     *     }, 300);
     *     setTimeout(function () {
     *         window.test = "value 2 -- prevented";
     *     }, 400);
     *     setTimeout(function () {
     *         window.test = "value 3 -- prevented";
     *     }, 500);
     *     ```
     *
     * 1. Prevents `setTimeout` calls if the callback does not contain `value` and the delay is not set to `300`
     *
     *     ```adblock
     *     example.org#%#//scriptlet('prevent-setTimeout', '!value', '!300')
     *     ```
     *
     *     For instance, only the second of the following calls will be prevented:
     *
     *     ```javascript
     *     setTimeout(function () {
     *         window.test = "test -- executed";
     *     }, 300);
     *     setTimeout(function () {
     *         window.test = "test -- prevented";
     *     }, 400);
     *     setTimeout(function () {
     *         window.test = "value -- executed";
     *     }, 400);
     *     setTimeout(function () {
     *         window.value = "test -- executed";
     *     }, 500);
     *     ```
     *
     * 1. Prevents `setTimeout` calls if the callback contains `value` and delay is a decimal
     *
     *     ```adblock
     *     example.org#%#//scriptlet('prevent-setTimeout', 'value', '300')
     *     ```
     *
     *     For instance, the following calls will be prevented:
     *
     *     ```javascript
     *     setTimeout(function () {
     *         window.test = "value";
     *     }, 300);
     *     setTimeout(function () {
     *         window.test = "value";
     *     }, 300 + Math.random());
     *     ```
     *
     * @added v1.0.4.
     */
    /* eslint-enable max-len */
    function preventSetTimeout$1(source, matchCallback, matchDelay) {
      // logs setTimeouts to console if no arguments have been specified
      var shouldLog = typeof matchCallback === 'undefined' && typeof matchDelay === 'undefined';
      var handlerWrapper = function handlerWrapper(target, thisArg, args) {
        var callback = args[0];
        var delay = args[1];
        var shouldPrevent = false;
        if (shouldLog) {
          hit(source);
          // https://github.com/AdguardTeam/Scriptlets/issues/105
          logMessage(source, "setTimeout(".concat(String(callback), ", ").concat(delay, ")"), true);
        } else {
          shouldPrevent = isPreventionNeeded({
            callback,
            delay,
            matchCallback,
            matchDelay
          });
        }
        if (shouldPrevent) {
          hit(source);
          args[0] = noopFunc;
        }
        return target.apply(thisArg, args);
      };
      var setTimeoutHandler = {
        apply: handlerWrapper
      };
      window.setTimeout = new Proxy(window.setTimeout, setTimeoutHandler);
    }
    preventSetTimeout$1.names = ['prevent-setTimeout',
    // aliases are needed for matching the related scriptlet converted into our syntax
    'no-setTimeout-if.js',
    // new implementation of setTimeout-defuser.js
    'ubo-no-setTimeout-if.js', 'nostif.js',
    // new short name of no-setTimeout-if
    'ubo-nostif.js', 'ubo-no-setTimeout-if', 'ubo-nostif',
    // old scriptlet names which should be supported as well.
    // should be removed eventually.
    // do not remove until other filter lists maintainers use them
    'setTimeout-defuser.js', 'ubo-setTimeout-defuser.js', 'ubo-setTimeout-defuser', 'std.js', 'ubo-std.js', 'ubo-std'];
    preventSetTimeout$1.injections = [hit, noopFunc, isPreventionNeeded, logMessage,
    // following helpers should be injected as helpers above use them
    parseMatchArg, parseDelayArg, toRegExp, nativeIsNaN, isValidCallback, isValidMatchStr, escapeRegExp, isValidStrPattern, nativeIsFinite, isValidMatchNumber, parseRawDelay];

    /* eslint-disable max-len */
    /**
     * @scriptlet prevent-setInterval
     *
     * @description
     * Prevents a `setInterval` call if:
     *
     * 1. The text of the callback is matching the specified `matchCallback` string/regexp which does not start with `!`;
     *    otherwise mismatched calls should be defused.
     * 1. The delay is matching the specified `matchDelay`; otherwise mismatched calls should be defused.
     *
     * Related UBO scriptlet:
     * https://github.com/gorhill/uBlock/wiki/Resources-Library#no-setinterval-ifjs-
     *
     * ### Syntax
     *
     * ```text
     * example.org#%#//scriptlet('prevent-setInterval'[, matchCallback[, matchDelay]])
     * ```
     *
     * > Call with no arguments will log all setInterval calls (`log-setInterval` superseding),
     * > it may be useful for debugging but it is not allowed for prod versions of filter lists.
     *
     * - `matchCallback` — optional, string or regular expression;
     *   invalid regular expression will be skipped and all callbacks will be matched.
     *   If starts with `!`, scriptlet will not match the stringified callback but all other will be defused.
     *   If do not start with `!`, the stringified callback will be matched.
     *   If not set, prevents all `setInterval` calls due to specified `matchDelay`.
     * - `matchDelay` — optional, must be an integer.
     *   If starts with `!`, scriptlet will not match the delay but all other will be defused.
     *   If do not start with `!`, the delay passed to the `setInterval` call will be matched.
     *   Decimal delay values will be rounded down, e.g `10.95` will be matched by `matchDelay` with value `10`.
     *
     * > If `prevent-setInterval` log looks like `setInterval(undefined, 1000)`,
     * > it means that no callback was passed to setInterval() and that's not scriptlet issue
     * > and obviously it can not be matched by `matchCallback`.
     *
     * ### Examples
     *
     * 1. Prevents `setInterval` calls if the callback matches `/\.test/` regardless of the delay
     *
     *     ```adblock
     *     example.org#%#//scriptlet('prevent-setInterval', '/\.test/')
     *     ```
     *
     *     For instance, the following call will be prevented:
     *
     *     ```javascript
     *     setInterval(function () {
     *         window.test = "value";
     *     }, 100);
     *     ```
     *
     * 1. Prevents `setInterval` calls if the callback does not contain `value`
     *
     *     ```adblock
     *     example.org#%#//scriptlet('prevent-setInterval', '!value')
     *     ```
     *
     *     For instance, only the first of the following calls will be prevented:
     *
     *     ```javascript
     *     setInterval(function () {
     *         window.test = "test -- prevented";
     *     }, 300);
     *     setInterval(function () {
     *         window.test = "value -- executed";
     *     }, 400);
     *     setInterval(function () {
     *         window.value = "test -- executed";
     *     }, 500);
     *     ```
     *
     * 1. Prevents `setInterval` calls if the callback contains `value` and the delay is not set to `300`
     *
     *     ```adblock
     *     example.org#%#//scriptlet('prevent-setInterval', 'value', '!300')
     *     ```
     *
     *     For instance, only the first of the following calls will not be prevented:
     *
     *     ```javascript
     *     setInterval(function () {
     *         window.test = "value 1 -- executed";
     *     }, 300);
     *     setInterval(function () {
     *         window.test = "value 2 -- prevented";
     *     }, 400);
     *     setInterval(function () {
     *         window.test = "value 3 -- prevented";
     *     }, 500);
     *     ```
     *
     * 1. Prevents `setInterval` calls if the callback does not contain `value` and the delay is not set to `300`
     *
     *     ```adblock
     *     example.org#%#//scriptlet('prevent-setInterval', '!value', '!300')
     *     ```
     *
     *     For instance, only the second of the following calls will be prevented:
     *
     *     ```javascript
     *     setInterval(function () {
     *         window.test = "test -- executed";
     *     }, 300);
     *     setInterval(function () {
     *         window.test = "test -- prevented";
     *     }, 400);
     *     setInterval(function () {
     *         window.test = "value -- executed";
     *     }, 400);
     *     setInterval(function () {
     *         window.value = "test -- executed";
     *     }, 500);
     *     ```
     *
     * 1. Prevents `setInterval` calls if the callback contains `value` and delay is a decimal number
     *
     *     ```adblock
     *     example.org#%#//scriptlet('prevent-setInterval', 'value', '300')
     *     ```
     *
     *     For instance, the following calls will be prevented:
     *
     *     ```javascript
     *     setInterval(function () {
     *         window.test = "value";
     *     }, 300);
     *     setInterval(function () {
     *         window.test = "value";
     *     }, 300 + Math.random());
     *     ```
     *
     * @added v1.0.4.
     */
    /* eslint-enable max-len */
    function preventSetInterval$1(source, matchCallback, matchDelay) {
      // logs setIntervals to console if no arguments have been specified
      var shouldLog = typeof matchCallback === 'undefined' && typeof matchDelay === 'undefined';
      var handlerWrapper = function handlerWrapper(target, thisArg, args) {
        var callback = args[0];
        var delay = args[1];
        var shouldPrevent = false;
        if (shouldLog) {
          hit(source);
          // https://github.com/AdguardTeam/Scriptlets/issues/105
          logMessage(source, "setInterval(".concat(String(callback), ", ").concat(delay, ")"), true);
        } else {
          shouldPrevent = isPreventionNeeded({
            callback,
            delay,
            matchCallback,
            matchDelay
          });
        }
        if (shouldPrevent) {
          hit(source);
          args[0] = noopFunc;
        }
        return target.apply(thisArg, args);
      };
      var setIntervalHandler = {
        apply: handlerWrapper
      };
      window.setInterval = new Proxy(window.setInterval, setIntervalHandler);
    }
    preventSetInterval$1.names = ['prevent-setInterval',
    // aliases are needed for matching the related scriptlet converted into our syntax
    'no-setInterval-if.js',
    // new implementation of setInterval-defuser.js
    'ubo-no-setInterval-if.js', 'setInterval-defuser.js',
    // old name should be supported as well
    'ubo-setInterval-defuser.js', 'nosiif.js',
    // new short name of no-setInterval-if
    'ubo-nosiif.js', 'sid.js',
    // old short scriptlet name
    'ubo-sid.js', 'ubo-no-setInterval-if', 'ubo-setInterval-defuser', 'ubo-nosiif', 'ubo-sid'];
    preventSetInterval$1.injections = [hit, noopFunc, isPreventionNeeded, logMessage,
    // following helpers should be injected as helpers above use them
    toRegExp, nativeIsNaN, parseMatchArg, parseDelayArg, isValidCallback, isValidMatchStr, isValidStrPattern, escapeRegExp, nativeIsFinite, isValidMatchNumber, parseRawDelay];

    /* eslint-disable max-len */
    /**
     * @scriptlet prevent-window-open
     *
     * @description
     * Prevents `window.open` calls when URL either matches or not matches the specified string/regexp.
     * Using it without parameters prevents all `window.open` calls.
     *
     * Related UBO scriptlet:
     * https://github.com/gorhill/uBlock/wiki/Resources-Library#no-window-open-ifjs-
     *
     * ### Syntax
     *
     * ```text
     * example.org#%#//scriptlet('prevent-window-open'[, match[, delay[, replacement]]])
     * ```
     *
     * - `match` — optional, string or regular expression.
     *   If not set or regular expression is invalid, all window.open calls will be matched.
     *   If starts with `!`, scriptlet will not match the stringified callback but all other will be defused.
     *   If do not start with `!`, the stringified callback will be matched.
     * - `delay` — optional, number of seconds. If not set, scriptlet will return `null`,
     *   otherwise valid sham window object as injected `iframe` will be returned
     *   for accessing its methods (blur(), focus() etc.) and will be removed after the delay.
     * - `replacement` — optional, string; one of the predefined constants:
     *     - `obj` — for returning an object instead of default iframe;
     *        for cases when the page requires a valid `window` instance to be returned
     *     - `log` — for logging window.open calls; not allowed for prod versions of filter lists.
     *
     * ### Examples
     *
     * 1. Prevent all `window.open` calls
     *
     *     ```adblock
     *     example.org#%#//scriptlet('prevent-window-open')
     *     ```
     *
     * 1. Prevent `window.open` for all URLs containing `example`
     *
     *     ```adblock
     *     example.org#%#//scriptlet('prevent-window-open', 'example')
     *     ```
     *
     * 1. Prevent `window.open` for all URLs matching RegExp `/example\./`
     *
     *     ```adblock
     *     example.org#%#//scriptlet('prevent-window-open', '/example\./')
     *     ```
     *
     * 1. Prevent `window.open` for all URLs **NOT** containing `example`
     *
     *     ```adblock
     *     example.org#%#//scriptlet('prevent-window-open', '!example')
     *     ```
     *
     * ### Old syntax of prevent-window-open parameters
     *
     * - `match` — optional, defaults to "matching", any positive number or nothing for "matching",
     *   0 or empty string for "not matching"
     * - `search` — optional, string or regexp for matching the URL passed to `window.open` call;
     *   defaults to search all `window.open` call
     * - `replacement` — optional, string to return prop value or property instead of window.open;
     *   defaults to return noopFunc.
     *
     * ### Examples of old syntax
     *
     * ```adblock
     * example.org#%#//scriptlet('prevent-window-open', '1', '/example\./')
     * example.org#%#//scriptlet('prevent-window-open', '0', 'example')
     * example.org#%#//scriptlet('prevent-window-open', '', '', 'trueFunc')
     * example.org#%#//scriptlet('prevent-window-open', '1', '', '{propName=noopFunc}')
     * ```
     *
     * > For better compatibility with uBO, old syntax is not recommended to use.
     *
     * @added v1.0.4.
     */
    /* eslint-enable max-len */
    function preventWindowOpen$1(source) {
      var match = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : '*';
      var delay = arguments.length > 2 ? arguments[2] : undefined;
      var replacement = arguments.length > 3 ? arguments[3] : undefined;
      // default match value is needed for preventing all window.open calls
      // if scriptlet runs without args
      var nativeOpen = window.open;
      var isNewSyntax = match !== '0' && match !== '1';
      var oldOpenWrapper = function oldOpenWrapper(str) {
        match = Number(match) > 0;
        // 'delay' was 'search' prop for matching in old syntax
        for (var _len = arguments.length, args = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
          args[_key - 1] = arguments[_key];
        }
        if (!isValidStrPattern(delay)) {
          logMessage(source, "Invalid parameter: ".concat(delay));
          return nativeOpen.apply(window, [str, ...args]);
        }
        var searchRegexp = toRegExp(delay);
        if (match !== searchRegexp.test(str)) {
          return nativeOpen.apply(window, [str, ...args]);
        }
        hit(source);
        return handleOldReplacement(replacement);
      };
      var newOpenWrapper = function newOpenWrapper(url) {
        var shouldLog = replacement && replacement.includes('log');
        for (var _len2 = arguments.length, args = new Array(_len2 > 1 ? _len2 - 1 : 0), _key2 = 1; _key2 < _len2; _key2++) {
          args[_key2 - 1] = arguments[_key2];
        }
        if (shouldLog) {
          var argsStr = args && args.length > 0 ? ", ".concat(args.join(', ')) : '';
          var message = "".concat(url).concat(argsStr);
          logMessage(source, message, true);
          hit(source);
        }
        var shouldPrevent = false;
        if (match === '*') {
          shouldPrevent = true;
        } else if (isValidMatchStr(match)) {
          var _parseMatchArg = parseMatchArg(match),
            isInvertedMatch = _parseMatchArg.isInvertedMatch,
            matchRegexp = _parseMatchArg.matchRegexp;
          shouldPrevent = matchRegexp.test(url) !== isInvertedMatch;
        } else {
          logMessage(source, "Invalid parameter: ".concat(match));
          shouldPrevent = false;
        }
        if (shouldPrevent) {
          var parsedDelay = parseInt(delay, 10);
          var result;
          if (nativeIsNaN(parsedDelay)) {
            result = noopNull();
          } else {
            var decoyArgs = {
              replacement,
              url,
              delay: parsedDelay
            };
            var decoy = createDecoy(decoyArgs);
            var popup = decoy.contentWindow;
            if (typeof popup === 'object' && popup !== null) {
              Object.defineProperty(popup, 'closed', {
                value: false
              });
              Object.defineProperty(popup, 'opener', {
                value: window
              });
              Object.defineProperty(popup, 'frameElement', {
                value: null
              });
            } else {
              var nativeGetter = decoy.contentWindow && decoy.contentWindow.get;
              Object.defineProperty(decoy, 'contentWindow', {
                get: getPreventGetter(nativeGetter)
              });
              popup = decoy.contentWindow;
            }
            result = popup;
          }
          hit(source);
          return result;
        }
        return nativeOpen.apply(window, [url, ...args]);
      };
      window.open = isNewSyntax ? newOpenWrapper : oldOpenWrapper;

      // Protect window.open from native code check
      window.open.toString = nativeOpen.toString.bind(nativeOpen);
    }
    preventWindowOpen$1.names = ['prevent-window-open',
    // aliases are needed for matching the related scriptlet converted into our syntax
    'window.open-defuser.js', 'ubo-window.open-defuser.js', 'ubo-window.open-defuser', 'nowoif.js', 'ubo-nowoif.js', 'ubo-nowoif', 'no-window-open-if.js', 'ubo-no-window-open-if.js', 'ubo-no-window-open-if'];
    preventWindowOpen$1.injections = [hit, isValidStrPattern, escapeRegExp, isValidMatchStr, toRegExp, nativeIsNaN, parseMatchArg, handleOldReplacement, createDecoy, getPreventGetter, noopNull, logMessage, noopFunc, trueFunc, substringBefore, substringAfter];

    /* eslint-disable max-len */
    /**
     * @scriptlet abort-current-inline-script
     *
     * @description
     * Aborts an inline script when it attempts to **read** or **write to** the specified property
     * AND when the contents of the `<script>` element contains the specified
     * text or matches the regular expression.
     *
     * Related UBO scriptlet:
     * https://github.com/gorhill/uBlock/wiki/Resources-Library#abort-current-inline-scriptjs-
     *
     * Related ABP source:
     * https://gitlab.com/eyeo/snippets/-/blob/main/source/behavioral/abort-current-inline-script.js
     *
     * ### Syntax
     *
     * ```text
     * example.org#%#//scriptlet('abort-current-inline-script', property[, search])
     * ```
     *
     * - `property` — required, path to a property (joined with `.` if needed). The property must be attached to `window`
     * - `search` — optional, string or regular expression that must match the inline script content.
     *   Defaults to abort all scripts which are trying to access the specified property.
     *   Invalid regular expression will cause exit and rule will not work.
     *
     * > Note please that to abort the inline script with addEventListener in it,
     * > `property` should be set as `EventTarget.prototype.addEventListener`, not just `addEventListener`.
     *
     * ### Examples
     *
     * 1. Aborts all inline scripts trying to access `window.alert`
     *
     *     ```adblock
     *     example.org#%#//scriptlet('abort-current-inline-script', 'alert')
     *     ```
     *
     * 1. Aborts inline scripts which are trying to access `window.alert` and contain `Hello, world`
     *
     *     ```adblock
     *     example.org#%#//scriptlet('abort-current-inline-script', 'alert', 'Hello, world')
     *     ```
     *
     *     For instance, the following script will be aborted:
     *
     *     ```html
     *     <script>alert("Hello, world");</script>
     *     ```
     *
     * 1. Aborts inline scripts which are trying to access `window.alert` and match regexp `/Hello.+world/`
     *
     *     ```adblock
     *     example.org#%#//scriptlet('abort-current-inline-script', 'alert', '/Hello.+world/')
     *     ```
     *
     *     For instance, the following scripts will be aborted:
     *
     *     ```html
     *     <script>alert("Hello, big world");</script>
     *     ```
     *
     *     ```html
     *     <script>alert("Hello, little world");</script>
     *     ```
     *
     *     And this script will not be aborted:
     *
     *     ```html
     *     <script>alert("Hi, little world");</script>
     *     ```
     *
     * @added v1.0.4.
     */
    /* eslint-enable max-len */
    function abortCurrentInlineScript$1(source, property, search) {
      var searchRegexp = toRegExp(search);
      var rid = randomId();
      var SRC_DATA_MARKER = 'data:text/javascript;base64,';
      var getCurrentScript = function getCurrentScript() {
        if ('currentScript' in document) {
          return document.currentScript;
        }
        var scripts = document.getElementsByTagName('script');
        return scripts[scripts.length - 1];
      };
      var ourScript = getCurrentScript();
      var abort = function abort() {
        var _scriptEl$src;
        var scriptEl = getCurrentScript();
        if (!scriptEl) {
          return;
        }
        var content = scriptEl.textContent;

        // We are using Node.prototype.textContent property descriptor
        // to get the real script content
        // even when document.currentScript.textContent is replaced.
        // https://github.com/AdguardTeam/Scriptlets/issues/57#issuecomment-593638991
        try {
          var textContentGetter = Object.getOwnPropertyDescriptor(Node.prototype, 'textContent').get;
          content = textContentGetter.call(scriptEl);
        } catch (e) {} // eslint-disable-line no-empty

        // https://github.com/AdguardTeam/Scriptlets/issues/130
        if (content.length === 0 && typeof scriptEl.src !== 'undefined' && (_scriptEl$src = scriptEl.src) !== null && _scriptEl$src !== void 0 && _scriptEl$src.startsWith(SRC_DATA_MARKER)) {
          var encodedContent = scriptEl.src.slice(SRC_DATA_MARKER.length);
          content = window.atob(encodedContent);
        }
        if (scriptEl instanceof HTMLScriptElement && content.length > 0 && scriptEl !== ourScript && searchRegexp.test(content)) {
          hit(source);
          throw new ReferenceError(rid);
        }
      };
      var setChainPropAccess = function setChainPropAccess(owner, property) {
        var chainInfo = getPropertyInChain(owner, property);
        var base = chainInfo.base;
        var prop = chainInfo.prop,
          chain = chainInfo.chain;

        // The scriptlet might be executed before the chain property has been created
        // (for instance, document.body before the HTML body was loaded).
        // In this case we're checking whether the base element exists or not
        // and if not, we simply exit without overriding anything.
        // e.g. https://github.com/AdguardTeam/Scriptlets/issues/57#issuecomment-575841092
        if (base instanceof Object === false && base === null) {
          var props = property.split('.');
          var propIndex = props.indexOf(prop);
          var baseName = props[propIndex - 1];
          var message = "The scriptlet had been executed before the ".concat(baseName, " was loaded.");
          logMessage(source, message);
          return;
        }
        if (chain) {
          var setter = function setter(a) {
            base = a;
            if (a instanceof Object) {
              setChainPropAccess(a, chain);
            }
          };
          Object.defineProperty(owner, prop, {
            get: function get() {
              return base;
            },
            set: setter
          });
          return;
        }
        var currentValue = base[prop];
        var origDescriptor = Object.getOwnPropertyDescriptor(base, prop);
        if (origDescriptor instanceof Object === false || origDescriptor.get instanceof Function === false) {
          currentValue = base[prop];
          origDescriptor = undefined;
        }
        var descriptorWrapper = Object.assign(getDescriptorAddon(), {
          currentValue,
          get() {
            if (!this.isAbortingSuspended) {
              this.isolateCallback(abort);
            }
            if (origDescriptor instanceof Object) {
              return origDescriptor.get.call(base);
            }
            return this.currentValue;
          },
          set(newValue) {
            if (!this.isAbortingSuspended) {
              this.isolateCallback(abort);
            }
            if (origDescriptor instanceof Object) {
              origDescriptor.set.call(base, newValue);
            } else {
              this.currentValue = newValue;
            }
          }
        });
        setPropertyAccess(base, prop, {
          // Call wrapped getter and setter to keep isAbortingSuspended & isolateCallback values
          get() {
            return descriptorWrapper.get.call(descriptorWrapper);
          },
          set(newValue) {
            descriptorWrapper.set.call(descriptorWrapper, newValue);
          }
        });
      };
      setChainPropAccess(window, property);
      window.onerror = createOnErrorHandler(rid).bind();
    }
    abortCurrentInlineScript$1.names = ['abort-current-inline-script',
    // aliases are needed for matching the related scriptlet converted into our syntax
    'abort-current-script.js', 'ubo-abort-current-script.js', 'acs.js', 'ubo-acs.js',
    // "ubo"-aliases with no "js"-ending
    'ubo-abort-current-script', 'ubo-acs',
    // obsolete but supported aliases
    'abort-current-inline-script.js', 'ubo-abort-current-inline-script.js', 'acis.js', 'ubo-acis.js', 'ubo-abort-current-inline-script', 'ubo-acis', 'abp-abort-current-inline-script'];
    abortCurrentInlineScript$1.injections = [randomId, setPropertyAccess, getPropertyInChain, toRegExp, createOnErrorHandler, hit, logMessage, isEmptyObject, getDescriptorAddon];

    /* eslint-disable max-len */
    /**
     * @scriptlet set-constant
     *
     * @description
     * Creates a constant property and assigns it one of the values from the predefined list.
     *
     * > Actually, it's not a constant. Please note, that it can be rewritten with a value of a different type.
     *
     * > If empty object is present in chain it will be trapped until chain leftovers appear.
     *
     * Related UBO scriptlet:
     * https://github.com/gorhill/uBlock/wiki/Resources-Library#set-constantjs-
     *
     * Related ABP snippet:
     * https://github.com/adblockplus/adblockpluscore/blob/adblockpluschrome-3.9.4/lib/content/snippets.js#L1361
     *
     * ### Syntax
     *
     * ```text
     * example.org#%#//scriptlet('set-constant', property, value[, stack,[ valueWrapper[, setProxyTrap]]])
     * ```
     *
     * - `property` — required, path to a property (joined with `.` if needed). The property must be attached to `window`.
     * - `value` — required. Possible values:
     *     - positive decimal integer `<= 32767`
     *     - one of the predefined constants:
     *         - `undefined`
     *         - `false`
     *         - `true`
     *         - `null`
     *         - `emptyObj` — empty object
     *         - `emptyArr` — empty array
     *         - `noopFunc` — function with empty body
     *         - `noopCallbackFunc` — function returning noopFunc
     *         - `trueFunc` — function returning true
     *         - `falseFunc` — function returning false
     *         - `throwFunc` — function throwing an error
     *         - `noopPromiseResolve` — function returning Promise object that is resolved with an empty response
     *         - `noopPromiseReject` — function returning Promise.reject()
     *         - `''` — empty string
     *         - `-1` — number value `-1`
     *         - `yes`
     *         - `no`
     * - `stack` — string or regular expression that must match the current function call stack trace,
     *   defaults to matching every call; if regular expression is invalid, it will be skipped
     * - `valueWrapper` – optional, string to modify a value to be set. Possible wrappers:
     *     - `asFunction` – function returning value
     *     - `asCallback` – function returning callback, that would return value
     *     - `asResolved` – Promise that would resolve with value
     *     - `asRejected` – Promise that would reject with value
     * - `setProxyTrap` – optional, boolean, if set to true, proxy trap will be set on the object
     *
     * ### Examples
     *
     * ```adblock
     * ! Any access to `window.first` will return `false`
     * example.org#%#//scriptlet('set-constant', 'first', 'false')
     *
     * ✔ window.first === false
     * ```
     *
     * ```adblock
     * ! Any call to `window.second()` will return `true`
     * example.org#%#//scriptlet('set-constant', 'second', 'trueFunc')
     *
     * ✔ window.second() === true
     * ✔ window.second.toString() === "function trueFunc() {return true;}"
     * ```
     *
     * ```adblock
     * ! Any call to `document.third()` will return `true` if the method is related to `checking.js`
     * example.org#%#//scriptlet('set-constant', 'document.third', 'trueFunc', 'checking.js')
     *
     * ✔ document.third() === true  // if the condition described above is met
     * ```
     *
     * ```adblock
     * ! Any call to `document.fourth()` will return `yes`
     * example.org#%#//scriptlet('set-constant', 'document.fourth', 'yes', '', 'asFunction')
     *
     * ✔ document.fourth() === 'yes'
     * ```
     *
     * ```adblock
     * ! Any call to `document.fifth()` will return `yes`
     * example.org#%#//scriptlet('set-constant', 'document.fifth', '42', '', 'asRejected')
     *
     * ✔ document.fifth.catch((reason) => reason === 42) // promise rejects with specified number
     * ```
     *
     * ```adblock
     * ! Any access to `window.foo.bar` will return `false` and the proxy trap will be set on the `foo` object
     * ! It may be required in the case when `foo` object is overwritten by website script
     * ! Related to this issue - https://github.com/AdguardTeam/Scriptlets/issues/330
     * example.org#%#//scriptlet('set-constant', 'foo.bar', 'false', '', '', 'true')
     *
     * ✔ window.foo.bar === false
     * ```
     *
     * @added v1.0.4.
     */
    /* eslint-enable max-len */
    function setConstant$1(source, property, value) {
      var stack = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : '';
      var valueWrapper = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : '';
      var setProxyTrap = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : false;
      var uboAliases = ['set-constant.js', 'ubo-set-constant.js', 'set.js', 'ubo-set.js', 'ubo-set-constant', 'ubo-set'];

      /**
       * UBO set-constant analog has it's own args sequence:
       * (property, value, defer | wrapper)
       * 'defer' – a stringified number, which defines execution time, or
       * 'wrapper' - string which defines value wrapper name
       *
       * joysound.com##+js(set, document.body.oncopy, null, 3)
       * kompetent.de##+js(set, Object.keys, 42, asFunction)
       */
      if (uboAliases.includes(source.name)) {
        /**
         * Check that third argument was intended as 'valueWrapper' argument,
         * by excluding 'defer' single digits case, and move it to 'valueWrapper'
         */
        if (stack.length !== 1 && !getNumberFromString(stack)) {
          valueWrapper = stack;
        }
        /**
         * ubo doesn't support 'stack', while adg doesn't support 'defer'
         * that goes in the same spot, so we discard it
         */
        stack = undefined;
      }
      if (!property || !matchStackTrace(stack, new Error().stack)) {
        return;
      }
      var isProxyTrapSet = false;
      var emptyArr = noopArray();
      var emptyObj = noopObject();
      var constantValue;
      if (value === 'undefined') {
        constantValue = undefined;
      } else if (value === 'false') {
        constantValue = false;
      } else if (value === 'true') {
        constantValue = true;
      } else if (value === 'null') {
        constantValue = null;
      } else if (value === 'emptyArr') {
        constantValue = emptyArr;
      } else if (value === 'emptyObj') {
        constantValue = emptyObj;
      } else if (value === 'noopFunc') {
        constantValue = noopFunc;
      } else if (value === 'noopCallbackFunc') {
        constantValue = noopCallbackFunc;
      } else if (value === 'trueFunc') {
        constantValue = trueFunc;
      } else if (value === 'falseFunc') {
        constantValue = falseFunc;
      } else if (value === 'throwFunc') {
        constantValue = throwFunc;
      } else if (value === 'noopPromiseResolve') {
        constantValue = noopPromiseResolve;
      } else if (value === 'noopPromiseReject') {
        constantValue = noopPromiseReject;
      } else if (/^\d+$/.test(value)) {
        constantValue = parseFloat(value);
        if (nativeIsNaN(constantValue)) {
          return;
        }
        if (Math.abs(constantValue) > 32767) {
          return;
        }
      } else if (value === '-1') {
        constantValue = -1;
      } else if (value === '') {
        constantValue = '';
      } else if (value === 'yes') {
        constantValue = 'yes';
      } else if (value === 'no') {
        constantValue = 'no';
      } else {
        return;
      }
      var valueWrapperNames = ['asFunction', 'asCallback', 'asResolved', 'asRejected'];
      if (valueWrapperNames.includes(valueWrapper)) {
        var valueWrappersMap = {
          asFunction(v) {
            return function () {
              return v;
            };
          },
          asCallback(v) {
            return function () {
              return function () {
                return v;
              };
            };
          },
          asResolved(v) {
            return Promise.resolve(v);
          },
          asRejected(v) {
            return Promise.reject(v);
          }
        };
        constantValue = valueWrappersMap[valueWrapper](constantValue);
      }
      var canceled = false;
      var mustCancel = function mustCancel(value) {
        if (canceled) {
          return canceled;
        }
        canceled = value !== undefined && constantValue !== undefined && typeof value !== typeof constantValue && value !== null;
        return canceled;
      };

      /**
       * Safely sets property on a given object
       *
       * IMPORTANT! this duplicates corresponding func in trusted-set-constant scriptlet as
       * reorganizing this to common helpers will most definitely complicate debugging
       *
       * @param {object} base arbitrary reachable object
       * @param {string} prop property name
       * @param {boolean} configurable if set property should be configurable
       * @param {object} handler custom property descriptor object
       * @returns {boolean} true if prop was trapped successfully
       */
      var trapProp = function trapProp(base, prop, configurable, handler) {
        if (!handler.init(base[prop])) {
          return false;
        }
        var origDescriptor = Object.getOwnPropertyDescriptor(base, prop);
        var prevSetter;
        // This is required to prevent scriptlets overwrite each over
        if (origDescriptor instanceof Object) {
          // This check is required to avoid defining non-configurable props
          if (!origDescriptor.configurable) {
            var message = "Property '".concat(prop, "' is not configurable");
            logMessage(source, message);
            return false;
          }
          if (base[prop]) {
            base[prop] = constantValue;
          }
          if (origDescriptor.set instanceof Function) {
            prevSetter = origDescriptor.set;
          }
        }
        Object.defineProperty(base, prop, {
          configurable,
          get() {
            return handler.get();
          },
          set(a) {
            if (prevSetter !== undefined) {
              prevSetter(a);
            }
            // Set a proxy trap to observe changes
            // This is a partial fix and only works with a single scriptlet,
            // a full fix requires synchronisation between the scriptlets
            // TODO: add proper fix when synchronisation between scriptlets is added
            // https://github.com/AdguardTeam/Scriptlets/issues/330
            if (a instanceof Object) {
              // Get properties which should be checked and remove first one
              // because it's current object
              var propertiesToCheck = property.split('.').slice(1);
              if (setProxyTrap && !isProxyTrapSet) {
                isProxyTrapSet = true;
                a = new Proxy(a, {
                  get: function get(target, propertyKey, val) {
                    // Check if object contains required property, if so
                    // check if current value is equal to constantValue, if not, set it to constantValue
                    propertiesToCheck.reduce(function (object, currentProp, index, array) {
                      var currentObj = object === null || object === void 0 ? void 0 : object[currentProp];
                      if (index === array.length - 1 && currentObj !== constantValue) {
                        object[currentProp] = constantValue;
                      }
                      return currentObj || object;
                    }, target);
                    return Reflect.get(target, propertyKey, val);
                  }
                });
              }
            }
            handler.set(a);
          }
        });
        return true;
      };

      /**
       * Traverses given chain to set constant value to its end prop
       * Chains that yet include non-object values (e.g null) are valid and will be
       * traversed when appropriate chain member is set by an external script
       *
       * IMPORTANT! this duplicates corresponding func in trusted-set-constant scriptlet as
       * reorganizing this to common helpers will most definitely complicate debugging
       *
       * @param {object} owner object that owns chain
       * @param {string} property chain of owner properties
       */
      var setChainPropAccess = function setChainPropAccess(owner, property) {
        var chainInfo = getPropertyInChain(owner, property);
        var base = chainInfo.base;
        var prop = chainInfo.prop,
          chain = chainInfo.chain;

        // Handler method init is used to keep track of factual value
        // and apply mustCancel() check only on end prop
        var inChainPropHandler = {
          factValue: undefined,
          init(a) {
            this.factValue = a;
            return true;
          },
          get() {
            return this.factValue;
          },
          set(a) {
            // Prevent breakage due to loop assignments like win.obj = win.obj
            if (this.factValue === a) {
              return;
            }
            this.factValue = a;
            if (a instanceof Object) {
              setChainPropAccess(a, chain);
            }
          }
        };
        var endPropHandler = {
          init(a) {
            if (mustCancel(a)) {
              return false;
            }
            return true;
          },
          get() {
            return constantValue;
          },
          set(a) {
            if (!mustCancel(a)) {
              return;
            }
            constantValue = a;
          }
        };

        // End prop case
        if (!chain) {
          var isTrapped = trapProp(base, prop, false, endPropHandler);
          if (isTrapped) {
            hit(source);
          }
          return;
        }

        // Null prop in chain
        if (base !== undefined && base[prop] === null) {
          trapProp(base, prop, true, inChainPropHandler);
          return;
        }

        // Empty object prop in chain
        if ((base instanceof Object || typeof base === 'object') && isEmptyObject(base)) {
          trapProp(base, prop, true, inChainPropHandler);
        }

        // Defined prop in chain
        var propValue = owner[prop];
        if (propValue instanceof Object || typeof propValue === 'object' && propValue !== null) {
          setChainPropAccess(propValue, chain);
        }

        // Undefined prop in chain
        trapProp(base, prop, true, inChainPropHandler);
      };
      setChainPropAccess(window, property);
    }
    setConstant$1.names = ['set-constant',
    // aliases are needed for matching the related scriptlet converted into our syntax
    'set-constant.js', 'ubo-set-constant.js', 'set.js', 'ubo-set.js', 'ubo-set-constant', 'ubo-set', 'abp-override-property-read'];
    setConstant$1.injections = [hit, logMessage, getNumberFromString, noopArray, noopObject, noopFunc, noopCallbackFunc, trueFunc, falseFunc, throwFunc, noopPromiseReject, noopPromiseResolve, getPropertyInChain, matchStackTrace, nativeIsNaN, isEmptyObject,
    // following helpers should be imported and injected
    // because they are used by helpers above
    shouldAbortInlineOrInjectedScript, getNativeRegexpTest, setPropertyAccess, toRegExp, backupRegExpValues, restoreRegExpValues];

    /* eslint-disable max-len */
    /**
     * @scriptlet remove-cookie
     *
     * @description
     * Removes current page cookies by passed string matching with name. For current domain and subdomains.
     * Runs on load and before unload.
     *
     * Related UBO scriptlet:
     * https://github.com/gorhill/uBlock/wiki/Resources-Library#cookie-removerjs-
     *
     * Related ABP source:
     * https://gitlab.com/eyeo/snippets/-/blob/main/source/behavioral/cookie-remover.js
     *
     * ### Syntax
     *
     * ```text
     * example.org#%#//scriptlet('remove-cookie'[, match])
     * ```
     *
     * - `match` — optional, string or regex matching the cookie name.
     *   If not specified all accessible cookies will be removed.
     *
     * ### Examples
     *
     * 1. Removes all cookies
     *
     *     ```adblock
     *     example.org#%#//scriptlet('remove-cookie')
     *     ```
     *
     * 1. Removes cookies which name contains `example` string
     *
     *     ```adblock
     *     example.org#%#//scriptlet('remove-cookie', 'example')
     *     ```
     *
     *     For instance this cookie will be removed:
     *
     *     ```javascript
     *     document.cookie = '__example=randomValue';
     *     ```
     *
     * @added v1.0.4.
     */
    /* eslint-enable max-len */
    function removeCookie$1(source, match) {
      var matchRegexp = toRegExp(match);
      var removeCookieFromHost = function removeCookieFromHost(cookieName, hostName) {
        var cookieSpec = "".concat(cookieName, "=");
        var domain1 = "; domain=".concat(hostName);
        var domain2 = "; domain=.".concat(hostName);
        var path = '; path=/';
        var expiration = '; expires=Thu, 01 Jan 1970 00:00:00 GMT';
        document.cookie = cookieSpec + expiration;
        document.cookie = cookieSpec + domain1 + expiration;
        document.cookie = cookieSpec + domain2 + expiration;
        document.cookie = cookieSpec + path + expiration;
        document.cookie = cookieSpec + domain1 + path + expiration;
        document.cookie = cookieSpec + domain2 + path + expiration;
        hit(source);
      };
      var rmCookie = function rmCookie() {
        document.cookie.split(';').forEach(function (cookieStr) {
          var pos = cookieStr.indexOf('=');
          if (pos === -1) {
            return;
          }
          var cookieName = cookieStr.slice(0, pos).trim();
          if (!matchRegexp.test(cookieName)) {
            return;
          }
          var hostParts = document.location.hostname.split('.');
          for (var i = 0; i <= hostParts.length - 1; i += 1) {
            var hostName = hostParts.slice(i).join('.');
            if (hostName) {
              removeCookieFromHost(cookieName, hostName);
            }
          }
        });
      };
      rmCookie();
      window.addEventListener('beforeunload', rmCookie);
    }
    removeCookie$1.names = ['remove-cookie',
    // aliases are needed for matching the related scriptlet converted into our syntax
    'cookie-remover.js', 'ubo-cookie-remover.js', 'ubo-cookie-remover', 'remove-cookie.js', 'ubo-remove-cookie.js', 'ubo-remove-cookie', 'abp-cookie-remover'];
    removeCookie$1.injections = [toRegExp, hit];

    /* eslint-disable max-len */
    /**
     * @scriptlet prevent-addEventListener
     *
     * @description
     * Prevents adding event listeners for the specified events and callbacks.
     *
     * Related UBO scriptlet:
     * https://github.com/gorhill/uBlock/wiki/Resources-Library#addeventlistener-defuserjs-
     *
     * Related ABP snippet:
     * https://gitlab.com/eyeo/snippets/-/blob/main/source/behavioral/prevent-listener.js
     *
     * ### Syntax
     *
     * ```text
     * example.org#%#//scriptlet('prevent-addEventListener'[, typeSearch[, listenerSearch]])
     * ```
     *
     * - `typeSearch` — optional, string or regular expression matching the type (event name);
     *   defaults to match all types; invalid regular expression will cause exit and rule will not work
     * - `listenerSearch` — optional, string or regular expression matching the listener function body;
     *   defaults to match all listeners; invalid regular expression will cause exit and rule will not work
     *
     * ### Examples
     *
     * 1. Prevent all `click` listeners
     *
     *     ```adblock
     *     example.org#%#//scriptlet('prevent-addEventListener', 'click')
     *     ```
     *
     * 1. Prevent 'click' listeners with the callback body containing `searchString`
     *
     *     ```adblock
     *     example.org#%#//scriptlet('prevent-addEventListener', 'click', 'searchString')
     *     ```
     *
     *     For instance, this listener will not be called:
     *
     *     ```javascript
     *     el.addEventListener('click', () => {
     *         window.test = 'searchString';
     *     });
     *     ```
     *
     * @added v1.0.4.
     */
    /* eslint-enable max-len */
    function preventAddEventListener$1(source, typeSearch, listenerSearch) {
      var typeSearchRegexp = toRegExp(typeSearch);
      var listenerSearchRegexp = toRegExp(listenerSearch);
      var nativeAddEventListener = window.EventTarget.prototype.addEventListener;
      function addEventListenerWrapper(type, listener) {
        var _this$constructor;
        var shouldPrevent = false;
        if (validateType(type) && validateListener(listener)) {
          shouldPrevent = typeSearchRegexp.test(type.toString()) && listenerSearchRegexp.test(listenerToString(listener));
        }
        if (shouldPrevent) {
          hit(source);
          return undefined;
        }

        // Avoid illegal invocations due to lost context
        // https://github.com/AdguardTeam/Scriptlets/issues/271
        var context = this;
        if (this && ((_this$constructor = this.constructor) === null || _this$constructor === void 0 ? void 0 : _this$constructor.name) === 'Window' && this !== window) {
          context = window;
        }
        for (var _len = arguments.length, args = new Array(_len > 2 ? _len - 2 : 0), _key = 2; _key < _len; _key++) {
          args[_key - 2] = arguments[_key];
        }
        return nativeAddEventListener.apply(context, [type, listener, ...args]);
      }
      var descriptor = {
        configurable: true,
        set: function set() {},
        get: function get() {
          return addEventListenerWrapper;
        }
      };
      // https://github.com/AdguardTeam/Scriptlets/issues/215
      // https://github.com/AdguardTeam/Scriptlets/issues/143
      Object.defineProperty(window.EventTarget.prototype, 'addEventListener', descriptor);
      Object.defineProperty(window, 'addEventListener', descriptor);
      Object.defineProperty(document, 'addEventListener', descriptor);
    }
    preventAddEventListener$1.names = ['prevent-addEventListener',
    // aliases are needed for matching the related scriptlet converted into our syntax
    'addEventListener-defuser.js', 'ubo-addEventListener-defuser.js', 'aeld.js', 'ubo-aeld.js', 'ubo-addEventListener-defuser', 'ubo-aeld', 'abp-prevent-listener'];
    preventAddEventListener$1.injections = [hit, toRegExp, validateType, validateListener, listenerToString];

    /* eslint-disable consistent-return, no-eval */

    /**
     * @scriptlet prevent-bab
     *
     * @description
     * Prevents BlockAdblock script from detecting an ad blocker.
     *
     * Related UBO scriptlet:
     * https://github.com/gorhill/uBlock/wiki/Resources-Library#bab-defuserjs-
     *
     * It also can be used as `$redirect` sometimes.
     * See [redirect description](../wiki/about-redirects.md#prevent-bab).
     *
     * ### Syntax
     *
     * ```adblock
     * example.org#%#//scriptlet('prevent-bab')
     * ```
     *
     * @added v1.0.4.
     */
    function preventBab$2(source) {
      var nativeSetTimeout = window.setTimeout;
      var babRegex = /\.bab_elementid.$/;
      var timeoutWrapper = function timeoutWrapper(callback) {
        if (typeof callback !== 'string' || !babRegex.test(callback)) {
          for (var _len = arguments.length, args = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
            args[_key - 1] = arguments[_key];
          }
          return nativeSetTimeout.apply(window, [callback, ...args]);
        }
        hit(source);
      };
      window.setTimeout = timeoutWrapper;
      var signatures = [['blockadblock'], ['babasbm'], [/getItem\('babn'\)/], ['getElementById', 'String.fromCharCode', 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789', 'charAt', 'DOMContentLoaded', 'AdBlock', 'addEventListener', 'doScroll', 'fromCharCode', '<<2|r>>4', 'sessionStorage', 'clientWidth', 'localStorage', 'Math', 'random']];
      var check = function check(str) {
        if (typeof str !== 'string') {
          return false;
        }
        for (var i = 0; i < signatures.length; i += 1) {
          var tokens = signatures[i];
          var match = 0;
          for (var j = 0; j < tokens.length; j += 1) {
            var token = tokens[j];
            var found = token instanceof RegExp ? token.test(str) : str.includes(token);
            if (found) {
              match += 1;
            }
          }
          if (match / tokens.length >= 0.8) {
            return true;
          }
        }
        return false;
      };
      var nativeEval = window.eval;
      var evalWrapper = function evalWrapper(str) {
        if (!check(str)) {
          return nativeEval(str);
        }
        hit(source);
        var bodyEl = document.body;
        if (bodyEl) {
          bodyEl.style.removeProperty('visibility');
        }
        var el = document.getElementById('babasbmsgx');
        if (el) {
          el.parentNode.removeChild(el);
        }
      };
      window.eval = evalWrapper.bind(window);
    }
    preventBab$2.names = ['prevent-bab'
    // there are no aliases for this scriptlet
    ];

    preventBab$2.injections = [hit];

    /* eslint-disable no-unused-vars, no-extra-bind, func-names */

    /* eslint-disable max-len */
    /**
     * @scriptlet nowebrtc
     *
     * @description
     * Disables WebRTC by overriding `RTCPeerConnection`.
     * The overridden function will log every attempt to create a new connection.
     *
     * Related UBO scriptlet:
     * https://github.com/gorhill/uBlock/wiki/Resources-Library#nowebrtcjs-
     *
     * ### Syntax
     *
     * ```adblock
     * example.org#%#//scriptlet('nowebrtc')
     * ```
     *
     * @added v1.0.4.
     */
    /* eslint-enable max-len */
    function nowebrtc$1(source) {
      var propertyName = '';
      if (window.RTCPeerConnection) {
        propertyName = 'RTCPeerConnection';
      } else if (window.webkitRTCPeerConnection) {
        propertyName = 'webkitRTCPeerConnection';
      }
      if (propertyName === '') {
        return;
      }
      var rtcReplacement = function rtcReplacement(config) {
        // eslint-disable-next-line max-len
        var message = "Document tried to create an RTCPeerConnection: ".concat(convertRtcConfigToString(config));
        logMessage(source, message);
        hit(source);
      };
      rtcReplacement.prototype = {
        close: noopFunc,
        createDataChannel: noopFunc,
        createOffer: noopFunc,
        setRemoteDescription: noopFunc
      };
      var rtc = window[propertyName];
      window[propertyName] = rtcReplacement;
      if (rtc.prototype) {
        rtc.prototype.createDataChannel = function (a, b) {
          return {
            close: noopFunc,
            send: noopFunc
          };
        }.bind(null);
      }
    }
    nowebrtc$1.names = ['nowebrtc',
    // aliases are needed for matching the related scriptlet converted into our syntax
    'nowebrtc.js', 'ubo-nowebrtc.js', 'ubo-nowebrtc'];
    nowebrtc$1.injections = [hit, noopFunc, logMessage, convertRtcConfigToString];

    /**
     * @scriptlet log-addEventListener
     *
     * @description
     * Logs all addEventListener calls to the console.
     *
     * Related UBO scriptlet:
     * https://github.com/gorhill/uBlock/wiki/Resources-Library#addeventlistener-loggerjs-
     *
     * ### Syntax
     *
     * ```adblock
     * example.org#%#//scriptlet('log-addEventListener')
     * ```
     *
     * @added v1.0.4.
     */
    function logAddEventListener$1(source) {
      var nativeAddEventListener = window.EventTarget.prototype.addEventListener;
      function addEventListenerWrapper(type, listener) {
        var _this$constructor;
        if (validateType(type) && validateListener(listener)) {
          var message = "addEventListener(\"".concat(type, "\", ").concat(listenerToString(listener), ")");
          logMessage(source, message, true);
          hit(source);
        } else {
          // logging while debugging
          var _message = "Invalid event type or listener passed to addEventListener:\n        type: ".concat(convertTypeToString(type), "\n        listener: ").concat(convertTypeToString(listener));
          logMessage(source, _message, true);
        }

        // Avoid illegal invocations due to lost context
        // https://github.com/AdguardTeam/Scriptlets/issues/271
        var context = this;
        if (this && ((_this$constructor = this.constructor) === null || _this$constructor === void 0 ? void 0 : _this$constructor.name) === 'Window' && this !== window) {
          context = window;
        }
        for (var _len = arguments.length, args = new Array(_len > 2 ? _len - 2 : 0), _key = 2; _key < _len; _key++) {
          args[_key - 2] = arguments[_key];
        }
        return nativeAddEventListener.apply(context, [type, listener, ...args]);
      }
      var descriptor = {
        configurable: true,
        set: function set() {},
        get: function get() {
          return addEventListenerWrapper;
        }
      };
      // https://github.com/AdguardTeam/Scriptlets/issues/215
      // https://github.com/AdguardTeam/Scriptlets/issues/143
      Object.defineProperty(window.EventTarget.prototype, 'addEventListener', descriptor);
      Object.defineProperty(window, 'addEventListener', descriptor);
      Object.defineProperty(document, 'addEventListener', descriptor);
    }
    logAddEventListener$1.names = ['log-addEventListener',
    // aliases are needed for matching the related scriptlet converted into our syntax
    'addEventListener-logger.js', 'ubo-addEventListener-logger.js', 'aell.js', 'ubo-aell.js', 'ubo-addEventListener-logger', 'ubo-aell'];
    logAddEventListener$1.injections = [hit, validateType, validateListener, listenerToString, convertTypeToString, logMessage, objectToString$1, isEmptyObject];

    /* eslint-disable no-eval */

    /**
     * @scriptlet log-eval
     *
     * @description
     * Logs all `eval()` or `new Function()` calls to the console.
     *
     * ### Syntax
     *
     * ```adblock
     * example.org#%#//scriptlet('log-eval')
     * ```
     *
     * @added v1.0.4.
     */
    function logEval$1(source) {
      // wrap eval function
      var nativeEval = window.eval;
      function evalWrapper(str) {
        hit(source);
        logMessage(source, "eval(\"".concat(str, "\")"), true);
        return nativeEval(str);
      }
      window.eval = evalWrapper;

      // wrap new Function
      var nativeFunction = window.Function;
      function FunctionWrapper() {
        hit(source);
        for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
          args[_key] = arguments[_key];
        }
        logMessage(source, "new Function(".concat(args.join(', '), ")"), true);
        return nativeFunction.apply(this, [...args]);
      }
      FunctionWrapper.prototype = Object.create(nativeFunction.prototype);
      FunctionWrapper.prototype.constructor = FunctionWrapper;
      window.Function = FunctionWrapper;
    }
    logEval$1.names = ['log-eval'];
    logEval$1.injections = [hit, logMessage];

    /**
     * @scriptlet log
     *
     * @description
     * A simple scriptlet which only purpose is to print arguments to console.
     * This scriptlet can be helpful for debugging and troubleshooting other scriptlets.
     *
     * Related ABP source:
     * https://gitlab.com/eyeo/snippets/-/blob/main/source/introspection/log.js
     *
     * ### Examples
     *
     * ```adblock
     * example.org#%#//scriptlet('log', 'arg1', 'arg2')
     * ```
     *
     * @added v1.0.4.
     */
    function log$1() {
      for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
        args[_key] = arguments[_key];
      }
      console.log(args); // eslint-disable-line no-console
    }

    log$1.names = ['log', 'abp-log'];

    /* eslint-disable no-eval, no-extra-bind */

    /**
     * @scriptlet noeval
     *
     * @description
     * Prevents page to use eval.
     * Notifies about attempts in the console
     *
     * Related UBO scriptlet:
     * https://github.com/gorhill/uBlock/wiki/Resources-Library#noevaljs-
     *
     * It also can be used as `$redirect` rules sometimes.
     * See [redirect description](../wiki/about-redirects.md#noeval).
     *
     * ### Syntax
     *
     * ```adblock
     * example.org#%#//scriptlet('noeval')
     * ```
     *
     * @added v1.0.4.
     */
    function noeval$1(source) {
      window.eval = function evalWrapper(s) {
        hit(source);
        logMessage(source, "AdGuard has prevented eval:\n".concat(s), true);
      }.bind();
    }
    noeval$1.names = ['noeval',
    // aliases are needed for matching the related scriptlet converted into our syntax
    'noeval.js', 'silent-noeval.js', 'ubo-noeval.js', 'ubo-silent-noeval.js', 'ubo-noeval', 'ubo-silent-noeval'];
    noeval$1.injections = [hit, logMessage];

    /* eslint-disable no-eval, no-extra-bind, func-names */


    /**
     * @scriptlet prevent-eval-if
     *
     * @description
     * Prevents page to use eval matching payload.
     *
     * Related UBO scriptlet:
     * https://github.com/gorhill/uBlock/wiki/Resources-Library#noeval-ifjs-
     *
     * ### Syntax
     *
     * ```text
     * example.org#%#//scriptlet('prevent-eval-if'[, search])
     * ```
     *
     * - `search` — optional, string or regular expression matching the stringified eval payload;
     *   defaults to match all stringified eval payloads;
     *   invalid regular expression will cause exit and rule will not work
     *
     * ### Examples
     *
     * ```adblock
     * ! Prevents eval if it matches 'test'
     * example.org#%#//scriptlet('prevent-eval-if', 'test')
     * ```
     *
     * @added v1.0.4.
     */
    function preventEvalIf$1(source, search) {
      var searchRegexp = toRegExp(search);
      var nativeEval = window.eval;
      window.eval = function (payload) {
        if (!searchRegexp.test(payload.toString())) {
          return nativeEval.call(window, payload);
        }
        hit(source);
        return undefined;
      }.bind(window);
    }
    preventEvalIf$1.names = ['prevent-eval-if',
    // aliases are needed for matching the related scriptlet converted into our syntax
    'noeval-if.js', 'ubo-noeval-if.js', 'ubo-noeval-if'];
    preventEvalIf$1.injections = [toRegExp, hit];

    /* eslint-disable func-names, no-multi-assign */

    /**
     * @scriptlet prevent-fab-3.2.0
     *
     * @description
     * Prevents execution of the FAB script v3.2.0.
     *
     * Related UBO scriptlet:
     * https://github.com/gorhill/uBlock/wiki/Resources-Library#fuckadblockjs-320-
     *
     * ### Syntax
     *
     * ```adblock
     * example.org#%#//scriptlet('prevent-fab-3.2.0')
     * ```
     *
     * @added v1.0.4.
     */
    function preventFab$1(source) {
      hit(source);

      // redefines Fab function for adblock detection
      var Fab = function Fab() {};
      Fab.prototype.check = noopFunc;
      Fab.prototype.clearEvent = noopFunc;
      Fab.prototype.emitEvent = noopFunc;
      Fab.prototype.on = function (a, b) {
        if (!a) {
          b();
        }
        return this;
      };
      Fab.prototype.onDetected = noopThis;
      Fab.prototype.onNotDetected = function (a) {
        a();
        return this;
      };
      Fab.prototype.setOption = noopFunc;
      Fab.prototype.options = {
        set: noopFunc,
        get: noopFunc
      };
      var fab = new Fab();
      var getSetFab = {
        get() {
          return Fab;
        },
        set() {}
      };
      var getsetfab = {
        get() {
          return fab;
        },
        set() {}
      };

      // redefined Fab data properties which if 'FuckAdBlock' variable exists
      if (Object.prototype.hasOwnProperty.call(window, 'FuckAdBlock')) {
        window.FuckAdBlock = Fab;
      } else {
        // or redefined Fab accessor properties
        Object.defineProperty(window, 'FuckAdBlock', getSetFab);
      }
      if (Object.prototype.hasOwnProperty.call(window, 'BlockAdBlock')) {
        window.BlockAdBlock = Fab;
      } else {
        Object.defineProperty(window, 'BlockAdBlock', getSetFab);
      }
      if (Object.prototype.hasOwnProperty.call(window, 'SniffAdBlock')) {
        window.SniffAdBlock = Fab;
      } else {
        Object.defineProperty(window, 'SniffAdBlock', getSetFab);
      }
      if (Object.prototype.hasOwnProperty.call(window, 'fuckAdBlock')) {
        window.fuckAdBlock = fab;
      } else {
        Object.defineProperty(window, 'fuckAdBlock', getsetfab);
      }
      if (Object.prototype.hasOwnProperty.call(window, 'blockAdBlock')) {
        window.blockAdBlock = fab;
      } else {
        Object.defineProperty(window, 'blockAdBlock', getsetfab);
      }
      if (Object.prototype.hasOwnProperty.call(window, 'sniffAdBlock')) {
        window.sniffAdBlock = fab;
      } else {
        Object.defineProperty(window, 'sniffAdBlock', getsetfab);
      }
    }
    preventFab$1.names = ['prevent-fab-3.2.0',
    // aliases are needed for matching the related scriptlet converted into our syntax
    'nofab.js', 'ubo-nofab.js', 'fuckadblock.js-3.2.0', 'ubo-fuckadblock.js-3.2.0', 'ubo-nofab'];
    preventFab$1.injections = [hit, noopFunc, noopThis];

    /* eslint-disable func-names, no-multi-assign */

    /**
     * @scriptlet set-popads-dummy
     *
     * @description
     * Sets static properties PopAds and popns.
     *
     * Related UBO scriptlet:
     * https://github.com/gorhill/uBlock/wiki/Resources-Library#popads-dummyjs-
     *
     * ### Syntax
     *
     * ```adblock
     * example.org#%#//scriptlet('set-popads-dummy')
     * ```
     *
     * @added v1.0.4.
     */
    function setPopadsDummy$1(source) {
      delete window.PopAds;
      delete window.popns;
      Object.defineProperties(window, {
        PopAds: {
          get: function get() {
            hit(source);
            return {};
          }
        },
        popns: {
          get: function get() {
            hit(source);
            return {};
          }
        }
      });
    }
    setPopadsDummy$1.names = ['set-popads-dummy',
    // aliases are needed for matching the related scriptlet converted into our syntax
    'popads-dummy.js', 'ubo-popads-dummy.js', 'ubo-popads-dummy'];
    setPopadsDummy$1.injections = [hit];

    /**
     * @scriptlet prevent-popads-net
     *
     * @description
     * Aborts on property write (PopAds, popns), throws reference error with random id.
     *
     * Related UBO scriptlet:
     * https://github.com/gorhill/uBlock/wiki/Resources-Library#popadsnetjs-
     *
     * ### Syntax
     *
     * ```adblock
     * example.org#%#//scriptlet('prevent-popads-net')
     * ```
     *
     * @added v1.0.4.
     */
    function preventPopadsNet$1(source) {
      var rid = randomId();
      var throwError = function throwError() {
        throw new ReferenceError(rid);
      };
      delete window.PopAds;
      delete window.popns;
      Object.defineProperties(window, {
        PopAds: {
          set: throwError
        },
        popns: {
          set: throwError
        }
      });
      window.onerror = createOnErrorHandler(rid).bind();
      hit(source);
    }
    preventPopadsNet$1.names = ['prevent-popads-net',
    // aliases are needed for matching the related scriptlet converted into our syntax
    'popads.net.js', 'ubo-popads.net.js', 'ubo-popads.net'];
    preventPopadsNet$1.injections = [createOnErrorHandler, randomId, hit];

    /* eslint-disable func-names */

    /**
     * @scriptlet prevent-adfly
     *
     * @description
     * Prevents anti-adblock scripts on adfly short links.
     *
     * Related UBO scriptlet:
     * https://github.com/gorhill/uBlock/wiki/Resources-Library#adfly-defuserjs-
     *
     * ### Syntax
     *
     * ```adblock
     * example.org#%#//scriptlet('prevent-adfly')
     * ```
     *
     * @added v1.0.4.
     */
    function preventAdfly$1(source) {
      var isDigit = function isDigit(data) {
        return /^\d$/.test(data);
      };
      var handler = function handler(encodedURL) {
        var evenChars = '';
        var oddChars = '';
        for (var i = 0; i < encodedURL.length; i += 1) {
          if (i % 2 === 0) {
            evenChars += encodedURL.charAt(i);
          } else {
            oddChars = encodedURL.charAt(i) + oddChars;
          }
        }
        var data = (evenChars + oddChars).split('');
        for (var _i = 0; _i < data.length; _i += 1) {
          if (isDigit(data[_i])) {
            for (var ii = _i + 1; ii < data.length; ii += 1) {
              if (isDigit(data[ii])) {
                // eslint-disable-next-line no-bitwise
                var temp = parseInt(data[_i], 10) ^ parseInt(data[ii], 10);
                if (temp < 10) {
                  data[_i] = temp.toString();
                }
                _i = ii;
                break;
              }
            }
          }
        }
        data = data.join('');
        var decodedURL = window.atob(data).slice(16, -16);
        if (window.stop) {
          window.stop();
        }
        window.onbeforeunload = null;
        window.location.href = decodedURL;
      };
      var val;
      // Do not apply handler more than one time
      var applyHandler = true;
      var result = setPropertyAccess(window, 'ysmm', {
        configurable: false,
        set: function set(value) {
          if (applyHandler) {
            applyHandler = false;
            try {
              if (typeof value === 'string') {
                handler(value);
              }
            } catch (err) {} // eslint-disable-line no-empty
          }

          val = value;
        },
        get: function get() {
          return val;
        }
      });
      if (result) {
        hit(source);
      } else {
        logMessage(source, 'Failed to set up prevent-adfly scriptlet');
      }
    }
    preventAdfly$1.names = ['prevent-adfly'
    // there are no aliases for this scriptlet
    ];

    preventAdfly$1.injections = [setPropertyAccess, hit, logMessage];

    /* eslint-disable max-len */
    /**
     * @scriptlet debug-on-property-read
     *
     * @description
     * This scriptlet is basically the same as [abort-on-property-read](#abort-on-property-read),
     * but instead of aborting it starts the debugger.
     *
     * > It is not allowed for prod versions of filter lists.
     *
     * ### Examples
     *
     * ```adblock
     * ! Debug script if it tries to access `window.alert`
     * example.org#%#//scriptlet('debug-on-property-read', 'alert')
     *
     * ! or `window.open`
     * example.org#%#//scriptlet('debug-on-property-read', 'open')
     * ```
     *
     * @added v1.0.4.
     */
    /* eslint-enable max-len */
    function debugOnPropertyRead$1(source, property) {
      if (!property) {
        return;
      }
      var rid = randomId();
      var abort = function abort() {
        hit(source);
        debugger; // eslint-disable-line no-debugger
      };

      var setChainPropAccess = function setChainPropAccess(owner, property) {
        var chainInfo = getPropertyInChain(owner, property);
        var base = chainInfo.base;
        var prop = chainInfo.prop,
          chain = chainInfo.chain;
        if (chain) {
          var setter = function setter(a) {
            base = a;
            if (a instanceof Object) {
              setChainPropAccess(a, chain);
            }
          };
          Object.defineProperty(owner, prop, {
            get: function get() {
              return base;
            },
            set: setter
          });
          return;
        }
        setPropertyAccess(base, prop, {
          get: abort,
          set: noopFunc
        });
      };
      setChainPropAccess(window, property);
      window.onerror = createOnErrorHandler(rid).bind();
    }
    debugOnPropertyRead$1.names = ['debug-on-property-read'];
    debugOnPropertyRead$1.injections = [randomId, setPropertyAccess, getPropertyInChain, createOnErrorHandler, hit, noopFunc, isEmptyObject];

    /* eslint-disable max-len */
    /**
     * @scriptlet debug-on-property-write
     *
     * @description
     * This scriptlet is basically the same as [abort-on-property-write](#abort-on-property-write),
     * but instead of aborting it starts the debugger.
     *
     * > It is not allowed for prod versions of filter lists.
     *
     * ### Examples
     *
     * ```adblock
     * ! Aborts script when it tries to write in property `window.test`
     * example.org#%#//scriptlet('debug-on-property-write', 'test')
     * ```
     *
     * @added v1.0.4.
     */
    /* eslint-enable max-len */
    function debugOnPropertyWrite$1(source, property) {
      if (!property) {
        return;
      }
      var rid = randomId();
      var abort = function abort() {
        hit(source);
        debugger; // eslint-disable-line no-debugger
      };

      var setChainPropAccess = function setChainPropAccess(owner, property) {
        var chainInfo = getPropertyInChain(owner, property);
        var base = chainInfo.base;
        var prop = chainInfo.prop,
          chain = chainInfo.chain;
        if (chain) {
          var setter = function setter(a) {
            base = a;
            if (a instanceof Object) {
              setChainPropAccess(a, chain);
            }
          };
          Object.defineProperty(owner, prop, {
            get: function get() {
              return base;
            },
            set: setter
          });
          return;
        }
        setPropertyAccess(base, prop, {
          set: abort
        });
      };
      setChainPropAccess(window, property);
      window.onerror = createOnErrorHandler(rid).bind();
    }
    debugOnPropertyWrite$1.names = ['debug-on-property-write'];
    debugOnPropertyWrite$1.injections = [randomId, setPropertyAccess, getPropertyInChain, createOnErrorHandler, hit, isEmptyObject];

    /* eslint-disable max-len */
    /**
     * @scriptlet debug-current-inline-script
     *
     * @description
     * This scriptlet is basically the same as [abort-current-inline-script](#abort-current-inline-script),
     * but instead of aborting it starts the debugger.
     *
     * > It is not allowed for prod versions of filter lists.
     *
     * ### Examples
     *
     * ```adblock
     * ! Aborts script when it tries to access `window.alert`
     * example.org#%#//scriptlet('debug-current-inline-script', 'alert')
     * ```
     *
     * @added v1.0.4.
     */
    /* eslint-enable max-len */
    function debugCurrentInlineScript$1(source, property, search) {
      var searchRegexp = toRegExp(search);
      var rid = randomId();
      var getCurrentScript = function getCurrentScript() {
        if ('currentScript' in document) {
          return document.currentScript;
        }
        var scripts = document.getElementsByTagName('script');
        return scripts[scripts.length - 1];
      };
      var ourScript = getCurrentScript();
      var abort = function abort() {
        var scriptEl = getCurrentScript();
        if (!scriptEl) {
          return;
        }
        var content = scriptEl.textContent;

        // We are using Node.prototype.textContent property descriptor
        // to get the real script content
        // even when document.currentScript.textContent is replaced.
        // https://github.com/AdguardTeam/Scriptlets/issues/57#issuecomment-593638991
        try {
          var textContentGetter = Object.getOwnPropertyDescriptor(Node.prototype, 'textContent').get;
          content = textContentGetter.call(scriptEl);
        } catch (e) {} // eslint-disable-line no-empty

        if (scriptEl instanceof HTMLScriptElement && content.length > 0 && scriptEl !== ourScript && searchRegexp.test(content)) {
          hit(source);
          debugger; // eslint-disable-line no-debugger
        }
      };

      var setChainPropAccess = function setChainPropAccess(owner, property) {
        var chainInfo = getPropertyInChain(owner, property);
        var base = chainInfo.base;
        var prop = chainInfo.prop,
          chain = chainInfo.chain;

        // The scriptlet might be executed before the chain property has been created
        // (for instance, document.body before the HTML body was loaded).
        // In this case we're checking whether the base element exists or not
        // and if not, we simply exit without overriding anything.
        // e.g. https://github.com/AdguardTeam/Scriptlets/issues/57#issuecomment-575841092
        if (base instanceof Object === false && base === null) {
          var props = property.split('.');
          var propIndex = props.indexOf(prop);
          var baseName = props[propIndex - 1];
          var message = "The scriptlet had been executed before the ".concat(baseName, " was loaded.");
          logMessage(message, source.verbose);
          return;
        }
        if (chain) {
          var setter = function setter(a) {
            base = a;
            if (a instanceof Object) {
              setChainPropAccess(a, chain);
            }
          };
          Object.defineProperty(owner, prop, {
            get: function get() {
              return base;
            },
            set: setter
          });
          return;
        }
        var currentValue = base[prop];
        setPropertyAccess(base, prop, {
          set: function set(value) {
            abort();
            currentValue = value;
          },
          get: function get() {
            abort();
            return currentValue;
          }
        });
      };
      setChainPropAccess(window, property);
      window.onerror = createOnErrorHandler(rid).bind();
    }
    debugCurrentInlineScript$1.names = ['debug-current-inline-script'];
    debugCurrentInlineScript$1.injections = [randomId, setPropertyAccess, getPropertyInChain, toRegExp, createOnErrorHandler, hit, logMessage, isEmptyObject];

    /* eslint-disable max-len */
    /**
     * @scriptlet remove-attr
     *
     * @description
     * Removes the specified attributes from DOM nodes. This scriptlet runs once when the page loads
     * and after that periodically in order to DOM tree changes by default,
     * or as specified by applying argument.
     *
     * Related UBO scriptlet:
     * https://github.com/gorhill/uBlock/wiki/Resources-Library#remove-attrjs-
     *
     * ### Syntax
     *
     * ```text
     * example.org#%#//scriptlet('remove-attr', attrs[, selector, applying])
     * ```
     *
     * - `attrs` — required, attribute or list of attributes joined by '|'
     * - `selector` — optional, CSS selector, specifies DOM nodes from which the attributes will be removed
     * - `applying` — optional, one or more space-separated flags that describe the way scriptlet apply,
     *   defaults to 'asap stay'; possible flags:
     *     - `asap` — runs as fast as possible **once**
     *     - `complete` — runs **once** after the whole page has been loaded
     *     - `stay` — as fast as possible **and** stays on the page observing possible DOM changes
     *
     * ### Examples
     *
     * 1. Removes by attribute
     *
     *     ```adblock
     *     example.org#%#//scriptlet('remove-attr', 'example|test')
     *     ```
     *
     *     ```html
     *     <!-- before -->
     *     <div example="true" test="true">Some text</div>
     *
     *     <!-- after -->
     *     <div>Some text</div>
     *     ```
     *
     * 1. Removes with specified selector
     *
     *     ```adblock
     *     example.org#%#//scriptlet('remove-attr', 'example', 'div[class="inner"]')
     *     ```
     *
     *     ```html
     *     <!-- before -->
     *     <div class="wrapper" example="true">
     *         <div class="inner" example="true">Some text</div>
     *     </div>
     *
     *     <!-- after -->
     *     <div class="wrapper" example="true">
     *         <div class="inner">Some text</div>
     *     </div>
     *     ```
     *
     * 1. Using flags
     *
     *     ```adblock
     *     example.org#%#//scriptlet('remove-attr', 'example', 'html', 'asap complete')
     *     ```
     *
     * @added v1.0.4.
     */
    /* eslint-enable max-len */
    function removeAttr$1(source, attrs, selector) {
      var applying = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : 'asap stay';
      if (!attrs) {
        return;
      }
      attrs = attrs.split(/\s*\|\s*/);
      if (!selector) {
        selector = "[".concat(attrs.join('],['), "]");
      }
      var rmattr = function rmattr() {
        var nodes = [];
        try {
          nodes = [].slice.call(document.querySelectorAll(selector));
        } catch (e) {
          logMessage(source, "Invalid selector arg: '".concat(selector, "'"));
        }
        var removed = false;
        nodes.forEach(function (node) {
          attrs.forEach(function (attr) {
            node.removeAttribute(attr);
            removed = true;
          });
        });
        if (removed) {
          hit(source);
        }
      };
      var flags = parseFlags(applying);
      var run = function run() {
        rmattr();
        if (!flags.hasFlag(flags.STAY)) {
          return;
        }
        // 'true' for observing attributes
        observeDOMChanges(rmattr, true);
      };
      if (flags.hasFlag(flags.ASAP)) {
        // https://github.com/AdguardTeam/Scriptlets/issues/245
        // Call rmattr on DOM content loaded
        // to ensure that target node is present on the page
        if (document.readyState === 'loading') {
          window.addEventListener('DOMContentLoaded', rmattr, {
            once: true
          });
        } else {
          rmattr();
        }
      }
      if (document.readyState !== 'complete' && flags.hasFlag(flags.COMPLETE)) {
        window.addEventListener('load', run, {
          once: true
        });
      } else if (flags.hasFlag(flags.STAY)) {
        // Only call rmattr for single 'stay' flag
        if (!applying.includes(' ')) {
          rmattr();
        }
        // 'true' for observing attributes
        observeDOMChanges(rmattr, true);
      }
    }
    removeAttr$1.names = ['remove-attr',
    // aliases are needed for matching the related scriptlet converted into our syntax
    'remove-attr.js', 'ubo-remove-attr.js', 'ra.js', 'ubo-ra.js', 'ubo-remove-attr', 'ubo-ra'];
    removeAttr$1.injections = [hit, observeDOMChanges, parseFlags, logMessage,
    // following helpers should be imported and injected
    // because they are used by helpers above
    throttle];

    /* eslint-disable max-len */
    /**
     * @scriptlet set-attr
     *
     * @description
     * Sets attribute with permitted value on the specified elements. This scriptlet runs once when the page loads
     * and after that on DOM tree changes.
     *
     * Related UBO scriptlet:
     * https://github.com/gorhill/uBlock/wiki/Resources-Library#set-attrjs-
     *
     * ### Syntax
     *
     * ```text
     * example.org#%#//scriptlet('set-attr', selector, attr[, value])
     * ```
     *
     * - `selector` — required, CSS selector, specifies DOM nodes to set attributes on
     * - `attr` — required, attribute to be set
     * - `value` — optional, the value to assign to the attribute, defaults to ''. Possible values:
     *     - `''` — empty string
     *     - positive decimal integer `<= 32767`
     *     - `true` / `false` in any case variation
     *     - `[attribute-name]` copy the value from attribute `attribute-name` on the same element.
     *
     * ### Examples
     *
     * 1. Set attribute by selector
     *
     *     ```adblock
     *     example.org#%#//scriptlet('set-attr', 'div.class > a.class', 'test-attribute', '0')
     *     ```
     *
     *     ```html
     *     <!-- before -->
     *     <div>
     *         <a>Another text</a>
     *         <a class="class">Some text</a>
     *     </div>
     *
     *     <!-- after -->
     *     <div>
     *         <a>Another text</a>
     *         <a class="class" test-attribute="0">Some text</a>
     *     </div>
     *     ```
     *
     * 1. Set attribute without value
     *
     *     ```adblock
     *     example.org#%#//scriptlet('set-attr', 'a.class', 'test-attribute')
     *     ```
     *
     *     ```html
     *     <!-- before -->
     *     <a class="class">Some text</div>
     *
     *     <!-- after -->
     *     <a class="class" test-attribute>Some text</div>
     *     ```
     *
     * 1. Set attribute value to `TRUE`
     *
     *     ```adblock
     *     example.org#%#//scriptlet('set-attr', 'a.class', 'test-attribute', 'TRUE')
     *     ```
     *
     *     ```html
     *     <!-- before -->
     *     <a class="class">Some text</div>
     *
     *     <!-- after -->
     *     <a class="class" test-attribute="TRUE">Some text</div>
     *     ```
     *
     * 1. Set attribute value to `fAlse`
     *
     *     ```adblock
     *     example.org#%#//scriptlet('set-attr', 'a.class', 'test-attribute', 'fAlse')
     *     ```
     *
     *     ```html
     *     <!-- before -->
     *     <a class="class">Some text</div>
     *
     *     <!-- after -->
     *     <a class="class" test-attribute="fAlse">Some text</div>
     *     ```
     *
     * 1. Copy attribute value from the target element
     *
     *     ```adblock
     *     example.org#%#//scriptlet('set-attr', 'iframe[data-cur]', 'href', '[data-cur]')
     *     ```
     *
     *     ```html
     *     <!-- before -->
     *     <iframe data-cur="good-url.com" href="bad-url.org"></iframe>
     *
     *     <!-- after -->
     *     <iframe data-cur="good-url.com" href="good-url.com"></iframe>
     *     ```
     *
     * @added v1.5.0.
     */
    /* eslint-enable max-len */
    function setAttr$1(source, selector, attr) {
      var value = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : '';
      if (!selector || !attr) {
        return;
      }
      var allowedValues = ['true', 'false'];
      var shouldCopyValue = value.startsWith('[') && value.endsWith(']');
      var isValidValue = value.length === 0 || !nativeIsNaN(parseInt(value, 10)) && parseInt(value, 10) >= 0 && parseInt(value, 10) <= 32767 || allowedValues.includes(value.toLowerCase());
      if (!shouldCopyValue && !isValidValue) {
        logMessage(source, "Invalid attribute value provided: '".concat(convertTypeToString(value), "'"));
        return;
      }

      /**
       * Defining value extraction logic here allows us to remove
       * excessive `shouldCopyValue` checks in observer callback.
       * Setting plain value is a default behavior.
       */
      var attributeHandler;
      if (shouldCopyValue) {
        attributeHandler = function attributeHandler(elem, attr, value) {
          var valueToCopy = elem.getAttribute(value.slice(1, -1));
          if (valueToCopy === null) {
            logMessage(source, "No element attribute found to copy value from: ".concat(value));
          }
          elem.setAttribute(attr, valueToCopy);
        };
      }
      setAttributeBySelector(source, selector, attr, value, attributeHandler);
      observeDOMChanges(function () {
        return setAttributeBySelector(source, selector, attr, value, attributeHandler);
      }, true);
    }
    setAttr$1.names = ['set-attr',
    // aliases are needed for matching the related scriptlet converted into our syntax
    'set-attr.js', 'ubo-set-attr.js', 'ubo-set-attr'];
    setAttr$1.injections = [setAttributeBySelector, observeDOMChanges, nativeIsNaN, convertTypeToString,
    // following helpers should be imported and injected
    // because they are used by helpers above
    defaultAttributeSetter, logMessage, throttle, hit];

    /* eslint-disable max-len */
    /**
     * @scriptlet remove-class
     *
     * @description
     * Removes the specified classes from DOM nodes. This scriptlet runs once after the page loads
     * and after that periodically in order to DOM tree changes.
     *
     * Related UBO scriptlet:
     * https://github.com/gorhill/uBlock/wiki/Resources-Library#remove-classjs-
     *
     * ### Syntax
     *
     * ```text
     * example.org#%#//scriptlet('remove-class', classes[, selector, applying])
     * ```
     *
     * - `classes` — required, class or list of classes separated by '|'
     * - `selector` — optional, CSS selector, specifies DOM nodes from which the classes will be removed.
     *   If there is no `selector`, each class of `classes` independently will be removed from all nodes which has one
     * - `applying` — optional, one or more space-separated flags that describe the way scriptlet apply,
     *   defaults to 'asap stay'; possible flags:
     *     - `asap` — runs as fast as possible **once**
     *     - `complete` — runs **once** after the whole page has been loaded
     *     - `stay` — as fast as possible **and** stays on the page observing possible DOM changes
     *
     * ### Examples
     *
     * 1. Removes by classes
     *
     *     ```adblock
     *     example.org#%#//scriptlet('remove-class', 'example|test')
     *     ```
     *
     *     ```html
     *     <!-- before -->
     *     <div id="first" class="nice test">Some text</div>
     *     <div id="second" class="rare example for test">Some text</div>
     *     <div id="third" class="testing better example">Some text</div>
     *
     *     <!-- after -->
     *     <div id="first" class="nice">Some text</div>
     *     <div id="second" class="rare for">Some text</div>
     *     <div id="third" class="testing better">Some text</div>
     *     ```
     *
     * 1. Removes with specified selector
     *
     *     ```adblock
     *     example.org#%#//scriptlet('remove-class', 'branding', 'div[class^="inner"]')
     *     ```
     *
     *     ```html
     *     <!-- before -->
     *     <div class="wrapper true branding">
     *         <div class="inner bad branding">Some text</div>
     *     </div>
     *
     *     <!-- after -->
     *     <div class="wrapper true branding">
     *         <div class="inner bad">Some text</div>
     *     </div>
     *     ```
     *
     * 1. Using flags
     *
     *     ```adblock
     *     example.org#%#//scriptlet('remove-class', 'branding', 'div[class^="inner"]', 'asap complete')
     *     ```
     *
     * @added v1.1.1.
     */
    /* eslint-enable max-len */

    function removeClass$1(source, classNames, selector) {
      var applying = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : 'asap stay';
      if (!classNames) {
        return;
      }
      classNames = classNames.split(/\s*\|\s*/);
      var selectors = [];
      if (!selector) {
        selectors = classNames.map(function (className) {
          return ".".concat(className);
        });
      }
      var removeClassHandler = function removeClassHandler() {
        var nodes = new Set();
        if (selector) {
          var foundNodes = [];
          try {
            foundNodes = [].slice.call(document.querySelectorAll(selector));
          } catch (e) {
            logMessage(source, "Invalid selector arg: '".concat(selector, "'"));
          }
          foundNodes.forEach(function (n) {
            return nodes.add(n);
          });
        } else if (selectors.length > 0) {
          selectors.forEach(function (s) {
            var elements = document.querySelectorAll(s);
            for (var i = 0; i < elements.length; i += 1) {
              var element = elements[i];
              nodes.add(element);
            }
          });
        }
        var removed = false;
        nodes.forEach(function (node) {
          classNames.forEach(function (className) {
            if (node.classList.contains(className)) {
              node.classList.remove(className);
              removed = true;
            }
          });
        });
        if (removed) {
          hit(source);
        }
      };
      var CLASS_ATTR_NAME = ['class'];
      var flags = parseFlags(applying);
      var run = function run() {
        removeClassHandler();
        if (!flags.hasFlag(flags.STAY)) {
          return;
        }
        // 'true' for observing attributes
        // 'class' for observing only classes
        observeDOMChanges(removeClassHandler, true, CLASS_ATTR_NAME);
      };
      if (flags.hasFlag(flags.ASAP)) {
        // https://github.com/AdguardTeam/Scriptlets/issues/245
        // Call removeClassHandler on DOM content loaded
        // to ensure that target node is present on the page
        if (document.readyState === 'loading') {
          window.addEventListener('DOMContentLoaded', removeClassHandler, {
            once: true
          });
        } else {
          removeClassHandler();
        }
      }
      if (document.readyState !== 'complete' && flags.hasFlag(flags.COMPLETE)) {
        window.addEventListener('load', run, {
          once: true
        });
      } else if (flags.hasFlag(flags.STAY)) {
        // Only call removeClassHandler for single 'stay' flag
        if (!applying.includes(' ')) {
          removeClassHandler();
        }
        observeDOMChanges(removeClassHandler, true, CLASS_ATTR_NAME);
      }
    }
    removeClass$1.names = ['remove-class',
    // aliases are needed for matching the related scriptlet converted into our syntax
    'remove-class.js', 'ubo-remove-class.js', 'rc.js', 'ubo-rc.js', 'ubo-remove-class', 'ubo-rc'];
    removeClass$1.injections = [hit, logMessage, observeDOMChanges, parseFlags,
    // following helpers should be imported and injected
    // because they are used by helpers above
    throttle];

    /**
     * @scriptlet disable-newtab-links
     *
     * @description
     * Prevents opening new tabs and windows if there is `target` attribute in element.
     *
     * Related UBO scriptlet:
     * https://github.com/gorhill/uBlock/wiki/Resources-Library#disable-newtab-linksjs-
     *
     * ### Syntax
     *
     * ```adblock
     * example.org#%#//scriptlet('disable-newtab-links')
     * ```
     *
     * @added v1.0.4.
     */
    function disableNewtabLinks$1(source) {
      document.addEventListener('click', function (ev) {
        var target = ev.target;
        while (target !== null) {
          if (target.localName === 'a' && target.hasAttribute('target')) {
            ev.stopPropagation();
            ev.preventDefault();
            hit(source);
            break;
          }
          target = target.parentNode;
        }
      });
    }
    disableNewtabLinks$1.names = ['disable-newtab-links',
    // aliases are needed for matching the related scriptlet converted into our syntax
    'disable-newtab-links.js', 'ubo-disable-newtab-links.js', 'ubo-disable-newtab-links'];
    disableNewtabLinks$1.injections = [hit];

    /* eslint-disable max-len */
    /**
     * @scriptlet adjust-setInterval
     *
     * @description
     * Adjusts delay for specified setInterval() callbacks.
     *
     * Related UBO scriptlet:
     * https://github.com/gorhill/uBlock/wiki/Resources-Library#nano-setinterval-boosterjs-
     *
     * ### Syntax
     *
     * ```text
     * example.org#%#//scriptlet('adjust-setInterval'[, matchCallback [, matchDelay[, boost]]])
     * ```
     *
     * - `matchCallback` — optional, string or regular expression for stringified callback matching;
     *   defaults to match all callbacks; invalid regular expression will cause exit and rule will not work
     * - `matchDelay` — optional, defaults to 1000, matching setInterval delay; decimal integer OR '*' for any delay
     * - `boost` — optional, default to 0.05, float,
     *   capped at 1000 times for up and 50 for down (0.001...50), setInterval delay multiplier
     *
     * ### Examples
     *
     * 1. Adjust all setInterval() x20 times where delay equal 1000ms
     *
     *     ```adblock
     *     example.org#%#//scriptlet('adjust-setInterval')
     *     ```
     *
     * 1. Adjust all setInterval() x20 times where callback matched with `example` and delay equal 1000ms
     *
     *     ```adblock
     *     example.org#%#//scriptlet('adjust-setInterval', 'example')
     *     ```
     *
     * 1. Adjust all setInterval() x20 times where callback matched with `example` and delay equal 400ms
     *
     *     ```adblock
     *     example.org#%#//scriptlet('adjust-setInterval', 'example', '400')
     *     ```
     *
     * 1. Slow down setInterval() x2 times where callback matched with `example` and delay equal 1000ms
     *
     *     ```adblock
     *     example.org#%#//scriptlet('adjust-setInterval', 'example', '', '2')
     *     ```
     *
     * 1. Adjust all setInterval() x50 times where delay equal 2000ms
     *
     *     ```adblock
     *     example.org#%#//scriptlet('adjust-setInterval', '', '2000', '0.02')
     *     ```
     *
     * 1. Adjust all setInterval() x1000 times where delay equal 2000ms
     *
     *     ```adblock
     *     example.org#%#//scriptlet('adjust-setInterval', '', '2000', '0.001')
     *     ```
     *
     * 1. Adjust all setInterval() x50 times where delay is randomized
     *
     *     ```adblock
     *     example.org#%#//scriptlet('adjust-setInterval', '', '*', '0.02')
     *     ```
     *
     * @added v1.0.4.
     */
    /* eslint-enable max-len */
    function adjustSetInterval$1(source, matchCallback, matchDelay, boost) {
      var nativeSetInterval = window.setInterval;
      var matchRegexp = toRegExp(matchCallback);
      var intervalWrapper = function intervalWrapper(callback, delay) {
        // https://github.com/AdguardTeam/Scriptlets/issues/221
        if (!isValidCallback(callback)) {
          // eslint-disable-next-line max-len
          var message = "Scriptlet can't be applied because of invalid callback: '".concat(String(callback), "'");
          logMessage(source, message);
        } else if (matchRegexp.test(callback.toString()) && isDelayMatched(matchDelay, delay)) {
          delay *= getBoostMultiplier(boost);
          hit(source);
        }
        for (var _len = arguments.length, args = new Array(_len > 2 ? _len - 2 : 0), _key = 2; _key < _len; _key++) {
          args[_key - 2] = arguments[_key];
        }
        return nativeSetInterval.apply(window, [callback, delay, ...args]);
      };
      window.setInterval = intervalWrapper;
    }
    adjustSetInterval$1.names = ['adjust-setInterval',
    // aliases are needed for matching the related scriptlet converted into our syntax
    'nano-setInterval-booster.js', 'ubo-nano-setInterval-booster.js', 'nano-sib.js', 'ubo-nano-sib.js', 'adjust-setInterval.js', 'ubo-adjust-setInterval.js', 'ubo-nano-setInterval-booster', 'ubo-nano-sib', 'ubo-adjust-setInterval'];
    adjustSetInterval$1.injections = [hit, isValidCallback, toRegExp, getBoostMultiplier, isDelayMatched, logMessage,
    // following helpers should be injected as helpers above use them
    nativeIsNaN, nativeIsFinite, getMatchDelay, shouldMatchAnyDelay];

    /* eslint-disable max-len */
    /**
     * @scriptlet adjust-setTimeout
     *
     * @description
     * Adjusts delay for specified setTimeout() callbacks.
     *
     * Related UBO scriptlet:
     * https://github.com/gorhill/uBlock/wiki/Resources-Library#nano-settimeout-boosterjs-
     *
     * ### Syntax
     *
     * ```text
     * example.org#%#//scriptlet('adjust-setTimeout'[, matchCallback [, matchDelay[, boost]]])
     * ```
     *
     * - `matchCallback` — optional, string or regular expression for stringified callback matching;
     *   defaults to match all callbacks; invalid regular expression will cause exit and rule will not work
     * - `matchDelay` — optional, defaults to 1000, matching setTimeout delay; decimal integer OR '*' for any delay
     * - `boost` — optional, default to 0.05, float,
     *   capped at 1000 times for up and 50 for down (0.001...50), setTimeout delay multiplier
     *
     * ### Examples
     *
     * 1. Adjust all setTimeout() x20 times where timeout equal 1000ms
     *
     *     ```adblock
     *     example.org#%#//scriptlet('adjust-setTimeout')
     *     ```
     *
     * 1. Adjust all setTimeout() x20 times where callback matched with `example` and timeout equal 1000ms
     *
     *     ```adblock
     *     example.org#%#//scriptlet('adjust-setTimeout', 'example')
     *     ```
     *
     * 1. Adjust all setTimeout() x20 times where callback matched with `example` and timeout equal 400ms
     *
     *     ```adblock
     *     example.org#%#//scriptlet('adjust-setTimeout', 'example', '400')
     *     ```
     *
     * 1. Slow down setTimeout() x2 times where callback matched with `example` and timeout equal 1000ms
     *
     *     ```adblock
     *     example.org#%#//scriptlet('adjust-setTimeout', 'example', '', '2')
     *     ```
     *
     * 1. Adjust all setTimeout() x50 times where timeout equal 2000ms
     *
     *     ```adblock
     *     example.org#%#//scriptlet('adjust-setTimeout', '', '2000', '0.02')
     *     ```
     *
     * 1. Adjust all setTimeout() x1000 times where timeout equal 2000ms
     *
     *     ```adblock
     *     example.org#%#//scriptlet('adjust-setTimeout', '', '2000', '0.001')
     *     ```
     *
     * 1. Adjust all setTimeout() x20 times where callback matched with `test` and timeout is randomized
     *
     *     ```adblock
     *     example.org#%#//scriptlet('adjust-setTimeout', 'test', '*')
     *     ```
     *
     * @added v1.0.4.
     */
    /* eslint-enable max-len */
    function adjustSetTimeout$1(source, matchCallback, matchDelay, boost) {
      var nativeSetTimeout = window.setTimeout;
      var matchRegexp = toRegExp(matchCallback);
      var timeoutWrapper = function timeoutWrapper(callback, delay) {
        // https://github.com/AdguardTeam/Scriptlets/issues/221
        if (!isValidCallback(callback)) {
          // eslint-disable-next-line max-len
          var message = "Scriptlet can't be applied because of invalid callback: '".concat(String(callback), "'");
          logMessage(source, message);
        } else if (matchRegexp.test(callback.toString()) && isDelayMatched(matchDelay, delay)) {
          delay *= getBoostMultiplier(boost);
          hit(source);
        }
        for (var _len = arguments.length, args = new Array(_len > 2 ? _len - 2 : 0), _key = 2; _key < _len; _key++) {
          args[_key - 2] = arguments[_key];
        }
        return nativeSetTimeout.apply(window, [callback, delay, ...args]);
      };
      window.setTimeout = timeoutWrapper;
    }
    adjustSetTimeout$1.names = ['adjust-setTimeout',
    // aliases are needed for matching the related scriptlet converted into our syntax
    'adjust-setTimeout.js', 'ubo-adjust-setTimeout.js', 'nano-setTimeout-booster.js', 'ubo-nano-setTimeout-booster.js', 'nano-stb.js', 'ubo-nano-stb.js', 'ubo-adjust-setTimeout', 'ubo-nano-setTimeout-booster', 'ubo-nano-stb'];
    adjustSetTimeout$1.injections = [hit, isValidCallback, toRegExp, getBoostMultiplier, isDelayMatched, logMessage,
    // following helpers should be injected as helpers above use them
    nativeIsNaN, nativeIsFinite, getMatchDelay, shouldMatchAnyDelay];

    /* eslint-disable max-len */
    /**
     * @scriptlet dir-string
     *
     * @description
     * Wraps the `console.dir` API to call the `toString` method of the argument.
     * There are several adblock circumvention systems that detect browser devtools
     * and hide themselves. Therefore, if we force them to think
     * that devtools are open (using this scriptlet),
     * it will automatically disable the adblock circumvention script.
     *
     * ### Syntax
     *
     * ```text
     * example.org#%#//scriptlet('dir-string'[, times])
     * ```
     *
     * - `times` — optional, the number of times to call the `toString` method of the argument to `console.dir`
     *
     * ### Examples
     *
     * ```adblock
     * ! Run 2 times
     * example.org#%#//scriptlet('dir-string', '2')
     * ```
     *
     * @added v1.0.4.
     */
    /* eslint-enable max-len */
    function dirString$1(source, times) {
      var _console = console,
        dir = _console.dir;
      function dirWrapper(object) {
        if (typeof dir === 'function') {
          dir.call(this, object);
        }
        hit(source);
      }
      // eslint-disable-next-line no-console
      console.dir = dirWrapper;
    }
    dirString$1.names = ['dir-string'];
    dirString$1.injections = [hit];

    /* eslint-disable max-len */
    /**
     * @scriptlet json-prune
     *
     * @description
     * Removes specified properties from the result of calling JSON.parse and returns the caller.
     *
     * Related UBO scriptlet:
     * https://github.com/gorhill/uBlock/wiki/Resources-Library#json-prunejs-
     *
     * Related ABP source:
     * https://gitlab.com/eyeo/snippets/-/blob/main/source/behavioral/json-prune.js
     *
     * ### Syntax
     *
     * ```text
     * example.org#%#//scriptlet('json-prune'[, propsToRemove [, obligatoryProps [, stack]]])
     * ```
     *
     * - `propsToRemove` — optional, string of space-separated properties to remove
     * - `obligatoryProps` — optional, string of space-separated properties
     *   which must be all present for the pruning to occur
     * - `stack` — optional, string or regular expression that must match the current function call stack trace;
     *   if regular expression is invalid it will be skipped
     *
     * > Note please that you can use wildcard `*` for chain property name,
     * > e.g. `ad.*.src` instead of `ad.0.src ad.1.src ad.2.src`.
     *
     * ### Examples
     *
     * 1. Removes property `example` from the results of JSON.parse call
     *
     *     ```adblock
     *     example.org#%#//scriptlet('json-prune', 'example')
     *     ```
     *
     *     For instance, the following call will return `{ one: 1}`
     *
     *     ```html
     *     JSON.parse('{"one":1,"example":true}')
     *     ```
     *
     * 1. If there are no specified properties in the result of JSON.parse call, pruning will NOT occur
     *
     *     ```adblock
     *     example.org#%#//scriptlet('json-prune', 'one', 'obligatoryProp')
     *     ```
     *
     *     For instance, the following call will return `{ one: 1, two: 2}`
     *
     *     ```html
     *     JSON.parse('{"one":1,"two":2}')
     *     ```
     *
     * 1. A property in a list of properties can be a chain of properties
     *
     *     ```adblock
     *     example.org#%#//scriptlet('json-prune', 'a.b', 'ads.url.first')
     *     ```
     *
     * 1. Removes property `content.ad` from the results of JSON.parse call if its error stack trace contains `test.js`
     *
     *     ```adblock
     *     example.org#%#//scriptlet('json-prune', 'content.ad', '', 'test.js')
     *     ```
     *
     * 1. A property in a list of properties can be a chain of properties with wildcard in it
     *
     *     ```adblock
     *     example.org#%#//scriptlet('json-prune', 'content.*.media.src', 'content.*.media.ad')
     *     ```
     *
     * 1. Call with no arguments will log the current hostname and json payload at the console
     *
     *     ```adblock
     *     example.org#%#//scriptlet('json-prune')
     *     ```
     *
     * 1. Call with only second argument will log the current hostname and matched json payload at the console
     *
     *     ```adblock
     *     example.org#%#//scriptlet('json-prune', '', '"id":"117458"')
     *     ```
     *
     * @added v1.1.0.
     */
    /* eslint-enable max-len */
    function jsonPrune$1(source, propsToRemove, requiredInitialProps) {
      var stack = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : '';
      var prunePaths = getPrunePath(propsToRemove);
      var requiredPaths = getPrunePath(requiredInitialProps);
      var nativeObjects = {
        nativeStringify: window.JSON.stringify
      };
      var nativeJSONParse = JSON.parse;
      var jsonParseWrapper = function jsonParseWrapper() {
        for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
          args[_key] = arguments[_key];
        }
        // dealing with stringified json in args, which should be parsed.
        // so we call nativeJSONParse as JSON.parse which is bound to JSON object
        var root = nativeJSONParse.apply(JSON, args);
        return jsonPruner(source, root, prunePaths, requiredPaths, stack, nativeObjects);
      };

      // JSON.parse mocking
      jsonParseWrapper.toString = nativeJSONParse.toString.bind(nativeJSONParse);
      JSON.parse = jsonParseWrapper;
      var nativeResponseJson = Response.prototype.json;
      // eslint-disable-next-line func-names
      var responseJsonWrapper = function responseJsonWrapper() {
        var promise = nativeResponseJson.apply(this);
        return promise.then(function (obj) {
          return jsonPruner(source, obj, prunePaths, requiredPaths, stack, nativeObjects);
        });
      };

      // do nothing if browser does not support Response (e.g. Internet Explorer)
      // https://developer.mozilla.org/en-US/docs/Web/API/Response
      if (typeof Response === 'undefined') {
        return;
      }
      Response.prototype.json = responseJsonWrapper;
    }
    jsonPrune$1.names = ['json-prune',
    // aliases are needed for matching the related scriptlet converted into our syntax
    'json-prune.js', 'ubo-json-prune.js', 'ubo-json-prune', 'abp-json-prune'];
    jsonPrune$1.injections = [hit, matchStackTrace, getWildcardPropertyInChain, logMessage, isPruningNeeded, jsonPruner, getPrunePath,
    // following helpers are needed for helpers above
    toRegExp, getNativeRegexpTest, shouldAbortInlineOrInjectedScript, backupRegExpValues, restoreRegExpValues];

    /* eslint-disable max-len */
    /**
     * @scriptlet prevent-requestAnimationFrame
     *
     * @description
     * Prevents a `requestAnimationFrame` call
     * if the text of the callback is matching the specified search string which does not start with `!`;
     * otherwise mismatched calls should be defused.
     *
     * Related UBO scriptlet:
     * https://github.com/gorhill/uBlock/wiki/Resources-Library#no-requestanimationframe-ifjs-
     *
     * ### Syntax
     *
     * ```text
     * example.org#%#//scriptlet('prevent-requestAnimationFrame'[, search])
     * ```
     *
     * - `search` — optional, string or regular expression;
     *   invalid regular expression will be skipped and all callbacks will be matched.
     *   If starts with `!`, scriptlet will not match the stringified callback but all other will be defused.
     *   If do not start with `!`, the stringified callback will be matched.
     *
     * > Call with no argument will log all requestAnimationFrame calls,
     * > it may be useful for debugging but it is not allowed for prod versions of filter lists.
     *
     * ### Examples
     *
     * 1. Prevents `requestAnimationFrame` calls if the callback matches `/\.test/`
     *
     *     ```adblock
     *     example.org#%#//scriptlet('prevent-requestAnimationFrame', '/\.test/')
     *     ```
     *
     *     For instance, the following call will be prevented:
     *
     *     ```javascript
     *     var times = 0;
     *     requestAnimationFrame(function change() {
     *         window.test = 'new value';
     *         if (times < 2) {
     *             times += 1;
     *             requestAnimationFrame(change);
     *         }
     *     });
     *     ```
     *
     * 1. Prevents `requestAnimationFrame` calls if **does not match** 'check'
     *
     *     ```adblock
     *     example.org#%#//scriptlet('prevent-requestAnimationFrame', '!check')
     *     ```
     *
     *     For instance, only the first call will be prevented:
     *
     *     ```javascript
     *     var timesFirst = 0;
     *     requestAnimationFrame(function changeFirst() {
     *         window.check = 'should not be prevented';
     *         if (timesFirst < 2) {
     *             timesFirst += 1;
     *             requestAnimationFrame(changeFirst);
     *         }
     *     });
     *
     *     var timesSecond = 0;
     *     requestAnimationFrame(function changeSecond() {
     *         window.second = 'should be prevented';
     *         if (timesSecond < 2) {
     *             timesSecond += 1;
     *             requestAnimationFrame(changeSecond);
     *         }
     *     });
     *     ```
     *
     * @added v1.1.15.
     */
    /* eslint-enable max-len */

    function preventRequestAnimationFrame$1(source, match) {
      var nativeRequestAnimationFrame = window.requestAnimationFrame;

      // logs requestAnimationFrame to console if no arguments have been specified
      var shouldLog = typeof match === 'undefined';
      var _parseMatchArg = parseMatchArg(match),
        isInvertedMatch = _parseMatchArg.isInvertedMatch,
        matchRegexp = _parseMatchArg.matchRegexp;
      var rafWrapper = function rafWrapper(callback) {
        var shouldPrevent = false;
        if (shouldLog) {
          hit(source);
          logMessage(source, "requestAnimationFrame(".concat(String(callback), ")"), true);
        } else if (isValidCallback(callback) && isValidStrPattern(match)) {
          shouldPrevent = matchRegexp.test(callback.toString()) !== isInvertedMatch;
        }
        if (shouldPrevent) {
          hit(source);
          return nativeRequestAnimationFrame(noopFunc);
        }
        for (var _len = arguments.length, args = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
          args[_key - 1] = arguments[_key];
        }
        return nativeRequestAnimationFrame.apply(window, [callback, ...args]);
      };
      window.requestAnimationFrame = rafWrapper;
    }
    preventRequestAnimationFrame$1.names = ['prevent-requestAnimationFrame',
    // aliases are needed for matching the related scriptlet converted into our syntax
    'no-requestAnimationFrame-if.js', 'ubo-no-requestAnimationFrame-if.js', 'norafif.js', 'ubo-norafif.js', 'ubo-no-requestAnimationFrame-if', 'ubo-norafif'];
    preventRequestAnimationFrame$1.injections = [hit, noopFunc, parseMatchArg, isValidStrPattern, isValidCallback, logMessage,
    // following helpers should be injected as helpers above use them
    escapeRegExp, toRegExp];

    /* eslint-disable max-len */
    /**
     * @scriptlet set-cookie
     *
     * @description
     * Sets a cookie with the specified name, value, path, and domain.
     *
     * Related UBO scriptlet:
     * https://github.com/gorhill/uBlock/wiki/Resources-Library#set-cookiejs-
     *
     * ### Syntax
     *
     * ```text
     * example.org#%#//scriptlet('set-cookie', name, value[, path[, domain]])
     * ```
     *
     * - `name` — required, cookie name to be set
     * - `value` — required, cookie value; possible values:
     *     - positive decimal integer `<= 32767`
     *     - one of the predefined constants in any case variation:
     *         - `true` / `t`
     *         - `false` / `f`
     *         - `yes` / `y`
     *         - `no` / `n`
     *         - `ok`
     *         - `on` / `off`
     *         - `accept`/ `accepted` / `notaccepted`
     *         - `reject` / `rejected`
     *         - `allow` / `allowed`
     *         - `disallow` / `deny`
     *         - `enable` / `enabled`
     *         - `disable` / `disabled`
     *         - `necessary` / `required`
     *         - `hide` / `hidden`
     *         - `essential` / `nonessential`
     *         - `checked` / `unchecked`
     * - `path` — optional, cookie path, defaults to `/`; possible values:
     *     - `/` — root path
     *     - `none` — to set no path at all
     * - `domain` — optional, cookie domain, if not set origin will be set as domain,
     *              if the domain does not match the origin, the cookie will not be set
     *
     * > Note that the scriptlet does not encode a cookie name,
     * > e.g. name 'a:b' will be set as 'a:b' and not as 'a%3Ab'.
     * >
     * > Also if a cookie name includes `;`, the cookie will not be set since this may cause the cookie to break.
     *
     * ### Examples
     *
     * ```adblock
     * example.org#%#//scriptlet('set-cookie', 'CookieConsent', '1')
     *
     * example.org#%#//scriptlet('set-cookie', 'gdpr-settings-cookie', 'true')
     *
     * example.org#%#//scriptlet('set-cookie', 'cookie_consent', 'ok', 'none')
     *
     * example.org#%#//scriptlet('set-cookie-reload', 'test', '1', 'none', 'example.org')
     * ```
     *
     * @added v1.2.3.
     */
    /* eslint-enable max-len */
    function setCookie$1(source, name, value) {
      var path = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : '/';
      var domain = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : '';
      var validValue = getLimitedCookieValue(value);
      if (validValue === null) {
        logMessage(source, "Invalid cookie value: '".concat(validValue, "'"));
        return;
      }
      if (!isValidCookiePath(path)) {
        logMessage(source, "Invalid cookie path: '".concat(path, "'"));
        return;
      }
      if (!document.location.origin.includes(domain)) {
        logMessage(source, "Cookie domain not matched by origin: '".concat(domain, "'"));
        return;
      }
      var cookieToSet = serializeCookie(name, validValue, path, domain);
      if (!cookieToSet) {
        logMessage(source, 'Invalid cookie name or value');
        return;
      }
      hit(source);
      document.cookie = cookieToSet;
    }
    setCookie$1.names = ['set-cookie',
    // aliases are needed for matching the related scriptlet converted into our syntax
    'set-cookie.js', 'ubo-set-cookie.js', 'ubo-set-cookie'];
    setCookie$1.injections = [hit, logMessage, nativeIsNaN, isCookieSetWithValue, getLimitedCookieValue, serializeCookie, isValidCookiePath, getCookiePath];

    /**
     * @scriptlet set-cookie-reload
     *
     * @description
     * Sets a cookie with the specified name and value, path, and domain,
     * and reloads the current page after the cookie setting.
     * If reloading option is not needed, use [set-cookie](#set-cookie) scriptlet.
     *
     * ### Syntax
     *
     * ```text
     * example.org#%#//scriptlet('set-cookie-reload', name, value[, path[, domain]])
     * ```
     *
     * - `name` — required, cookie name to be set
     * - `value` — required, cookie value; possible values:
     *     - positive decimal integer `<= 32767`
     *     - one of the predefined constants in any case variation:
     *         - `true` / `t`
     *         - `false` / `f`
     *         - `yes` / `y`
     *         - `no` / `n`
     *         - `ok`
     *         - `on` / `off`
     *         - `accept`/ `accepted` / `notaccepted`
     *         - `reject` / `rejected`
     *         - `allow` / `allowed`
     *         - `disallow` / `deny`
     *         - `enable` / `enabled`
     *         - `disable` / `disabled`
     *         - `necessary` / `required`
     *         - `hide` / `hidden`
     *         - `essential` / `nonessential`
     *         - `checked` / `unchecked`
     * - `path` — optional, cookie path, defaults to `/`; possible values:
     *     - `/` — root path
     *     - `none` — to set no path at all
     * - `domain` — optional, cookie domain, if not set origin will be set as domain,
     *              if the domain does not match the origin, the cookie will not be set
     *
     * > Note that the scriptlet does not encode a cookie name,
     * > e.g. name 'a:b' will be set as 'a:b' and not as 'a%3Ab'.
     * >
     * > Also if a cookie name includes `;`, the cookie will not be set since this may cause the cookie to break.
     *
     * ### Examples
     *
     * ```adblock
     * example.org#%#//scriptlet('set-cookie-reload', 'checking', 'ok')
     *
     * example.org#%#//scriptlet('set-cookie-reload', 'gdpr-settings-cookie', '1')
     *
     * example.org#%#//scriptlet('set-cookie-reload', 'cookie-set', 'true', 'none')
     *
     * example.org#%#//scriptlet('set-cookie-reload', 'test', '1', 'none', 'example.org')
     * ```
     *
     * @added v1.3.14.
     */
    function setCookieReload$1(source, name, value) {
      var path = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : '/';
      var domain = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : '';
      if (isCookieSetWithValue(document.cookie, name, value)) {
        return;
      }
      var validValue = getLimitedCookieValue(value);
      if (validValue === null) {
        logMessage(source, "Invalid cookie value: '".concat(value, "'"));
        return;
      }
      if (!isValidCookiePath(path)) {
        logMessage(source, "Invalid cookie path: '".concat(path, "'"));
        return;
      }
      if (!document.location.origin.includes(domain)) {
        logMessage(source, "Cookie domain not matched by origin: '".concat(domain, "'"));
        return;
      }
      var cookieToSet = serializeCookie(name, validValue, path, domain);
      if (!cookieToSet) {
        logMessage(source, 'Invalid cookie name or value');
        return;
      }
      document.cookie = cookieToSet;
      hit(source);

      // Only reload the page if cookie was set
      // https://github.com/AdguardTeam/Scriptlets/issues/212
      if (isCookieSetWithValue(document.cookie, name, value)) {
        window.location.reload();
      }
    }
    setCookieReload$1.names = ['set-cookie-reload',
    // aliases are needed for matching the related scriptlet converted into our syntax
    'set-cookie-reload.js', 'ubo-set-cookie-reload.js', 'ubo-set-cookie-reload'];
    setCookieReload$1.injections = [hit, logMessage, nativeIsNaN, isCookieSetWithValue, getLimitedCookieValue, serializeCookie, isValidCookiePath, getCookiePath];

    /**
     * @scriptlet hide-in-shadow-dom
     *
     * @description
     * Hides elements inside open shadow DOM elements.
     *
     * ### Syntax
     *
     * ```text
     * example.org#%#//scriptlet('hide-in-shadow-dom', selector[, baseSelector])
     * ```
     *
     * - `selector` — required, CSS selector of element in shadow-dom to hide
     * - `baseSelector` — optional, selector of specific page DOM element,
     *   narrows down the part of the page DOM where shadow-dom host supposed to be,
     *   defaults to document.documentElement
     *
     * > `baseSelector` should match element of the page DOM, but not of shadow DOM.
     *
     * ### Examples
     *
     * ```adblock
     * ! hides menu bar
     * example.com#%#//scriptlet('hide-in-shadow-dom', '.storyAd', '#app')
     *
     * ! hides floating element
     * example.com#%#//scriptlet('hide-in-shadow-dom', '.contact-fab')
     * ```
     *
     * @added v1.3.0.
     */
    function hideInShadowDom$1(source, selector, baseSelector) {
      // do nothing if browser does not support ShadowRoot
      // https://developer.mozilla.org/en-US/docs/Web/API/ShadowRoot
      if (!Element.prototype.attachShadow) {
        return;
      }
      var hideElement = function hideElement(targetElement) {
        var DISPLAY_NONE_CSS = 'display:none!important;';
        targetElement.style.cssText = DISPLAY_NONE_CSS;
      };

      /**
       * Handles shadow-dom piercing and hiding of found elements
       */
      var hideHandler = function hideHandler() {
        // start value of shadow-dom hosts for the page dom
        var hostElements = !baseSelector ? findHostElements(document.documentElement) : document.querySelectorAll(baseSelector);

        // if there is shadow-dom host, they should be explored
        var _loop = function _loop() {
          var isHidden = false;
          var _pierceShadowDom = pierceShadowDom(selector, hostElements),
            targets = _pierceShadowDom.targets,
            innerHosts = _pierceShadowDom.innerHosts;
          targets.forEach(function (targetEl) {
            hideElement(targetEl);
            isHidden = true;
          });
          if (isHidden) {
            hit(source);
          }

          // continue to pierce for inner shadow-dom hosts
          // and search inside them while the next iteration
          hostElements = innerHosts;
        };
        while (hostElements.length !== 0) {
          _loop();
        }
      };
      hideHandler();
      observeDOMChanges(hideHandler, true);
    }
    hideInShadowDom$1.names = ['hide-in-shadow-dom'];
    hideInShadowDom$1.injections = [hit, observeDOMChanges, findHostElements, pierceShadowDom,
    // following helpers should be imported and injected
    // because they are used by helpers above
    flatten, throttle];

    /**
     * @scriptlet remove-in-shadow-dom
     *
     * @description
     * Removes elements inside open shadow DOM elements.
     *
     * ### Syntax
     *
     * ```text
     * example.org#%#//scriptlet('remove-in-shadow-dom', selector[, baseSelector])
     * ```
     *
     * - `selector` — required, CSS selector of element in shadow-dom to remove
     * - `baseSelector` — optional, selector of specific page DOM element,
     * narrows down the part of the page DOM where shadow-dom host supposed to be,
     * defaults to document.documentElement
     *
     * > `baseSelector` should match element of the page DOM, but not of shadow DOM.
     *
     * ### Examples
     *
     * ```adblock
     * ! removes menu bar
     * virustotal.com#%#//scriptlet('remove-in-shadow-dom', 'iron-pages', 'vt-virustotal-app')
     *
     * ! removes floating element
     * virustotal.com#%#//scriptlet('remove-in-shadow-dom', 'vt-ui-contact-fab')
     * ```
     *
     * @added v1.3.14.
     */
    function removeInShadowDom$1(source, selector, baseSelector) {
      // do nothing if browser does not support ShadowRoot
      // https://developer.mozilla.org/en-US/docs/Web/API/ShadowRoot
      if (!Element.prototype.attachShadow) {
        return;
      }
      var removeElement = function removeElement(targetElement) {
        targetElement.remove();
      };

      /**
       * Handles shadow-dom piercing and removing of found elements
       */
      var removeHandler = function removeHandler() {
        // start value of shadow-dom hosts for the page dom
        var hostElements = !baseSelector ? findHostElements(document.documentElement) : document.querySelectorAll(baseSelector);

        // if there is shadow-dom host, they should be explored
        var _loop = function _loop() {
          var isRemoved = false;
          var _pierceShadowDom = pierceShadowDom(selector, hostElements),
            targets = _pierceShadowDom.targets,
            innerHosts = _pierceShadowDom.innerHosts;
          targets.forEach(function (targetEl) {
            removeElement(targetEl);
            isRemoved = true;
          });
          if (isRemoved) {
            hit(source);
          }

          // continue to pierce for inner shadow-dom hosts
          // and search inside them while the next iteration
          hostElements = innerHosts;
        };
        while (hostElements.length !== 0) {
          _loop();
        }
      };
      removeHandler();
      observeDOMChanges(removeHandler, true);
    }
    removeInShadowDom$1.names = ['remove-in-shadow-dom'];
    removeInShadowDom$1.injections = [hit, observeDOMChanges, findHostElements, pierceShadowDom,
    // following helpers should be imported and injected
    // because they are used by helpers above
    flatten, throttle];

    /* eslint-disable max-len */
    /**
     * @scriptlet prevent-fetch
     *
     * @description
     * Prevents `fetch` calls if **all** given parameters match.
     *
     * Related UBO scriptlet:
     * https://github.com/gorhill/uBlock/wiki/Resources-Library#no-fetch-ifjs-
     *
     * ### Syntax
     *
     * ```text
     * example.org#%#//scriptlet('prevent-fetch'[, propsToMatch[, responseBody[, responseType]]])
     * ```
     *
     * - `propsToMatch` — optional, string of space-separated properties to match; possible props:
     *     - string or regular expression for matching the URL passed to fetch call;
     *       empty string, wildcard `*` or invalid regular expression will match all fetch calls
     *     - colon-separated pairs `name:value` where
     *         <!-- markdownlint-disable-next-line line-length -->
     *         - `name` is [`init` option name](https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/fetch#parameters)
     *         - `value` is string or regular expression for matching the value of the option passed to fetch call;
     *           invalid regular expression will cause any value matching
     * - `responseBody` — optional, string for defining response body value,
     *   defaults to `emptyObj`. Possible values:
     *     - `emptyObj` — empty object
     *     - `emptyArr` — empty array
     *     - `emptyStr` — empty string
     * - `responseType` — optional, string for defining response type,
     *   original response type is used if not specified. Possible values:
     *     - `basic`
     *     - `cors`
     *     - `opaque`
     *
     * > Usage with no arguments will log fetch calls to browser console;
     * > it may be useful for debugging but it is not allowed for prod versions of filter lists.
     *
     * ### Examples
     *
     * 1. Log all fetch calls
     *
     *     ```adblock
     *     example.org#%#//scriptlet('prevent-fetch')
     *     ```
     *
     * 1. Prevent all fetch calls
     *
     *     ```adblock
     *     example.org#%#//scriptlet('prevent-fetch', '*')
     *     ! or
     *     example.org#%#//scriptlet('prevent-fetch', '')
     *     ```
     *
     * 1. Prevent fetch call for specific url
     *
     *     ```adblock
     *     example.org#%#//scriptlet('prevent-fetch', '/url\\.part/')
     *     ```
     *
     * 1. Prevent fetch call for specific request method
     *
     *     ```adblock
     *     example.org#%#//scriptlet('prevent-fetch', 'method:HEAD')
     *     ```
     *
     * 1. Prevent fetch call for specific url and request method
     *
     *     ```adblock
     *     example.org#%#//scriptlet('prevent-fetch', '/specified_url_part/ method:/HEAD|GET/')
     *     ```
     *
     * 1. Prevent fetch call and specify response body value
     *
     *     ```adblock
     *     ! Specify response body for fetch call to a specific url
     *     example.org#%#//scriptlet('prevent-fetch', '/specified_url_part/ method:/HEAD|GET/', 'emptyArr')
     *
     *     ! Specify response body for all fetch calls
     *     example.org#%#//scriptlet('prevent-fetch', '', 'emptyArr')
     *     ```
     *
     * 1. Prevent all fetch calls and specify response type value
     *
     *     ```adblock
     *     example.org#%#//scriptlet('prevent-fetch', '*', '', 'opaque')
     *     ```
     *
     * @added v1.3.18.
     */
    /* eslint-enable max-len */
    function preventFetch$1(source, propsToMatch) {
      var responseBody = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 'emptyObj';
      var responseType = arguments.length > 3 ? arguments[3] : undefined;
      // do nothing if browser does not support fetch or Proxy (e.g. Internet Explorer)
      // https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/fetch
      // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy
      if (typeof fetch === 'undefined' || typeof Proxy === 'undefined' || typeof Response === 'undefined') {
        return;
      }
      var nativeRequestClone = Request.prototype.clone;
      var strResponseBody;
      if (responseBody === '' || responseBody === 'emptyObj') {
        strResponseBody = '{}';
      } else if (responseBody === 'emptyArr') {
        strResponseBody = '[]';
      } else if (responseBody === 'emptyStr') {
        strResponseBody = '';
      } else {
        logMessage(source, "Invalid responseBody parameter: '".concat(responseBody, "'"));
        return;
      }
      var isResponseTypeSpecified = typeof responseType !== 'undefined';
      var isResponseTypeSupported = function isResponseTypeSupported(responseType) {
        var SUPPORTED_TYPES = ['basic', 'cors', 'opaque'];
        return SUPPORTED_TYPES.includes(responseType);
      };
      // Skip disallowed response types,
      // specified responseType has limited list of possible values
      if (isResponseTypeSpecified && !isResponseTypeSupported(responseType)) {
        logMessage(source, "Invalid responseType parameter: '".concat(responseType, "'"));
        return;
      }

      /**
       * Get the response type based on the given request object.
       *
       * @param {Request} request - The request object.
       * @returns {string|undefined} The response type or undefined.
       */
      var getResponseType = function getResponseType(request) {
        try {
          var mode = request.mode;
          if (mode === undefined || mode === 'cors' || mode === 'no-cors') {
            var fetchURL = new URL(request.url);
            if (fetchURL.origin === document.location.origin) {
              return 'basic';
            }
            return mode === 'no-cors' ? 'opaque' : 'cors';
          }
        } catch (error) {
          logMessage(source, "Could not determine response type: ".concat(error));
        }
        return undefined;
      };
      var handlerWrapper = async function handlerWrapper(target, thisArg, args) {
        var shouldPrevent = false;
        var fetchData = getFetchData(args, nativeRequestClone);
        if (typeof propsToMatch === 'undefined') {
          logMessage(source, "fetch( ".concat(objectToString$1(fetchData), " )"), true);
          hit(source);
          return Reflect.apply(target, thisArg, args);
        }
        shouldPrevent = matchRequestProps(source, propsToMatch, fetchData);
        if (shouldPrevent) {
          hit(source);
          var finalResponseType;
          try {
            finalResponseType = responseType || getResponseType(fetchData);
            var origResponse = await Reflect.apply(target, thisArg, args);
            // In the case of apps, the blocked request has status 500
            // and no error is thrown, so it's necessary to check response.ok
            // https://github.com/AdguardTeam/Scriptlets/issues/334
            if (!origResponse.ok) {
              return noopPromiseResolve(strResponseBody, fetchData.url, finalResponseType);
            }
            return modifyResponse(origResponse, {
              body: strResponseBody,
              type: finalResponseType
            });
          } catch (ex) {
            // https://github.com/AdguardTeam/Scriptlets/issues/334
            return noopPromiseResolve(strResponseBody, fetchData.url, finalResponseType);
          }
        }
        return Reflect.apply(target, thisArg, args);
      };
      var fetchHandler = {
        apply: handlerWrapper
      };
      fetch = new Proxy(fetch, fetchHandler); // eslint-disable-line no-global-assign
    }

    preventFetch$1.names = ['prevent-fetch',
    // aliases are needed for matching the related scriptlet converted into our syntax
    'prevent-fetch.js', 'ubo-prevent-fetch.js', 'ubo-prevent-fetch', 'no-fetch-if.js', 'ubo-no-fetch-if.js', 'ubo-no-fetch-if'];
    preventFetch$1.injections = [hit, getFetchData, objectToString$1, matchRequestProps, logMessage, noopPromiseResolve, modifyResponse, toRegExp, isValidStrPattern, escapeRegExp, isEmptyObject, getRequestData, getRequestProps, parseMatchProps, isValidParsedData, getMatchPropsData];

    /* eslint-disable max-len */
    /**
     * @scriptlet set-local-storage-item
     *
     * @description
     * Adds specified key and its value to localStorage object, or updates the value of the key if it already exists.
     * Scriptlet won't set item if storage is full.
     *
     * To remove item from localStorage use `$remove$` as a value.
     *
     * Related UBO scriptlet:
     * https://github.com/gorhill/uBlock/wiki/Resources-Library#set-local-storage-itemjs-
     *
     * ### Syntax
     *
     * ```text
     * example.com#%#//scriptlet('set-local-storage-item', 'key', 'value')
     * ```
     *
     * - `key` — required, key name to be set. Should be a string for setting,
     *   but it also can be a regular expression for removing items from localStorage.
     * - `value` — required, key value; possible values:
     *     - positive decimal integer `<= 32767`
     *     - one of the predefined constants in any case variation:
     *         - `undefined`
     *         - `false`
     *         - `true`
     *         - `null`
     *         - `emptyObj` — empty object
     *         - `emptyArr` — empty array
     *         - `''` — empty string
     *         - `yes`
     *         - `no`
     *         - `on`
     *         - `off`
     *         - `accept`
     *         - `accepted`
     *         - `reject`
     *         - `rejected`
     *         - `allowed`
     *         - `denied`
     *         - `$remove$` — remove specific item from localStorage
     *
     * ### Examples
     *
     * ```adblock
     * example.org#%#//scriptlet('set-local-storage-item', 'player.live.current.mute', 'false')
     *
     * example.org#%#//scriptlet('set-local-storage-item', 'exit-intent-marketing', '1')
     *
     * ! Removes the item with key 'foo' from local storage
     * example.org#%#//scriptlet('set-local-storage-item', 'foo', '$remove$')
     *
     * ! Removes from local storage all items whose key matches the regular expression `/mp_.*_mixpanel/`
     * example.org#%#//scriptlet('set-local-storage-item', '/mp_.*_mixpanel/', '$remove$')
     * ```
     *
     * @added v1.4.3.
     */
    /* eslint-enable max-len */

    function setLocalStorageItem$1(source, key, value) {
      if (typeof key === 'undefined') {
        logMessage(source, 'Item key should be specified.');
        return;
      }
      var validValue;
      try {
        validValue = getLimitedStorageItemValue(value);
      } catch (_unused) {
        logMessage(source, "Invalid storage item value: '".concat(value, "'"));
        return;
      }
      var _window = window,
        localStorage = _window.localStorage;
      if (validValue === '$remove$') {
        removeStorageItem(source, localStorage, key);
      } else {
        setStorageItem(source, localStorage, key, validValue);
      }
      hit(source);
    }
    setLocalStorageItem$1.names = ['set-local-storage-item',
    // aliases are needed for matching the related scriptlet converted into our syntax
    'set-local-storage-item.js', 'ubo-set-local-storage-item.js', 'ubo-set-local-storage-item'];
    setLocalStorageItem$1.injections = [hit, logMessage, nativeIsNaN, setStorageItem, removeStorageItem, getLimitedStorageItemValue,
    // following helpers are needed for helpers above
    isValidStrPattern, toRegExp, escapeRegExp];

    /* eslint-disable max-len */
    /**
     * @scriptlet set-session-storage-item
     *
     * @description
     * Adds specified key and its value to sessionStorage object, or updates the value of the key if it already exists.
     * Scriptlet won't set item if storage is full.
     *
     * To remove item from sessionStorage use `$remove$` as a value.
     *
     * Related UBO scriptlet:
     * https://github.com/gorhill/uBlock/wiki/Resources-Library#set-session-storage-itemjs-
     *
     * ### Syntax
     *
     * ```text
     * example.com#%#//scriptlet('set-session-storage-item', 'key', 'value')
     * ```
     *
     * - `key` — required, key name to be set. Should be a string for setting,
     *   but it also can be a regular expression for removing items from localStorage.
     * - `value` — required, key value; possible values:
     *     - positive decimal integer `<= 32767`
     *     - one of the predefined constants in any case variation:
     *         - `undefined`
     *         - `false`
     *         - `true`
     *         - `null`
     *         - `emptyObj` — empty object
     *         - `emptyArr` — empty array
     *         - `''` — empty string
     *         - `yes`
     *         - `no`
     *         - `on`
     *         - `off`
     *         - `accept`
     *         - `accepted`
     *         - `reject`
     *         - `rejected`
     *         - `allowed`
     *         - `denied`
     *         - `$remove$` — remove specific item from sessionStorage
     *
     * ### Examples
     *
     * ```adblock
     * example.org#%#//scriptlet('set-session-storage-item', 'player.live.current.mute', 'false')
     *
     * example.org#%#//scriptlet('set-session-storage-item', 'exit-intent-marketing', '1')
     *
     * ! Removes the item with key 'foo' from session storage
     * example.org#%#//scriptlet('set-session-storage-item', 'foo', '$remove$')
     *
     * ! Removes from session storage all items whose key matches the regular expression `/mp_.*_mixpanel/`
     * example.org#%#//scriptlet('set-session-storage-item', '/mp_.*_mixpanel/', '$remove$')
     * ```
     *
     * @added v1.4.3.
     */
    /* eslint-enable max-len */

    function setSessionStorageItem$1(source, key, value) {
      if (typeof key === 'undefined') {
        logMessage(source, 'Item key should be specified.');
        return;
      }
      var validValue;
      try {
        validValue = getLimitedStorageItemValue(value);
      } catch (_unused) {
        logMessage(source, "Invalid storage item value: '".concat(value, "'"));
        return;
      }
      var _window = window,
        sessionStorage = _window.sessionStorage;
      if (validValue === '$remove$') {
        removeStorageItem(source, sessionStorage, key);
      } else {
        setStorageItem(source, sessionStorage, key, validValue);
      }
      hit(source);
    }
    setSessionStorageItem$1.names = ['set-session-storage-item',
    // aliases are needed for matching the related scriptlet converted into our syntax
    'set-session-storage-item.js', 'ubo-set-session-storage-item.js', 'ubo-set-session-storage-item'];
    setSessionStorageItem$1.injections = [hit, logMessage, nativeIsNaN, setStorageItem, removeStorageItem, getLimitedStorageItemValue,
    // following helpers are needed for helpers above
    isValidStrPattern, toRegExp, escapeRegExp];

    /* eslint-disable max-len */
    /**
     * @scriptlet abort-on-stack-trace
     *
     * @description
     * Aborts a script when it attempts to utilize (read or write to) the specified property
     * and it's error stack trace contains given value.
     *
     * Related UBO scriptlet:
     * https://github.com/gorhill/uBlock-for-firefox-legacy/commit/7099186ae54e70b588d5e99554a05d783cabc8ff
     *
     * ### Syntax
     *
     * ```text
     * example.com#%#//scriptlet('abort-on-stack-trace', property, stack)
     * ```
     *
     * - `property` — required, path to a property. The property must be attached to window.
     * - `stack` — required, string that must match the current function call stack trace.
     *     - values to abort inline or injected script, accordingly:
     *         - `inlineScript`
     *         - `injectedScript`
     *
     * ### Examples
     *
     * 1. Aborts script when it tries to access `window.Ya` and it's error stack trace contains `test.js`
     *
     *     ```adblock
     *     example.org#%#//scriptlet('abort-on-stack-trace', 'Ya', 'test.js')
     *     ```
     *
     * 1. Aborts script when it tries to access `window.Ya.videoAd` and it's error stack trace contains `test.js`
     *
     *     ```adblock
     *     example.org#%#//scriptlet('abort-on-stack-trace', 'Ya.videoAd', 'test.js')
     *     ```
     *
     * 1. Aborts script when stack trace matches with any of these parameters
     *
     *     ```adblock
     *     example.org#%#//scriptlet('abort-on-stack-trace', 'Ya', 'yandexFuncName')
     *     example.org#%#//scriptlet('abort-on-stack-trace', 'Ya', 'yandexScriptName')
     *     ```
     *
     * 1. Aborts script when it tries to access `window.Ya` and it's an inline script
     *
     *     ```adblock
     *     example.org#%#//scriptlet('abort-on-stack-trace', 'Ya', 'inlineScript')
     *     ```
     *
     * 1. Aborts script when it tries to access `window.Ya` and it's an injected script
     *
     *      ```adblock
     *      example.org#%#//scriptlet('abort-on-stack-trace', 'Ya', 'injectedScript')
     *      ```
     *
     * @added v1.5.0.
     */
    /* eslint-enable max-len */
    function abortOnStackTrace$1(source, property, stack) {
      if (!property || !stack) {
        return;
      }
      var rid = randomId();
      var abort = function abort() {
        hit(source);
        throw new ReferenceError(rid);
      };
      var setChainPropAccess = function setChainPropAccess(owner, property) {
        var chainInfo = getPropertyInChain(owner, property);
        var base = chainInfo.base;
        var prop = chainInfo.prop,
          chain = chainInfo.chain;
        if (chain) {
          var setter = function setter(a) {
            base = a;
            if (a instanceof Object) {
              setChainPropAccess(a, chain);
            }
          };
          Object.defineProperty(owner, prop, {
            get: function get() {
              return base;
            },
            set: setter
          });
          return;
        }
        if (!stack.match(/^(inlineScript|injectedScript)$/) && !isValidStrPattern(stack)) {
          logMessage(source, "Invalid parameter: ".concat(stack));
          return;
        }

        // Prevent infinite loops when trapping prop used by helpers in getter/setter
        var descriptorWrapper = Object.assign(getDescriptorAddon(), {
          value: base[prop],
          get() {
            if (!this.isAbortingSuspended && this.isolateCallback(matchStackTrace, stack, new Error().stack)) {
              abort();
            }
            return this.value;
          },
          set(newValue) {
            if (!this.isAbortingSuspended && this.isolateCallback(matchStackTrace, stack, new Error().stack)) {
              abort();
            }
            this.value = newValue;
          }
        });
        setPropertyAccess(base, prop, {
          // Call wrapped getter and setter to keep isAbortingSuspended & isolateCallback values
          get() {
            return descriptorWrapper.get.call(descriptorWrapper);
          },
          set(newValue) {
            descriptorWrapper.set.call(descriptorWrapper, newValue);
          }
        });
      };
      setChainPropAccess(window, property);
      window.onerror = createOnErrorHandler(rid).bind();
    }
    abortOnStackTrace$1.names = ['abort-on-stack-trace',
    // aliases are needed for matching the related scriptlet converted into our syntax
    'abort-on-stack-trace.js', 'ubo-abort-on-stack-trace.js', 'aost.js', 'ubo-aost.js', 'ubo-abort-on-stack-trace', 'ubo-aost', 'abp-abort-on-stack-trace'];
    abortOnStackTrace$1.injections = [randomId, setPropertyAccess, getPropertyInChain, createOnErrorHandler, hit, isValidStrPattern, escapeRegExp, matchStackTrace, getDescriptorAddon, logMessage, toRegExp, isEmptyObject, getNativeRegexpTest, shouldAbortInlineOrInjectedScript, backupRegExpValues, restoreRegExpValues];

    /* eslint-disable max-len */
    /**
     * @scriptlet log-on-stack-trace
     *
     * @description
     * This scriptlet is basically the same as [abort-on-stack-trace](#abort-on-stack-trace),
     * but instead of aborting it logs:
     *
     * - function and source script names pairs that access the given property
     * - was that get or set attempt
     * - script being injected or inline
     *
     * ### Syntax
     *
     * ```text
     * example.com#%#//scriptlet('log-on-stack-trace', 'property')
     * ```
     *
     * - `property` — required, path to a property. The property must be attached to window.
     *
     * @added v1.5.0.
     */
    /* eslint-enable max-len */
    function logOnStacktrace$1(source, property) {
      if (!property) {
        return;
      }
      var refineStackTrace = function refineStackTrace(stackString) {
        var regExpValues = backupRegExpValues();

        // Split stack trace string by lines and remove first two elements ('Error' and getter call)
        // Remove '    at ' at the start of each string
        var stackSteps = stackString.split('\n').slice(2).map(function (line) {
          return line.replace(/ {4}at /, '');
        });
        // Trim each line extracting funcName : fullPath pair
        var logInfoArray = stackSteps.map(function (line) {
          var funcName;
          var funcFullPath;
          /* eslint-disable-next-line no-useless-escape */
          var reg = /\(([^\)]+)\)/;
          var regFirefox = /(.*?@)(\S+)(:\d+):\d+\)?$/;
          if (line.match(reg)) {
            funcName = line.split(' ').slice(0, -1).join(' ');
            /* eslint-disable-next-line prefer-destructuring */
            funcFullPath = line.match(reg)[1];
          } else if (line.match(regFirefox)) {
            funcName = line.split('@').slice(0, -1).join(' ');
            /* eslint-disable-next-line prefer-destructuring */
            funcFullPath = line.match(regFirefox)[2];
          } else {
            // For when func name is not available
            funcName = 'function name is not available';
            funcFullPath = line;
          }
          return [funcName, funcFullPath];
        });
        // Convert array into object for better display using console.table
        var logInfoObject = {};
        logInfoArray.forEach(function (pair) {
          /* eslint-disable-next-line prefer-destructuring */
          logInfoObject[pair[0]] = pair[1];
        });
        if (regExpValues.length && regExpValues[0] !== RegExp.$1) {
          restoreRegExpValues(regExpValues);
        }
        return logInfoObject;
      };
      var setChainPropAccess = function setChainPropAccess(owner, property) {
        var chainInfo = getPropertyInChain(owner, property);
        var base = chainInfo.base;
        var prop = chainInfo.prop,
          chain = chainInfo.chain;
        if (chain) {
          var setter = function setter(a) {
            base = a;
            if (a instanceof Object) {
              setChainPropAccess(a, chain);
            }
          };
          Object.defineProperty(owner, prop, {
            get: function get() {
              return base;
            },
            set: setter
          });
          return;
        }
        var value = base[prop];
        /* eslint-disable no-console */
        setPropertyAccess(base, prop, {
          get() {
            hit(source);
            logMessage(source, "Get ".concat(prop), true);
            console.table(refineStackTrace(new Error().stack));
            return value;
          },
          set(newValue) {
            hit(source);
            logMessage(source, "Set ".concat(prop), true);
            console.table(refineStackTrace(new Error().stack));
            value = newValue;
          }
        });
        /* eslint-enable no-console */
      };

      setChainPropAccess(window, property);
    }
    logOnStacktrace$1.names = ['log-on-stack-trace'];
    logOnStacktrace$1.injections = [getPropertyInChain, setPropertyAccess, hit, logMessage, isEmptyObject, backupRegExpValues, restoreRegExpValues];

    /* eslint-disable max-len */
    /**
     * @scriptlet prevent-xhr
     *
     * @description
     * Prevents `xhr` calls if **all** given parameters match.
     *
     * Related UBO scriptlet:
     * https://github.com/gorhill/uBlock/wiki/Resources-Library#no-xhr-ifjs-
     *
     * ### Syntax
     *
     * ```text
     * example.org#%#//scriptlet('prevent-xhr'[, propsToMatch[, randomize]])
     * ```
     *
     * - `propsToMatch` — optional, string of space-separated properties to match; possible props:
     *     - string or regular expression for matching the URL passed to `XMLHttpRequest.open()` call;
     *       empty string or wildcard `*` for all `XMLHttpRequest.open()` calls match
     *         - colon-separated pairs `name:value` where
     *             - `name` is XMLHttpRequest object property name
     *             - `value` is string or regular expression for matching the value of the option
     *     passed to `XMLHttpRequest.open()` call
     * - `randomize` — defaults to `false` for empty responseText,
     *   optional argument to randomize responseText of matched XMLHttpRequest's response; possible values:
     *     - `true` to randomize responseText, random alphanumeric string of 10 symbols
     *     - colon-separated pair `name:value` string value to customize responseText data where
     *         - `name` — only `length` supported for now
     *         - `value` — range on numbers, for example `100-300`, limited to 500000 characters
     *
     * > Usage with no arguments will log XMLHttpRequest objects to browser console;
     * > it may be useful for debugging but it is not allowed for prod versions of filter lists.
     *
     * ### Examples
     *
     * 1. Log all XMLHttpRequests
     *
     *     ```adblock
     *     example.org#%#//scriptlet('prevent-xhr')
     *     ```
     *
     * 1. Prevent all XMLHttpRequests
     *
     *     ```adblock
     *     example.org#%#//scriptlet('prevent-xhr', '*')
     *     example.org#%#//scriptlet('prevent-xhr', '')
     *     ```
     *
     * 1. Prevent XMLHttpRequests for specific url
     *
     *     ```adblock
     *     example.org#%#//scriptlet('prevent-xhr', 'example.org')
     *     ```
     *
     * 1. Prevent XMLHttpRequests for specific request method
     *
     *     ```adblock
     *     example.org#%#//scriptlet('prevent-xhr', 'method:HEAD')
     *     ```
     *
     * 1. Prevent XMLHttpRequests for specific url and specified request methods
     *
     *     ```adblock
     *     example.org#%#//scriptlet('prevent-xhr', 'example.org method:/HEAD|GET/')
     *     ```
     *
     * 1. Prevent XMLHttpRequests for specific url and randomize it's response text
     *
     *     ```adblock
     *     example.org#%#//scriptlet('prevent-xhr', 'example.org', 'true')
     *     ```
     *
     * 1. Prevent XMLHttpRequests for specific url and randomize it's response text with range
     *
     *     ```adblock
     *    example.org#%#//scriptlet('prevent-xhr', 'example.org', 'length:100-300')
     *     ```
     *
     * @added v1.5.0.
     */
    /* eslint-enable max-len */
    function preventXHR$1(source, propsToMatch, customResponseText) {
      // do nothing if browser does not support Proxy (e.g. Internet Explorer)
      // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy
      if (typeof Proxy === 'undefined') {
        return;
      }
      var nativeOpen = window.XMLHttpRequest.prototype.open;
      var nativeSend = window.XMLHttpRequest.prototype.send;
      var nativeGetResponseHeader = window.XMLHttpRequest.prototype.getResponseHeader;
      var nativeGetAllResponseHeaders = window.XMLHttpRequest.prototype.getAllResponseHeaders;
      var xhrData;
      var modifiedResponse = '';
      var modifiedResponseText = '';
      var openWrapper = function openWrapper(target, thisArg, args) {
        // Get original request properties
        // eslint-disable-next-line prefer-spread
        xhrData = getXhrData.apply(null, args);
        if (typeof propsToMatch === 'undefined') {
          // Log if no propsToMatch given
          logMessage(source, "xhr( ".concat(objectToString$1(xhrData), " )"), true);
          hit(source);
        } else if (matchRequestProps(source, propsToMatch, xhrData)) {
          thisArg.shouldBePrevented = true;
          // Add xhrData to thisArg to keep original values in case of multiple requests
          // https://github.com/AdguardTeam/Scriptlets/issues/347
          thisArg.xhrData = xhrData;
        }

        // Trap setRequestHeader of target xhr object to mimic request headers later;
        // needed for getResponseHeader() and getAllResponseHeaders() methods
        if (thisArg.shouldBePrevented) {
          thisArg.collectedHeaders = [];
          var setRequestHeaderWrapper = function setRequestHeaderWrapper(target, thisArg, args) {
            // Collect headers
            thisArg.collectedHeaders.push(args);
            return Reflect.apply(target, thisArg, args);
          };
          var setRequestHeaderHandler = {
            apply: setRequestHeaderWrapper
          };
          // setRequestHeader() can only be called on xhr.open(),
          // so we can safely proxy it here
          thisArg.setRequestHeader = new Proxy(thisArg.setRequestHeader, setRequestHeaderHandler);
        }
        return Reflect.apply(target, thisArg, args);
      };
      var sendWrapper = function sendWrapper(target, thisArg, args) {
        if (!thisArg.shouldBePrevented) {
          return Reflect.apply(target, thisArg, args);
        }
        if (thisArg.responseType === 'blob') {
          modifiedResponse = new Blob();
        }
        if (thisArg.responseType === 'arraybuffer') {
          modifiedResponse = new ArrayBuffer();
        }
        if (customResponseText) {
          var randomText = generateRandomResponse(customResponseText);
          if (randomText) {
            modifiedResponseText = randomText;
          } else {
            logMessage(source, "Invalid randomize parameter: '".concat(customResponseText, "'"));
          }
        }

        /**
         * Create separate XHR request with original request's input
         * to be able to collect response data without triggering
         * listeners on original XHR object
         */
        var forgedRequest = new XMLHttpRequest();
        forgedRequest.addEventListener('readystatechange', function () {
          if (forgedRequest.readyState !== 4) {
            return;
          }
          var readyState = forgedRequest.readyState,
            responseURL = forgedRequest.responseURL,
            responseXML = forgedRequest.responseXML,
            statusText = forgedRequest.statusText;

          // Mock response object
          Object.defineProperties(thisArg, {
            // original values
            readyState: {
              value: readyState,
              writable: false
            },
            statusText: {
              value: statusText,
              writable: false
            },
            // If the request is blocked, responseURL is an empty string
            responseURL: {
              value: responseURL || thisArg.xhrData.url,
              writable: false
            },
            responseXML: {
              value: responseXML,
              writable: false
            },
            // modified values
            status: {
              value: 200,
              writable: false
            },
            response: {
              value: modifiedResponse,
              writable: false
            },
            responseText: {
              value: modifiedResponseText,
              writable: false
            }
          });

          // Mock events
          setTimeout(function () {
            var stateEvent = new Event('readystatechange');
            thisArg.dispatchEvent(stateEvent);
            var loadEvent = new Event('load');
            thisArg.dispatchEvent(loadEvent);
            var loadEndEvent = new Event('loadend');
            thisArg.dispatchEvent(loadEndEvent);
          }, 1);
          hit(source);
        });
        nativeOpen.apply(forgedRequest, [thisArg.xhrData.method, thisArg.xhrData.url]);

        // Mimic request headers before sending
        // setRequestHeader can only be called on open request objects
        thisArg.collectedHeaders.forEach(function (header) {
          var name = header[0];
          var value = header[1];
          forgedRequest.setRequestHeader(name, value);
        });
        try {
          nativeSend.call(forgedRequest, args);
        } catch (_unused) {
          return Reflect.apply(target, thisArg, args);
        }
        return undefined;
      };

      /**
       * Mock XMLHttpRequest.prototype.getHeaderHandler() to avoid adblocker detection.
       *
       * @param {Function} target XMLHttpRequest.prototype.getHeaderHandler().
       * @param {XMLHttpRequest} thisArg The request.
       * @param {string[]} args Header name is passed as first argument.
       *
       * @returns {string|null} Header value or null if header is not set.
       */
      var getHeaderWrapper = function getHeaderWrapper(target, thisArg, args) {
        if (!thisArg.shouldBePrevented) {
          return nativeGetResponseHeader.apply(thisArg, args);
        }
        if (!thisArg.collectedHeaders.length) {
          return null;
        }
        // The search for the header name is case-insensitive
        // https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/getResponseHeader
        var searchHeaderName = args[0].toLowerCase();
        var matchedHeader = thisArg.collectedHeaders.find(function (header) {
          var headerName = header[0].toLowerCase();
          return headerName === searchHeaderName;
        });
        return matchedHeader ? matchedHeader[1] : null;
      };

      /**
       * Mock XMLHttpRequest.prototype.getAllResponseHeaders() to avoid adblocker detection.
       *
       * @param {Function} target XMLHttpRequest.prototype.getAllResponseHeaders().
       * @param {XMLHttpRequest} thisArg The request.
       *
       * @returns {string} All headers as a string. For no headers an empty string is returned.
       */
      var getAllHeadersWrapper = function getAllHeadersWrapper(target, thisArg) {
        if (!thisArg.shouldBePrevented) {
          return nativeGetAllResponseHeaders.call(thisArg);
        }
        if (!thisArg.collectedHeaders.length) {
          return '';
        }
        var allHeadersStr = thisArg.collectedHeaders.map(function (header) {
          /**
           * TODO: array destructuring may be used here
           * after the typescript implementation and bundling refactoring
           * as now there is an error: slicedToArray is not defined
           */
          var headerName = header[0];
          var headerValue = header[1];
          // In modern browsers, the header names are returned in all lower case, as per the latest spec.
          // https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/getAllResponseHeaders
          return "".concat(headerName.toLowerCase(), ": ").concat(headerValue);
        }).join('\r\n');
        return allHeadersStr;
      };
      var openHandler = {
        apply: openWrapper
      };
      var sendHandler = {
        apply: sendWrapper
      };
      var getHeaderHandler = {
        apply: getHeaderWrapper
      };
      var getAllHeadersHandler = {
        apply: getAllHeadersWrapper
      };
      XMLHttpRequest.prototype.open = new Proxy(XMLHttpRequest.prototype.open, openHandler);
      XMLHttpRequest.prototype.send = new Proxy(XMLHttpRequest.prototype.send, sendHandler);
      XMLHttpRequest.prototype.getResponseHeader = new Proxy(XMLHttpRequest.prototype.getResponseHeader, getHeaderHandler);
      XMLHttpRequest.prototype.getAllResponseHeaders = new Proxy(XMLHttpRequest.prototype.getAllResponseHeaders, getAllHeadersHandler);
    }
    preventXHR$1.names = ['prevent-xhr',
    // aliases are needed for matching the related scriptlet converted into our syntax
    'no-xhr-if.js', 'ubo-no-xhr-if.js', 'ubo-no-xhr-if'];
    preventXHR$1.injections = [hit, objectToString$1, generateRandomResponse, matchRequestProps, getXhrData, logMessage, toRegExp, isValidStrPattern, escapeRegExp, isEmptyObject, getNumberFromString, nativeIsFinite, nativeIsNaN, parseMatchProps, isValidParsedData, getMatchPropsData, getRequestProps, getRandomIntInclusive, getRandomStrByLength];

    /**
     * @scriptlet close-window
     *
     * @description
     * Closes the browser tab immediately.
     *
     * > `window.close()` usage is restricted in the Chrome browser.
     * > In this case tab will only be closed when using AdGuard Browser extension.
     *
     * ### Syntax
     *
     * ```text
     * example.org#%#//scriptlet('close-window'[, path])
     * ```
     *
     * - `path` — optional, string or regular expression
     *   matching the current location's path: `window.location.pathname` + `window.location.search`.
     *   Defaults to execute on every page.
     *
     * ### Examples
     *
     * ```adblock
     * ! closes any example.org tab
     * example.org#%#//scriptlet('close-window')
     *
     * ! closes specific example.org tab
     * example.org#%#//scriptlet('close-window', '/example-page.html')
     * ```
     *
     * @added v1.5.0.
     */
    function forceWindowClose$1(source) {
      var path = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : '';
      // https://github.com/AdguardTeam/Scriptlets/issues/158#issuecomment-993423036
      if (typeof window.close !== 'function') {
        var message = 'window.close() is not a function so \'close-window\' scriptlet is unavailable';
        logMessage(source, message);
        return;
      }
      var closeImmediately = function closeImmediately() {
        try {
          hit(source);
          window.close();
        } catch (e) {
          // log the error if window closing is impossible
          // https://developer.mozilla.org/en-US/docs/Web/API/Window/close
          logMessage(source, e);
        }
      };
      var closeByExtension = function closeByExtension() {
        var extCall = function extCall() {
          dispatchEvent(new Event('adguard:scriptlet-close-window'));
        };
        window.addEventListener('adguard:subscribed-to-close-window', extCall, {
          once: true
        });
        setTimeout(function () {
          window.removeEventListener('adguard:subscribed-to-close-window', extCall, {
            once: true
          });
        }, 5000);
      };
      var shouldClose = function shouldClose() {
        if (path === '') {
          return true;
        }
        var pathRegexp = toRegExp(path);
        var currentPath = "".concat(window.location.pathname).concat(window.location.search);
        return pathRegexp.test(currentPath);
      };
      if (shouldClose()) {
        closeImmediately();
        if (navigator.userAgent.includes('Chrome')) {
          closeByExtension();
        }
      }
    }
    forceWindowClose$1.names = ['close-window',
    // aliases are needed for matching the related scriptlet converted into our syntax
    'window-close-if.js', 'ubo-window-close-if.js', 'ubo-window-close-if', 'close-window.js', 'ubo-close-window.js', 'ubo-close-window'];
    forceWindowClose$1.injections = [hit, toRegExp, logMessage];

    /* eslint-disable max-len */
    /**
     * @scriptlet prevent-refresh
     *
     * @description
     * Prevents reloading of a document through a meta "refresh" tag.
     *
     * Related UBO scriptlet:
     * https://github.com/gorhill/uBlock/wiki/Resources-Library#refresh-defuserjs-
     *
     * ### Syntax
     *
     * ```text
     * example.org#%#//scriptlet('prevent-refresh'[, delay])
     * ```
     *
     * - `delay` — optional, number of seconds for delay that indicates when scriptlet should run.
     *   If not set, source tag value will be applied.
     *
     * ### Examples
     *
     * 1. Prevent reloading of a document through a meta "refresh" tag
     *
     *     ```adblock
     *     example.org#%#//scriptlet('prevent-refresh')
     *     ```
     *
     * 1. Prevent reloading of a document with delay
     *
     *     ```adblock
     *     example.com#%#//scriptlet('prevent-refresh', 3)
     *     ```
     *
     * @added v1.6.2.
     */
    /* eslint-enable max-len */
    function preventRefresh$1(source, delaySec) {
      var getMetaElements = function getMetaElements() {
        var metaNodes = [];
        try {
          metaNodes = document.querySelectorAll('meta[http-equiv="refresh" i][content]');
        } catch (e) {
          // 'i' attribute flag is problematic in Edge 15
          try {
            metaNodes = document.querySelectorAll('meta[http-equiv="refresh"][content]');
          } catch (e) {
            logMessage(source, e);
          }
        }
        return Array.from(metaNodes);
      };
      var getMetaContentDelay = function getMetaContentDelay(metaElements) {
        var delays = metaElements.map(function (meta) {
          var contentString = meta.getAttribute('content');
          if (contentString.length === 0) {
            return null;
          }
          var contentDelay;
          // https://developer.mozilla.org/en-US/docs/Web/HTML/Element/meta#attr-http-equiv
          var limiterIndex = contentString.indexOf(';');
          if (limiterIndex !== -1) {
            var delaySubstring = contentString.substring(0, limiterIndex);
            contentDelay = getNumberFromString(delaySubstring);
          } else {
            contentDelay = getNumberFromString(contentString);
          }
          return contentDelay;
        }).filter(function (delay) {
          return delay !== null;
        });
        // Check if "delays" array is empty, may happens when meta's content is invalid
        // and reduce() method cannot be used with empty arrays without initial value
        if (!delays.length) {
          return null;
        }
        // Get smallest delay of all metas on the page
        var minDelay = delays.reduce(function (a, b) {
          return Math.min(a, b);
        });
        // eslint-disable-next-line consistent-return
        return minDelay;
      };
      var stop = function stop() {
        var metaElements = getMetaElements();
        if (metaElements.length === 0) {
          return;
        }
        var secondsToRun = getNumberFromString(delaySec);
        // Check if argument is provided
        if (secondsToRun === null) {
          secondsToRun = getMetaContentDelay(metaElements);
        }
        // Check if meta tag has delay
        if (secondsToRun === null) {
          return;
        }
        var delayMs = secondsToRun * 1000;
        setTimeout(function () {
          window.stop();
          hit(source);
        }, delayMs);
      };
      if (document.readyState === 'loading') {
        document.addEventListener('DOMContentLoaded', stop, {
          once: true
        });
      } else {
        stop();
      }
    }
    preventRefresh$1.names = ['prevent-refresh',
    // Aliases are needed for matching the related scriptlet converted into our syntax
    // These are used by UBO rules syntax
    // https://github.com/gorhill/uBlock/wiki/Resources-Library#general-purpose-scriptlets
    'prevent-refresh.js', 'refresh-defuser.js', 'refresh-defuser',
    // Prefix 'ubo-' is required to run converted rules
    'ubo-prevent-refresh.js', 'ubo-prevent-refresh', 'ubo-refresh-defuser.js', 'ubo-refresh-defuser'];
    preventRefresh$1.injections = [hit, getNumberFromString, logMessage, nativeIsNaN];

    /* eslint-disable max-len, consistent-return */
    /**
     * @scriptlet prevent-element-src-loading
     *
     * @description
     * Prevents target element source loading without triggering 'onerror' listeners and not breaking 'onload' ones.
     *
     * ### Syntax
     *
     * ```text
     * example.org#%#//scriptlet('prevent-element-src-loading', tagName, match)
     * ```
     *
     * - `tagName` — required, case-insensitive target element tagName
     *   which `src` property resource loading will be silently prevented; possible values:
     *     - `script`
     *     - `img`
     *     - `iframe`
     *     - `link`
     * - `match` — required, string or regular expression for matching the element's URL;
     *
     * ### Examples
     *
     * 1. Prevent script source loading
     *
     *     ```adblock
     *     example.org#%#//scriptlet('prevent-element-src-loading', 'script' ,'adsbygoogle')
     *     ```
     *
     * @added v1.6.2.
     */
    /* eslint-enable max-len */
    function preventElementSrcLoading$1(source, tagName, match) {
      // do nothing if browser does not support Proxy or Reflect
      if (typeof Proxy === 'undefined' || typeof Reflect === 'undefined') {
        return;
      }
      var srcMockData = {
        // "KCk9Pnt9" = "()=>{}"
        script: 'data:text/javascript;base64,KCk9Pnt9',
        // Empty 1x1 image
        img: 'data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==',
        // Empty h1 tag
        iframe: 'data:text/html;base64, PGRpdj48L2Rpdj4=',
        // Empty data
        link: 'data:text/plain;base64,'
      };
      var instance;
      if (tagName === 'script') {
        instance = HTMLScriptElement;
      } else if (tagName === 'img') {
        instance = HTMLImageElement;
      } else if (tagName === 'iframe') {
        instance = HTMLIFrameElement;
      } else if (tagName === 'link') {
        instance = HTMLLinkElement;
      } else {
        return;
      }

      // For websites that use Trusted Types
      // https://w3c.github.io/webappsec-trusted-types/dist/spec/
      var hasTrustedTypes = window.trustedTypes && typeof window.trustedTypes.createPolicy === 'function';
      var policy;
      if (hasTrustedTypes) {
        // The name for the trusted-types policy should only be 'AGPolicy',because corelibs can
        // allow our policy if the server has restricted the creation of a trusted-types policy with
        // the directive 'Content-Security-Policy: trusted-types <policyName>;`.
        // If such a header is presented in the server response, corelibs adds permission to create
        // the 'AGPolicy' policy with the 'allow-duplicates' option to prevent errors.
        // See AG-18204 for details.
        policy = window.trustedTypes.createPolicy('AGPolicy', {
          createScriptURL: function createScriptURL(arg) {
            return arg;
          }
        });
      }
      var SOURCE_PROPERTY_NAME = tagName === 'link' ? 'href' : 'src';
      var ONERROR_PROPERTY_NAME = 'onerror';
      var searchRegexp = toRegExp(match);

      // This will be needed to silent error events on matched element,
      // as url wont be available
      var setMatchedAttribute = function setMatchedAttribute(elem) {
        return elem.setAttribute(source.name, 'matched');
      };
      var setAttributeWrapper = function setAttributeWrapper(target, thisArg, args) {
        // Check if arguments are present
        if (!args[0] || !args[1]) {
          return Reflect.apply(target, thisArg, args);
        }
        var nodeName = thisArg.nodeName.toLowerCase();
        var attrName = args[0].toLowerCase();
        var attrValue = args[1];
        var isMatched = attrName === SOURCE_PROPERTY_NAME && tagName.toLowerCase() === nodeName && srcMockData[nodeName] && searchRegexp.test(attrValue);
        if (!isMatched) {
          return Reflect.apply(target, thisArg, args);
        }
        hit(source);
        setMatchedAttribute(thisArg);
        // Forward the URI that corresponds with element's MIME type
        return Reflect.apply(target, thisArg, [attrName, srcMockData[nodeName]]);
      };
      var setAttributeHandler = {
        apply: setAttributeWrapper
      };
      // eslint-disable-next-line max-len
      instance.prototype.setAttribute = new Proxy(Element.prototype.setAttribute, setAttributeHandler);
      var origSrcDescriptor = safeGetDescriptor(instance.prototype, SOURCE_PROPERTY_NAME);
      if (!origSrcDescriptor) {
        return;
      }
      Object.defineProperty(instance.prototype, SOURCE_PROPERTY_NAME, {
        enumerable: true,
        configurable: true,
        get() {
          return origSrcDescriptor.get.call(this);
        },
        set(urlValue) {
          var nodeName = this.nodeName.toLowerCase();
          var isMatched = tagName.toLowerCase() === nodeName && srcMockData[nodeName] && searchRegexp.test(urlValue);
          if (!isMatched) {
            origSrcDescriptor.set.call(this, urlValue);
            return true;
          }

          // eslint-disable-next-line no-undef
          if (policy && urlValue instanceof TrustedScriptURL) {
            var trustedSrc = policy.createScriptURL(urlValue);
            origSrcDescriptor.set.call(this, trustedSrc);
            hit(source);
            return;
          }
          setMatchedAttribute(this);
          origSrcDescriptor.set.call(this, srcMockData[nodeName]);
          hit(source);
        }
      });

      // https://github.com/AdguardTeam/Scriptlets/issues/228
      // Prevent error event being triggered by other sources
      var origOnerrorDescriptor = safeGetDescriptor(HTMLElement.prototype, ONERROR_PROPERTY_NAME);
      if (!origOnerrorDescriptor) {
        return;
      }
      Object.defineProperty(HTMLElement.prototype, ONERROR_PROPERTY_NAME, {
        enumerable: true,
        configurable: true,
        get() {
          return origOnerrorDescriptor.get.call(this);
        },
        set(cb) {
          var isMatched = this.getAttribute(source.name) === 'matched';
          if (!isMatched) {
            origOnerrorDescriptor.set.call(this, cb);
            return true;
          }
          origOnerrorDescriptor.set.call(this, noopFunc);
          return true;
        }
      });
      var addEventListenerWrapper = function addEventListenerWrapper(target, thisArg, args) {
        // Check if arguments are present
        if (!args[0] || !args[1] || !thisArg) {
          return Reflect.apply(target, thisArg, args);
        }
        var eventName = args[0];
        var isMatched = typeof thisArg.getAttribute === 'function' && thisArg.getAttribute(source.name) === 'matched' && eventName === 'error';
        if (isMatched) {
          return Reflect.apply(target, thisArg, [eventName, noopFunc]);
        }
        return Reflect.apply(target, thisArg, args);
      };
      var addEventListenerHandler = {
        apply: addEventListenerWrapper
      };
      // eslint-disable-next-line max-len
      EventTarget.prototype.addEventListener = new Proxy(EventTarget.prototype.addEventListener, addEventListenerHandler);
      var preventInlineOnerror = function preventInlineOnerror(tagName, src) {
        window.addEventListener('error', function (event) {
          if (!event.target || !event.target.nodeName || event.target.nodeName.toLowerCase() !== tagName || !event.target.src || !src.test(event.target.src)) {
            return;
          }
          hit(source);
          if (typeof event.target.onload === 'function') {
            event.target.onerror = event.target.onload;
            return;
          }
          event.target.onerror = noopFunc;
        }, true);
      };
      preventInlineOnerror(tagName, searchRegexp);
    }
    preventElementSrcLoading$1.names = ['prevent-element-src-loading'];
    preventElementSrcLoading$1.injections = [hit, toRegExp, safeGetDescriptor, noopFunc];

    /**
     * @scriptlet no-topics
     *
     * @description
     * Prevents using the Topics API.
     * https://developer.chrome.com/docs/privacy-sandbox/topics/
     *
     * ### Syntax
     *
     * ```adblock
     * example.org#%#//scriptlet('no-topics')
     * ```
     *
     * @added v1.6.18.
     */
    function noTopics$1(source) {
      var TOPICS_PROPERTY_NAME = 'browsingTopics';
      if (Document instanceof Object === false) {
        return;
      }
      if (!Object.prototype.hasOwnProperty.call(Document.prototype, TOPICS_PROPERTY_NAME) || Document.prototype[TOPICS_PROPERTY_NAME] instanceof Function === false) {
        return;
      }

      // document.browsingTopics() is async function so it's better to return noopPromiseResolve()
      // https://github.com/patcg-individual-drafts/topics#the-api-and-how-it-works
      Document.prototype[TOPICS_PROPERTY_NAME] = function () {
        return noopPromiseResolve('[]');
      };
      hit(source);
    }
    noTopics$1.names = ['no-topics'];
    noTopics$1.injections = [hit, noopPromiseResolve];

    /* eslint-disable max-len */
    /**
     * @trustedScriptlet trusted-replace-xhr-response
     *
     * @description
     * Replaces response content of `xhr` requests if **all** given parameters match.
     *
     * ### Syntax
     *
     * ```text
     * example.org#%#//scriptlet('trusted-replace-xhr-response'[, pattern, replacement[, propsToMatch]])
     * ```
     *
     * - `pattern` — optional, argument for matching contents of responseText that should be replaced.
     *   If set, `replacement` is required. Possible values:
     *     - `*` to match all text content
     *     - non-empty string
     *     - regular expression
     * - `replacement` — optional, should be set if `pattern` is set. String to replace matched content with.
     *   Empty string to remove content.
     * - `propsToMatch` — optional, string of space-separated properties to match for extra condition; possible props:
     *     - string or regular expression for matching the URL passed to `XMLHttpRequest.open()` call;
     *     - colon-separated pairs `name:value` where
     *         - `name` — string or regular expression for matching XMLHttpRequest property name
     *         - `value` — string or regular expression for matching the value of the option
     *           passed to `XMLHttpRequest.open()` call
     * - `verbose` — optional, boolean, if set to 'true' will log original and modified text content of XMLHttpRequests.
     *
     * > `verbose` may be useful for debugging but it is not allowed for prod versions of filter lists.
     *
     * > Usage with no arguments will log XMLHttpRequest objects to browser console;
     * > it may be useful for debugging but it is not allowed for prod versions of filter lists.
     *
     * ### Examples
     *
     * 1. Log all XMLHttpRequests
     *
     *     ```adblock
     *     example.org#%#//scriptlet('trusted-replace-xhr-response')
     *     ```
     *
     * 1. Replace text content of XMLHttpRequests with specific url
     *
     *     <!-- markdownlint-disable line-length -->
     *
     *     ```adblock
     *     example.org#%#//scriptlet('trusted-replace-xhr-response', 'adb_detect:true', 'adb_detect:false', 'example.org')
     *     example.org#%#//scriptlet('trusted-replace-xhr-response', '/#EXT-X-VMAP-AD-BREAK[\s\S]*?/', '#EXT-X-ENDLIST', 'example.org')
     *     ```
     *
     *     <!-- markdownlint-enable line-length -->
     *
     * 1. Remove all text content of XMLHttpRequests with specific request method
     *
     *     ```adblock
     *     example.org#%#//scriptlet('trusted-replace-xhr-response', '*', '', 'method:GET')
     *     ```
     *
     * 1. Replace text content of XMLHttpRequests matching by URL regex and request methods
     *
     *     <!-- markdownlint-disable line-length -->
     *
     *     ```adblock
     *     example.org#%#//scriptlet('trusted-replace-xhr-response', '/#EXT-X-VMAP-AD-BREAK[\s\S]*?/', '#EXT-X-ENDLIST', '/\.m3u8/ method:/GET|HEAD/')
     *     ```
     *
     *    <!-- markdownlint-enable line-length -->
     *
     * 1. Remove all text content of all XMLHttpRequests for example.com
     *
     *     ```adblock
     *     example.org#%#//scriptlet('trusted-replace-xhr-response', '*', '', 'example.com')
     *     ```
     *
     * 1. Replace "foo" text content with "bar" of all XMLHttpRequests for example.com and log original and modified text content <!-- markdownlint-disable-line line-length -->
     *
     *     ```adblock
     *     example.org#%#//scriptlet('trusted-replace-xhr-response', 'foo', 'bar', 'example.com', 'true')
     *     ```
     *
     * @added v1.7.3.
     */
    /* eslint-enable max-len */
    function trustedReplaceXhrResponse$1(source) {
      var pattern = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : '';
      var replacement = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : '';
      var propsToMatch = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : '';
      var verbose = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : false;
      // do nothing if browser does not support Proxy (e.g. Internet Explorer)
      // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy
      if (typeof Proxy === 'undefined') {
        return;
      }

      // Only allow pattern as empty string for logging purposes
      if (pattern === '' && replacement !== '') {
        var message = 'Pattern argument should not be empty string.';
        logMessage(source, message);
        return;
      }
      var shouldLog = pattern === '' && replacement === '';
      var shouldLogContent = verbose === 'true';
      var nativeOpen = window.XMLHttpRequest.prototype.open;
      var nativeSend = window.XMLHttpRequest.prototype.send;
      var xhrData;
      var openWrapper = function openWrapper(target, thisArg, args) {
        // eslint-disable-next-line prefer-spread
        xhrData = getXhrData.apply(null, args);
        if (shouldLog) {
          // Log if no propsToMatch given
          var _message = "xhr( ".concat(objectToString$1(xhrData), " )");
          logMessage(source, _message, true);
          hit(source);
          return Reflect.apply(target, thisArg, args);
        }
        if (matchRequestProps(source, propsToMatch, xhrData)) {
          thisArg.shouldBePrevented = true;
          thisArg.headersReceived = !!thisArg.headersReceived;
        }

        // Trap setRequestHeader of target xhr object to mimic request headers later
        if (thisArg.shouldBePrevented && !thisArg.headersReceived) {
          thisArg.headersReceived = true;
          thisArg.collectedHeaders = [];
          var setRequestHeaderWrapper = function setRequestHeaderWrapper(target, thisArg, args) {
            // Collect headers
            thisArg.collectedHeaders.push(args);
            return Reflect.apply(target, thisArg, args);
          };
          var setRequestHeaderHandler = {
            apply: setRequestHeaderWrapper
          };

          // setRequestHeader can only be called on open xhr object,
          // so we can safely proxy it here
          thisArg.setRequestHeader = new Proxy(thisArg.setRequestHeader, setRequestHeaderHandler);
        }
        return Reflect.apply(target, thisArg, args);
      };
      var sendWrapper = function sendWrapper(target, thisArg, args) {
        if (!thisArg.shouldBePrevented) {
          return Reflect.apply(target, thisArg, args);
        }

        /**
         * Create separate XHR request with original request's input
         * to be able to collect response data without triggering
         * listeners on original XHR object
         */
        var forgedRequest = new XMLHttpRequest();
        forgedRequest.addEventListener('readystatechange', function () {
          if (forgedRequest.readyState !== 4) {
            return;
          }
          var readyState = forgedRequest.readyState,
            response = forgedRequest.response,
            responseText = forgedRequest.responseText,
            responseURL = forgedRequest.responseURL,
            responseXML = forgedRequest.responseXML,
            status = forgedRequest.status,
            statusText = forgedRequest.statusText;

          // Extract content from response
          var content = responseText || response;
          if (typeof content !== 'string') {
            return;
          }
          var patternRegexp = pattern === '*' ? /(\n|.)*/ : toRegExp(pattern);
          if (shouldLogContent) {
            logMessage(source, "Original text content: ".concat(content));
          }
          var modifiedContent = content.replace(patternRegexp, replacement);
          if (shouldLogContent) {
            logMessage(source, "Modified text content: ".concat(modifiedContent));
          }

          // Manually put required values into target XHR object
          // as thisArg can't be redefined and XHR objects can't be (re)assigned or copied
          Object.defineProperties(thisArg, {
            // original values
            readyState: {
              value: readyState,
              writable: false
            },
            responseURL: {
              value: responseURL,
              writable: false
            },
            responseXML: {
              value: responseXML,
              writable: false
            },
            status: {
              value: status,
              writable: false
            },
            statusText: {
              value: statusText,
              writable: false
            },
            // modified values
            response: {
              value: modifiedContent,
              writable: false
            },
            responseText: {
              value: modifiedContent,
              writable: false
            }
          });

          // Mock events
          setTimeout(function () {
            var stateEvent = new Event('readystatechange');
            thisArg.dispatchEvent(stateEvent);
            var loadEvent = new Event('load');
            thisArg.dispatchEvent(loadEvent);
            var loadEndEvent = new Event('loadend');
            thisArg.dispatchEvent(loadEndEvent);
          }, 1);
          hit(source);
        });
        nativeOpen.apply(forgedRequest, [xhrData.method, xhrData.url]);

        // Mimic request headers before sending
        // setRequestHeader can only be called on open request objects
        thisArg.collectedHeaders.forEach(function (header) {
          var name = header[0];
          var value = header[1];
          forgedRequest.setRequestHeader(name, value);
        });
        thisArg.collectedHeaders = [];
        try {
          nativeSend.call(forgedRequest, args);
        } catch (_unused) {
          return Reflect.apply(target, thisArg, args);
        }
        return undefined;
      };
      var openHandler = {
        apply: openWrapper
      };
      var sendHandler = {
        apply: sendWrapper
      };
      XMLHttpRequest.prototype.open = new Proxy(XMLHttpRequest.prototype.open, openHandler);
      XMLHttpRequest.prototype.send = new Proxy(XMLHttpRequest.prototype.send, sendHandler);
    }
    trustedReplaceXhrResponse$1.names = ['trusted-replace-xhr-response'
    // trusted scriptlets support no aliases
    ];

    trustedReplaceXhrResponse$1.injections = [hit, logMessage, toRegExp, objectToString$1, matchRequestProps, getXhrData, getMatchPropsData, getRequestProps, isValidParsedData, parseMatchProps, isValidStrPattern, escapeRegExp, isEmptyObject];

    /* eslint-disable max-len */
    /**
     * @scriptlet xml-prune
     *
     * @description
     * Removes an element from the specified XML.
     *
     * Related UBO scriptlet:
     * https://github.com/gorhill/uBlock/wiki/Resources-Library#xml-prunejs-
     *
     * ### Syntax
     *
     * ```text
     * example.org#%#//scriptlet('xml-prune'[, propsToMatch[, optionalProp[, urlToMatch]]])
     * ```
     *
     * - `propsToMatch` — optional, XPath or selector of elements which will be removed from XML
     * - `optionalProp` — optional, selector of elements that must occur in XML document
     * - `urlToMatch` — optional, string or regular expression for matching the request's URL
     * - `verbose` — optional, boolean, if set to 'true' will log original and modified XML content
     *
     * > `verbose` may be useful for debugging but it is not allowed for prod versions of filter lists.
     *
     * > Usage with no arguments will log response payload and URL to browser console;
     * > it may be useful for debugging but it is not allowed for prod versions of filter lists.
     *
     * ### Examples
     *
     * 1. Remove `Period` tag whose `id` contains `-ad-` from all requests
     *
     *     ```adblock
     *     example.org#%#//scriptlet('xml-prune', 'Period[id*="-ad-"]')
     *     ```
     *
     * 1. Remove `Period` tag whose `id` contains `-ad-`, only if XML contains `SegmentTemplate`
     *
     *     ```adblock
     *     example.org#%#//scriptlet('xml-prune', 'Period[id*="-ad-"]', 'SegmentTemplate')
     *     ```
     *
     * 1. Remove `Period` tag whose `id` contains `-ad-`, only if request's URL contains `.mpd`
     *
     *     ```adblock
     *     example.org#%#//scriptlet('xml-prune', 'Period[id*="-ad-"]', '', '.mpd')
     *     ```
     *
     * 1. Remove `Period` tag whose `id` contains `-ad-`, only if request's URL contains `.mpd` and log content
     *
     *     ```adblock
     *     example.org#%#//scriptlet('xml-prune', 'Period[id*="-ad-"]', '', '.mpd', 'true')
     *     ```
     *
     * 1. Remove `Period` tag whose `id` contains `pre-roll` and remove `duration` attribute from the `Period` tag
     *    by using XPath expression
     *
     *     <!-- markdownlint-disable line-length -->
     *
     *     ```adblock
     *     example.org#%#//scriptlet('xml-prune', 'xpath(//*[name()="Period"][contains(@id, "pre-roll") and contains(@id, "-ad-")] | //*[name()="Period"]/@duration)')
     *     ```
     *
     *     <!-- markdownlint-enable line-length -->
     *
     * 1. Call with no arguments will log response payload and URL at the console
     *
     *     ```adblock
     *     example.org#%#//scriptlet('xml-prune')
     *     ```
     *
     * 1. Call with only `urlToMatch` argument will log response payload and URL only for the matched URL
     *
     *     ```adblock
     *     example.org#%#//scriptlet('xml-prune', '', '', '.mpd')
     *     ```
     *
     * @added v1.7.3.
     */
    /* eslint-enable max-len */

    function xmlPrune$1(source, propsToRemove) {
      var optionalProp = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : '';
      var urlToMatch = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : '';
      var verbose = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : false;
      // do nothing if browser does not support Reflect, fetch or Proxy (e.g. Internet Explorer)
      // https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/fetch
      // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy
      // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Reflect
      if (typeof Reflect === 'undefined' || typeof fetch === 'undefined' || typeof Proxy === 'undefined' || typeof Response === 'undefined') {
        return;
      }
      var shouldPruneResponse = false;
      var shouldLogContent = verbose === 'true';
      var urlMatchRegexp = toRegExp(urlToMatch);
      var XPATH_MARKER = 'xpath(';
      var isXpath = propsToRemove && propsToRemove.startsWith(XPATH_MARKER);

      /**
       * Checks if the document node from the XML document contains propsToRemove
       * if so, returns an array with matched elements, otherwise returns an empty array
       *
       * @param {Node} contextNode - document node from XML document
       * @returns {Array}
       */
      var getXPathElements = function getXPathElements(contextNode) {
        var matchedElements = [];
        try {
          var elementsToRemove = propsToRemove.slice(XPATH_MARKER.length, -1);
          var xpathResult = contextNode.evaluate(elementsToRemove, contextNode, null, XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE, null);
          for (var i = 0; i < xpathResult.snapshotLength; i += 1) {
            matchedElements.push(xpathResult.snapshotItem(i));
          }
        } catch (ex) {
          var message = "Invalid XPath parameter: ".concat(propsToRemove, "\n").concat(ex);
          logMessage(source, message);
        }
        return matchedElements;
      };
      var xPathPruning = function xPathPruning(xPathElements) {
        xPathElements.forEach(function (element) {
          // ELEMENT_NODE
          if (element.nodeType === 1) {
            element.remove();
            // ATTRIBUTE_NODE
          } else if (element.nodeType === 2) {
            element.ownerElement.removeAttribute(element.nodeName);
          }
        });
      };
      var isXML = function isXML(text) {
        // It's necessary to check the type of 'text'
        // because 'text' is obtained from the xhr/fetch response,
        // so it could also be Blob/ArrayBuffer/Object or another type
        if (typeof text === 'string') {
          // Check if "text" starts with "<" and check if it ends with ">"
          // If so, then it might be an XML file and should be pruned or logged
          var trimmedText = text.trim();
          if (trimmedText.startsWith('<') && trimmedText.endsWith('>')) {
            return true;
          }
        }
        return false;
      };
      var createXMLDocument = function createXMLDocument(text) {
        var xmlParser = new DOMParser();
        var xmlDocument = xmlParser.parseFromString(text, 'text/xml');
        return xmlDocument;
      };
      var isPruningNeeded = function isPruningNeeded(response, propsToRemove) {
        if (!isXML(response)) {
          return false;
        }
        var docXML = createXMLDocument(response);
        return isXpath ? getXPathElements(docXML) : !!docXML.querySelector(propsToRemove);
      };
      var pruneXML = function pruneXML(text) {
        if (!isXML(text)) {
          shouldPruneResponse = false;
          return text;
        }
        var xmlDoc = createXMLDocument(text);
        var errorNode = xmlDoc.querySelector('parsererror');
        if (errorNode) {
          return text;
        }
        if (optionalProp !== '' && xmlDoc.querySelector(optionalProp) === null) {
          shouldPruneResponse = false;
          return text;
        }
        var elements = isXpath ? getXPathElements(xmlDoc) : xmlDoc.querySelectorAll(propsToRemove);
        if (!elements.length) {
          shouldPruneResponse = false;
          return text;
        }
        if (shouldLogContent) {
          // It's necessary to clone the XML document because xmlDoc is logged with removed elements
          var cloneXmlDoc = xmlDoc.cloneNode(true);
          logMessage(source, 'Original xml:');
          logMessage(source, cloneXmlDoc, true, false);
        }
        if (isXpath) {
          xPathPruning(elements);
        } else {
          elements.forEach(function (elem) {
            elem.remove();
          });
        }
        if (shouldLogContent) {
          logMessage(source, 'Modified xml:');
          logMessage(source, xmlDoc, true, false);
        }
        var serializer = new XMLSerializer();
        text = serializer.serializeToString(xmlDoc);
        return text;
      };
      var nativeOpen = window.XMLHttpRequest.prototype.open;
      var nativeSend = window.XMLHttpRequest.prototype.send;
      var xhrData;
      var openWrapper = function openWrapper(target, thisArg, args) {
        // eslint-disable-next-line prefer-spread
        xhrData = getXhrData.apply(null, args);
        if (matchRequestProps(source, urlToMatch, xhrData)) {
          thisArg.shouldBePruned = true;
        }

        // Trap setRequestHeader of target xhr object to mimic request headers later
        if (thisArg.shouldBePruned) {
          thisArg.collectedHeaders = [];
          var setRequestHeaderWrapper = function setRequestHeaderWrapper(target, thisArg, args) {
            // Collect headers
            thisArg.collectedHeaders.push(args);
            return Reflect.apply(target, thisArg, args);
          };
          var setRequestHeaderHandler = {
            apply: setRequestHeaderWrapper
          };

          // setRequestHeader can only be called on open xhr object,
          // so we can safely proxy it here
          thisArg.setRequestHeader = new Proxy(thisArg.setRequestHeader, setRequestHeaderHandler);
        }
        return Reflect.apply(target, thisArg, args);
      };
      var sendWrapper = function sendWrapper(target, thisArg, args) {
        var allowedResponseTypeValues = ['', 'text'];
        // Do nothing if request do not match
        // or response type is not a string
        if (!thisArg.shouldBePruned || !allowedResponseTypeValues.includes(thisArg.responseType)) {
          return Reflect.apply(target, thisArg, args);
        }

        /**
         * Create separate XHR request with original request's input
         * to be able to collect response data without triggering
         * listeners on original XHR object
         */
        var forgedRequest = new XMLHttpRequest();
        forgedRequest.addEventListener('readystatechange', function () {
          if (forgedRequest.readyState !== 4) {
            return;
          }
          var readyState = forgedRequest.readyState,
            response = forgedRequest.response,
            responseText = forgedRequest.responseText,
            responseURL = forgedRequest.responseURL,
            responseXML = forgedRequest.responseXML,
            status = forgedRequest.status,
            statusText = forgedRequest.statusText;

          // Extract content from response
          var content = responseText || response;
          if (typeof content !== 'string') {
            return;
          }
          if (!propsToRemove) {
            if (isXML(response)) {
              var message = "XMLHttpRequest.open() URL: ".concat(responseURL, "\nresponse: ").concat(response);
              logMessage(source, message);
              logMessage(source, createXMLDocument(response), true, false);
            }
          } else {
            shouldPruneResponse = isPruningNeeded(response, propsToRemove);
          }
          var responseContent = shouldPruneResponse ? pruneXML(response) : response;
          // Manually put required values into target XHR object
          // as thisArg can't be redefined and XHR objects can't be (re)assigned or copied
          Object.defineProperties(thisArg, {
            // original values
            readyState: {
              value: readyState,
              writable: false
            },
            responseURL: {
              value: responseURL,
              writable: false
            },
            responseXML: {
              value: responseXML,
              writable: false
            },
            status: {
              value: status,
              writable: false
            },
            statusText: {
              value: statusText,
              writable: false
            },
            // modified values
            response: {
              value: responseContent,
              writable: false
            },
            responseText: {
              value: responseContent,
              writable: false
            }
          });

          // Mock events
          setTimeout(function () {
            var stateEvent = new Event('readystatechange');
            thisArg.dispatchEvent(stateEvent);
            var loadEvent = new Event('load');
            thisArg.dispatchEvent(loadEvent);
            var loadEndEvent = new Event('loadend');
            thisArg.dispatchEvent(loadEndEvent);
          }, 1);
          hit(source);
        });
        nativeOpen.apply(forgedRequest, [xhrData.method, xhrData.url]);

        // Mimic request headers before sending
        // setRequestHeader can only be called on open request objects
        thisArg.collectedHeaders.forEach(function (header) {
          var name = header[0];
          var value = header[1];
          forgedRequest.setRequestHeader(name, value);
        });
        thisArg.collectedHeaders = [];
        try {
          nativeSend.call(forgedRequest, args);
        } catch (_unused) {
          return Reflect.apply(target, thisArg, args);
        }
        return undefined;
      };
      var openHandler = {
        apply: openWrapper
      };
      var sendHandler = {
        apply: sendWrapper
      };
      XMLHttpRequest.prototype.open = new Proxy(XMLHttpRequest.prototype.open, openHandler);
      XMLHttpRequest.prototype.send = new Proxy(XMLHttpRequest.prototype.send, sendHandler);
      var nativeFetch = window.fetch;
      var fetchWrapper = async function fetchWrapper(target, thisArg, args) {
        var fetchURL = args[0] instanceof Request ? args[0].url : args[0];
        if (typeof fetchURL !== 'string' || fetchURL.length === 0) {
          return Reflect.apply(target, thisArg, args);
        }
        if (urlMatchRegexp.test(fetchURL)) {
          var response = await nativeFetch(...args);
          // It's required to fix issue with - Request with body": Failed to execute 'fetch' on 'Window':
          // Cannot construct a Request with a Request object that has already been used.
          // For example, it occurs on youtube when scriptlet is used without arguments
          var clonedResponse = response.clone();
          var responseText = await response.text();
          shouldPruneResponse = isPruningNeeded(responseText, propsToRemove);
          if (!shouldPruneResponse) {
            var message = "fetch URL: ".concat(fetchURL, "\nresponse text: ").concat(responseText);
            logMessage(source, message);
            logMessage(source, createXMLDocument(responseText), true, false);
            return clonedResponse;
          }
          var prunedText = pruneXML(responseText);
          if (shouldPruneResponse) {
            hit(source);
            return new Response(prunedText, {
              status: response.status,
              statusText: response.statusText,
              headers: response.headers
            });
          }
          return clonedResponse;
        }
        return Reflect.apply(target, thisArg, args);
      };
      var fetchHandler = {
        apply: fetchWrapper
      };
      window.fetch = new Proxy(window.fetch, fetchHandler);
    }
    xmlPrune$1.names = ['xml-prune',
    // aliases are needed for matching the related scriptlet converted into our syntax
    'xml-prune.js', 'ubo-xml-prune.js', 'ubo-xml-prune'];
    xmlPrune$1.injections = [hit, logMessage, toRegExp, getXhrData, objectToString$1, matchRequestProps, getMatchPropsData, getRequestProps, isValidParsedData, parseMatchProps, isValidStrPattern, escapeRegExp, isEmptyObject];

    /* eslint-disable max-len */
    /**
     * @scriptlet m3u-prune
     *
     * @description
     * Removes content from the specified M3U file.
     *
     * Related UBO scriptlet:
     * https://github.com/gorhill/uBlock/wiki/Resources-Library#m3u-prunejs-
     *
     * ### Syntax
     *
     * ```text
     * example.org#%#//scriptlet('m3u-prune'[, propsToRemove[, urlToMatch]])
     * ```
     *
     * - `propsToRemove` — optional, string or regular expression
     *   to match the URL line (segment) which will be removed alongside with its tags
     * - `urlToMatch` — optional, string or regular expression for matching the request's URL
     * - `verbose` — optional, boolean, if set to 'true' will log original and modified M3U content
     *
     * > `verbose` may be useful for debugging but it is not allowed for prod versions of filter lists.
     *
     * > Usage with no arguments will log response payload and URL to browser console;
     * > it may be useful for debugging but it is not allowed for prod versions of filter lists.
     *
     * ### Examples
     *
     * 1. Removes a tag which contains `example.com/video/`, from all requests
     *
     *     ```adblock
     *     example.org#%#//scriptlet('m3u-prune', 'example.com/video/')
     *     ```
     *
     * 1. Removes a line which contains `example.com/video/`, only if request's URL contains `.m3u8`
     *
     *     ```adblock
     *     example.org#%#//scriptlet('m3u-prune', 'example.com/video/', '.m3u8')
     *     ```
     *
     * 1. Removes a line which contains `example.com/video/`, only if request's URL contains `.m3u8` and log content
     *
     *     ```adblock
     *     example.org#%#//scriptlet('m3u-prune', 'example.com/video/', '.m3u8', 'true')
     *     ```
     *
     * 1. Call with no arguments will log response payload and URL at the console
     *
     *     ```adblock
     *     example.org#%#//scriptlet('m3u-prune')
     *     ```
     *
     * 1. Call with only `urlToMatch` argument will log response payload and URL only for the matched URL
     *
     *     ```adblock
     *     example.org#%#//scriptlet('m3u-prune', '', '.m3u8')
     *     ```
     *
     * @added v1.9.1.
     */
    /* eslint-enable max-len */

    function m3uPrune$1(source, propsToRemove) {
      var urlToMatch = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : '';
      var verbose = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : false;
      // do nothing if browser does not support fetch or Proxy (e.g. Internet Explorer)
      // https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/fetch
      // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy
      // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Reflect
      if (typeof Reflect === 'undefined' || typeof fetch === 'undefined' || typeof Proxy === 'undefined' || typeof Response === 'undefined') {
        return;
      }
      var shouldPruneResponse = false;
      var shouldLogContent = verbose === 'true';
      var urlMatchRegexp = toRegExp(urlToMatch);
      var SEGMENT_MARKER = '#';
      var AD_MARKER = {
        ASSET: '#EXT-X-ASSET:',
        CUE: '#EXT-X-CUE:',
        CUE_IN: '#EXT-X-CUE-IN',
        DISCONTINUITY: '#EXT-X-DISCONTINUITY',
        EXTINF: '#EXTINF',
        EXTM3U: '#EXTM3U',
        SCTE35: '#EXT-X-SCTE35:'
      };
      var COMCAST_AD_MARKER = {
        AD: '-AD-',
        VAST: '-VAST-',
        VMAP_AD: '-VMAP-AD-',
        VMAP_AD_BREAK: '#EXT-X-VMAP-AD-BREAK:'
      };

      // List of tags which should not be removed
      var TAGS_ALLOWLIST = ['#EXT-X-TARGETDURATION', '#EXT-X-MEDIA-SEQUENCE', '#EXT-X-DISCONTINUITY-SEQUENCE', '#EXT-X-ENDLIST', '#EXT-X-PLAYLIST-TYPE', '#EXT-X-I-FRAMES-ONLY', '#EXT-X-MEDIA', '#EXT-X-STREAM-INF', '#EXT-X-I-FRAME-STREAM-INF', '#EXT-X-SESSION-DATA', '#EXT-X-SESSION-KEY', '#EXT-X-INDEPENDENT-SEGMENTS', '#EXT-X-START'];
      var isAllowedTag = function isAllowedTag(str) {
        return TAGS_ALLOWLIST.some(function (el) {
          return str.startsWith(el);
        });
      };

      /**
       * Sets an item in array to undefined, if it contains one of the
       * AD_MARKER: AD_MARKER.EXTINF, AD_MARKER.DISCONTINUITY
       *
       * @param {Array} lines
       * @param {number} i
       * @returns {object} { array, index }
       */
      var pruneExtinfFromVmapBlock = function pruneExtinfFromVmapBlock(lines, i) {
        var array = lines.slice();
        var index = i;
        if (array[index].includes(AD_MARKER.EXTINF)) {
          array[index] = undefined;
          index += 1;
          if (array[index].includes(AD_MARKER.DISCONTINUITY)) {
            array[index] = undefined;
            index += 1;
            var prunedExtinf = pruneExtinfFromVmapBlock(array, index);
            array = prunedExtinf.array;
            index = prunedExtinf.index;
          }
        }
        return {
          array,
          index
        };
      };

      /**
       * Sets an item in array to undefined, if it contains one of the
       * COMCAST_AD_MARKER: COMCAST_AD_MARKER.VMAP_AD, COMCAST_AD_MARKER.VAST, COMCAST_AD_MARKER.AD
       *
       * @param {Array} lines
       * @returns {Array}
       */
      var pruneVmapBlock = function pruneVmapBlock(lines) {
        var array = lines.slice();
        for (var i = 0; i < array.length - 1; i += 1) {
          if (array[i].includes(COMCAST_AD_MARKER.VMAP_AD) || array[i].includes(COMCAST_AD_MARKER.VAST) || array[i].includes(COMCAST_AD_MARKER.AD)) {
            array[i] = undefined;
            if (array[i + 1].includes(AD_MARKER.EXTINF)) {
              i += 1;
              var prunedExtinf = pruneExtinfFromVmapBlock(array, i);
              array = prunedExtinf.array;
              // It's necessary to subtract 1 from "i",
              // otherwise one line will be skipped
              i = prunedExtinf.index - 1;
            }
          }
        }
        return array;
      };

      /**
       * Sets an item in array to undefined, if it contains one of the
       * AD_MARKER: AD_MARKER.CUE, AD_MARKER.ASSET, AD_MARKER.SCTE35, AD_MARKER.CUE_IN
       *
       * @param {string} line
       * @param {number} index
       * @param {Array} array
       * @returns {string|undefined}
       */

      var pruneSpliceoutBlock = function pruneSpliceoutBlock(line, index, array) {
        if (!line.startsWith(AD_MARKER.CUE)) {
          return line;
        }
        line = undefined;
        index += 1;
        if (array[index].startsWith(AD_MARKER.ASSET)) {
          array[index] = undefined;
          index += 1;
        }
        if (array[index].startsWith(AD_MARKER.SCTE35)) {
          array[index] = undefined;
          index += 1;
        }
        if (array[index].startsWith(AD_MARKER.CUE_IN)) {
          array[index] = undefined;
          index += 1;
        }
        if (array[index].startsWith(AD_MARKER.SCTE35)) {
          array[index] = undefined;
        }
        return line;
      };
      var removeM3ULineRegexp = toRegExp(propsToRemove);

      /**
       * Sets an item in array to undefined, if it contains removeM3ULineRegexp and one of the
       * AD_MARKER: AD_MARKER.EXTINF, AD_MARKER.DISCONTINUITY
       *
       * @param {string} line
       * @param {number} index
       * @param {Array} array
       * @returns {string|undefined}
       */

      var pruneInfBlock = function pruneInfBlock(line, index, array) {
        if (!line.startsWith(AD_MARKER.EXTINF)) {
          return line;
        }
        if (!removeM3ULineRegexp.test(array[index + 1])) {
          return line;
        }
        if (!isAllowedTag(array[index])) {
          array[index] = undefined;
        }
        index += 1;
        if (!isAllowedTag(array[index])) {
          array[index] = undefined;
        }
        index += 1;
        if (array[index].startsWith(AD_MARKER.DISCONTINUITY)) {
          array[index] = undefined;
        }
        return line;
      };

      /**
       * Removes block of segments (if it contains removeM3ULineRegexp) until another segment occurs
       *
       * @param {Array} lines
       * @returns {Array}
       */
      var pruneSegments = function pruneSegments(lines) {
        for (var i = 0; i < lines.length - 1; i += 1) {
          var _lines$i;
          if ((_lines$i = lines[i]) !== null && _lines$i !== void 0 && _lines$i.startsWith(SEGMENT_MARKER) && removeM3ULineRegexp.test(lines[i])) {
            var segmentName = lines[i].substring(0, lines[i].indexOf(':'));
            if (!segmentName) {
              return lines;
            }
            lines[i] = undefined;
            i += 1;
            for (var j = i; j < lines.length; j += 1) {
              if (!lines[j].includes(segmentName) && !isAllowedTag(lines[j])) {
                lines[j] = undefined;
              } else {
                i = j - 1;
                break;
              }
            }
          }
        }
        return lines;
      };

      /**
       * Determines if text contains "#EXTM3U" or "VMAP_AD_BREAK"
       *
       * @param {*} text
       * @returns {boolean}
       */
      var isM3U = function isM3U(text) {
        if (typeof text === 'string') {
          // Check if "text" starts with "#EXTM3U" or with "VMAP_AD_BREAK"
          // If so, then it might be an M3U file and should be pruned or logged
          var trimmedText = text.trim();
          return trimmedText.startsWith(AD_MARKER.EXTM3U) || trimmedText.startsWith(COMCAST_AD_MARKER.VMAP_AD_BREAK);
        }
        return false;
      };

      /**
       * Determines if pruning is needed
       *
       * @param {string} text
       * @param {RegExp} regexp
       * @returns {boolean}
       */
      var isPruningNeeded = function isPruningNeeded(text, regexp) {
        return isM3U(text) && regexp.test(text);
      };

      /**
       * Prunes lines which contain removeM3ULineRegexp and specific AD_MARKER
       *
       * @param {string} text
       * @returns {string}
       */
      // TODO: make it compatible with $hls modifier
      var pruneM3U = function pruneM3U(text) {
        if (shouldLogContent) {
          logMessage(source, "Original M3U content:\n".concat(text));
        }
        var lines = text.split(/\r?\n/);
        if (text.includes(COMCAST_AD_MARKER.VMAP_AD_BREAK)) {
          lines = pruneVmapBlock(lines);
          lines = lines.filter(function (l) {
            return !!l;
          }).join('\n');
          if (shouldLogContent) {
            logMessage(source, "Modified M3U content:\n".concat(lines));
          }
          return lines;
        }
        lines = pruneSegments(lines);
        lines = lines.map(function (line, index, array) {
          if (typeof line === 'undefined') {
            return line;
          }
          line = pruneSpliceoutBlock(line, index, array);
          if (typeof line !== 'undefined') {
            line = pruneInfBlock(line, index, array);
          }
          return line;
        }).filter(function (l) {
          return !!l;
        }).join('\n');
        if (shouldLogContent) {
          logMessage(source, "Modified M3U content:\n".concat(lines));
        }
        return lines;
      };
      var nativeOpen = window.XMLHttpRequest.prototype.open;
      var nativeSend = window.XMLHttpRequest.prototype.send;
      var xhrData;
      var openWrapper = function openWrapper(target, thisArg, args) {
        // eslint-disable-next-line prefer-spread
        xhrData = getXhrData.apply(null, args);
        if (matchRequestProps(source, urlToMatch, xhrData)) {
          thisArg.shouldBePruned = true;
        }

        // Trap setRequestHeader of target xhr object to mimic request headers later
        if (thisArg.shouldBePruned) {
          thisArg.collectedHeaders = [];
          var setRequestHeaderWrapper = function setRequestHeaderWrapper(target, thisArg, args) {
            // Collect headers
            thisArg.collectedHeaders.push(args);
            return Reflect.apply(target, thisArg, args);
          };
          var setRequestHeaderHandler = {
            apply: setRequestHeaderWrapper
          };

          // setRequestHeader can only be called on open xhr object,
          // so we can safely proxy it here
          thisArg.setRequestHeader = new Proxy(thisArg.setRequestHeader, setRequestHeaderHandler);
        }
        return Reflect.apply(target, thisArg, args);
      };
      var sendWrapper = function sendWrapper(target, thisArg, args) {
        var allowedResponseTypeValues = ['', 'text'];
        // Do nothing if request do not match
        // or response type is not a string
        if (!thisArg.shouldBePruned || !allowedResponseTypeValues.includes(thisArg.responseType)) {
          return Reflect.apply(target, thisArg, args);
        }

        /**
         * Create separate XHR request with original request's input
         * to be able to collect response data without triggering
         * listeners on original XHR object
         */
        var forgedRequest = new XMLHttpRequest();
        forgedRequest.addEventListener('readystatechange', function () {
          if (forgedRequest.readyState !== 4) {
            return;
          }
          var readyState = forgedRequest.readyState,
            response = forgedRequest.response,
            responseText = forgedRequest.responseText,
            responseURL = forgedRequest.responseURL,
            responseXML = forgedRequest.responseXML,
            status = forgedRequest.status,
            statusText = forgedRequest.statusText;

          // Extract content from response
          var content = responseText || response;
          if (typeof content !== 'string') {
            return;
          }
          if (!propsToRemove) {
            if (isM3U(response)) {
              var message = "XMLHttpRequest.open() URL: ".concat(responseURL, "\nresponse: ").concat(response);
              logMessage(source, message);
            }
          } else {
            shouldPruneResponse = isPruningNeeded(response, removeM3ULineRegexp);
          }
          var responseContent = shouldPruneResponse ? pruneM3U(response) : response;
          // Manually put required values into target XHR object
          // as thisArg can't be redefined and XHR objects can't be (re)assigned or copied
          Object.defineProperties(thisArg, {
            // original values
            readyState: {
              value: readyState,
              writable: false
            },
            responseURL: {
              value: responseURL,
              writable: false
            },
            responseXML: {
              value: responseXML,
              writable: false
            },
            status: {
              value: status,
              writable: false
            },
            statusText: {
              value: statusText,
              writable: false
            },
            // modified values
            response: {
              value: responseContent,
              writable: false
            },
            responseText: {
              value: responseContent,
              writable: false
            }
          });

          // Mock events
          setTimeout(function () {
            var stateEvent = new Event('readystatechange');
            thisArg.dispatchEvent(stateEvent);
            var loadEvent = new Event('load');
            thisArg.dispatchEvent(loadEvent);
            var loadEndEvent = new Event('loadend');
            thisArg.dispatchEvent(loadEndEvent);
          }, 1);
          hit(source);
        });
        nativeOpen.apply(forgedRequest, [xhrData.method, xhrData.url]);

        // Mimic request headers before sending
        // setRequestHeader can only be called on open request objects
        thisArg.collectedHeaders.forEach(function (header) {
          var name = header[0];
          var value = header[1];
          forgedRequest.setRequestHeader(name, value);
        });
        thisArg.collectedHeaders = [];
        try {
          nativeSend.call(forgedRequest, args);
        } catch (_unused) {
          return Reflect.apply(target, thisArg, args);
        }
        return undefined;
      };
      var openHandler = {
        apply: openWrapper
      };
      var sendHandler = {
        apply: sendWrapper
      };
      XMLHttpRequest.prototype.open = new Proxy(XMLHttpRequest.prototype.open, openHandler);
      XMLHttpRequest.prototype.send = new Proxy(XMLHttpRequest.prototype.send, sendHandler);
      var nativeFetch = window.fetch;
      var fetchWrapper = async function fetchWrapper(target, thisArg, args) {
        var fetchURL = args[0] instanceof Request ? args[0].url : args[0];
        if (typeof fetchURL !== 'string' || fetchURL.length === 0) {
          return Reflect.apply(target, thisArg, args);
        }
        if (urlMatchRegexp.test(fetchURL)) {
          var response = await nativeFetch(...args);
          // It's required to fix issue with - Request with body": Failed to execute 'fetch' on 'Window':
          // Cannot construct a Request with a Request object that has already been used.
          // For example, it occurs on youtube when scriptlet is used without arguments
          var clonedResponse = response.clone();
          var responseText = await response.text();
          // If "propsToRemove" is not defined, then response should be logged only
          if (!propsToRemove && isM3U(responseText)) {
            var message = "fetch URL: ".concat(fetchURL, "\nresponse text: ").concat(responseText);
            logMessage(source, message);
            return clonedResponse;
          }
          if (isPruningNeeded(responseText, removeM3ULineRegexp)) {
            var prunedText = pruneM3U(responseText);
            hit(source);
            return new Response(prunedText, {
              status: response.status,
              statusText: response.statusText,
              headers: response.headers
            });
          }
          return clonedResponse;
        }
        return Reflect.apply(target, thisArg, args);
      };
      var fetchHandler = {
        apply: fetchWrapper
      };
      window.fetch = new Proxy(window.fetch, fetchHandler);
    }
    m3uPrune$1.names = ['m3u-prune',
    // aliases are needed for matching the related scriptlet converted into our syntax
    'm3u-prune.js', 'ubo-m3u-prune.js', 'ubo-m3u-prune'];
    m3uPrune$1.injections = [hit, toRegExp, logMessage, getXhrData, objectToString$1, matchRequestProps, getMatchPropsData, getRequestProps, isValidParsedData, parseMatchProps, isValidStrPattern, escapeRegExp, isEmptyObject];

    /* eslint-disable max-len */
    /**
     * @trustedScriptlet trusted-set-cookie
     *
     * @description
     * Sets a cookie with arbitrary name and value,
     * and with optional ability to offset cookie attribute 'expires', set path
     * and set domain.
     *
     * ### Syntax
     *
     * ```text
     * example.org#%#//scriptlet('trusted-set-cookie', name, value[, offsetExpiresSec[, path[, domain]]])
     * ```
     *
     * - `name` — required, cookie name to be set
     * - `value` — required, cookie value. Possible values:
     *     - arbitrary value
     *     - empty string for no value
     *     - `$now$` keyword for setting current time in ms, e.g 1667915146503
     *     - `$currentDate$` keyword for setting current time as string, e.g 'Tue Nov 08 2022 13:53:19 GMT+0300'
     *     - `$currentISODate$` keyword for setting current date in the date time string format,
     *       e.g '2022-11-08T13:53:19.650Z'
     * - `offsetExpiresSec` — optional, offset from current time in seconds, after which cookie should expire;
     *   defaults to no offset. Possible values:
     *     - positive integer in seconds
     *     - `1year` keyword for setting expiration date to one year
     *     - `1day` keyword for setting expiration date to one day
     * - `path` — optional, argument for setting cookie path, defaults to `/`; possible values:
     *     - `/` — root path
     *     - `none` — to set no path at all
     * - `domain` — optional, cookie domain, if not set origin will be set as domain,
     *              if the domain does not match the origin, the cookie will not be set
     *
     * > Note that the scriptlet does not encode cookie names and values.
     * > As a result, if a cookie's name or value includes `;`,
     * > the scriptlet will not set the cookie since this may cause the cookie to break.
     *
     * ### Examples
     *
     * 1. Set cookie
     *
     *     ```adblock
     *     example.org#%#//scriptlet('trusted-set-cookie', 'cmpconsent', 'accept')
     *     example.org#%#//scriptlet('trusted-set-cookie', 'cmpconsent', '1-accept_1')
     *     ```
     *
     * 1. Set cookie with `new Date().getTime()` value
     *
     *     ```adblock
     *     example.org#%#//scriptlet('trusted-set-cookie', 'cmpconsent', '$now$')
     *     ```
     *
     * 1. Set cookie which will expire in 3 days
     *
     *     ```adblock
     *     example.org#%#//scriptlet('trusted-set-cookie', 'cmpconsent', 'accept', '259200')
     *     ```
     *
     * 1. Set cookie which will expire in one year
     *
     *     ```adblock
     *     example.org#%#//scriptlet('trusted-set-cookie', 'cmpconsent', 'accept', '1year')
     *     ```
     *
     * 1. Set cookie with no path
     *
     *     ```adblock
     *     example.org#%#//scriptlet('trusted-set-cookie', 'cmpconsent', 'decline', '', 'none')
     *
     * 1. Set cookie with domain
     *
     *     ```adblock
     *     example.org#%#//scriptlet('trusted-set-cookie', 'cmpconsent', 'decline', '', 'none', 'example.org')
     *     ```
     *
     * @added v1.7.3.
     */
    /* eslint-enable max-len */

    function trustedSetCookie$1(source, name, value) {
      var offsetExpiresSec = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : '';
      var path = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : '/';
      var domain = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : '';
      if (typeof name === 'undefined') {
        logMessage(source, 'Cookie name should be specified');
        return;
      }
      if (typeof value === 'undefined') {
        logMessage(source, 'Cookie value should be specified');
        return;
      }
      var parsedValue = parseKeywordValue(value);
      if (!isValidCookiePath(path)) {
        logMessage(source, "Invalid cookie path: '".concat(path, "'"));
        return;
      }
      if (!document.location.origin.includes(domain)) {
        logMessage(source, "Cookie domain not matched by origin: '".concat(domain, "'"));
        return;
      }
      var cookieToSet = serializeCookie(name, parsedValue, path, domain, false);
      if (!cookieToSet) {
        logMessage(source, 'Invalid cookie name or value');
        return;
      }

      // TODO: Move this concat to serializeCookie
      if (offsetExpiresSec) {
        var parsedOffsetMs = getTrustedCookieOffsetMs(offsetExpiresSec);
        if (!parsedOffsetMs) {
          logMessage(source, "Invalid offsetExpiresSec value: ".concat(offsetExpiresSec));
          return;
        }
        var expires = Date.now() + parsedOffsetMs;
        cookieToSet += "; expires=".concat(new Date(expires).toUTCString());
      }
      document.cookie = cookieToSet;
      hit(source);
    }
    trustedSetCookie$1.names = ['trusted-set-cookie'
    // trusted scriptlets support no aliases
    ];

    trustedSetCookie$1.injections = [hit, logMessage, nativeIsNaN, isCookieSetWithValue, serializeCookie, isValidCookiePath, getTrustedCookieOffsetMs, parseKeywordValue, getCookiePath];

    /* eslint-disable max-len */
    /**
     * @trustedScriptlet trusted-set-cookie-reload
     *
     * @description
     * Sets a cookie with arbitrary name and value,
     * and with optional ability to offset cookie attribute 'expires', set path
     * and set domain.
     * Also reloads the current page after the cookie setting.
     * If reloading option is not needed, use the [`trusted-set-cookie` scriptlet](#trusted-set-cookie).
     *
     * ### Syntax
     *
     * ```text
     * example.org#%#//scriptlet('trusted-set-cookie-reload', name, value[, offsetExpiresSec[, path[, domain]]])
     * ```
     *
     * - `name` — required, cookie name to be set
     * - `value` — required, cookie value. Possible values:
     *     - arbitrary value
     *     - empty string for no value
     *     - `$now$` keyword for setting current time in ms, e.g 1667915146503
     *     - `$currentDate$` keyword for setting current time as string, e.g 'Tue Nov 08 2022 13:53:19 GMT+0300'
     *     - `$currentISODate$` keyword for setting current date in the date time string format,
     *       e.g '2022-11-08T13:53:19.650Z'
     * - `offsetExpiresSec` — optional, offset from current time in seconds, after which cookie should expire;
     *   defaults to no offset. Possible values:
     *     - positive integer in seconds
     *     - `1year` keyword for setting expiration date to one year
     *     - `1day` keyword for setting expiration date to one day
     * - `path` — optional, argument for setting cookie path, defaults to `/`; possible values:
     *     - `/` — root path
     *     - `none` — to set no path at all
     * - `domain` — optional, cookie domain, if not set origin will be set as domain,
     *              if the domain does not match the origin, the cookie will not be set
     *
     * > Note that the scriptlet does not encode cookie names and values.
     * > As a result, if a cookie's name or value includes `;`,
     * > the scriptlet will not set the cookie since this may cause the cookie to break.
     *
     * ### Examples
     *
     * 1. Set cookie and reload the page after it
     *
     *     ```adblock
     *     example.org#%#//scriptlet('trusted-set-cookie-reload', 'cmpconsent', 'accept')
     *     ```
     *
     * 1. Set cookie with `new Date().getTime()` value and reload the page after it
     *
     *     ```adblock
     *     example.org#%#//scriptlet('trusted-set-cookie-reload', 'cmpconsent', '$now$')
     *     ```
     *
     * 1. Set cookie which will expire in 3 days and reload the page after it
     *
     *     ```adblock
     *     example.org#%#//scriptlet('trusted-set-cookie-reload', 'cmpconsent', 'accept', '259200')
     *     ```
     *
     * 1. Set cookie which will expire in one year and reload the page after it
     *
     *     ```adblock
     *     example.org#%#//scriptlet('trusted-set-cookie-reload', 'cmpconsent', 'accept', '1year')
     *     ```
     *
     * 1. Set cookie with no 'expire' and no path, reload the page after it
     *
     *     ```adblock
     *     example.org#%#//scriptlet('trusted-set-cookie-reload', 'cmpconsent', 'decline', '', 'none')
     *     ```
     *
     * 1. Set cookie with domain
     *
     *     ```adblock
     *     example.org#%#//scriptlet('trusted-set-cookie-reload', 'cmpconsent', 'decline', '', 'none', 'example.org')
     *     ```
     *
     * @added v1.7.10.
     */
    /* eslint-enable max-len */

    function trustedSetCookieReload$1(source, name, value) {
      var offsetExpiresSec = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : '';
      var path = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : '/';
      var domain = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : '';
      if (typeof name === 'undefined') {
        logMessage(source, 'Cookie name should be specified');
        return;
      }
      if (typeof value === 'undefined') {
        logMessage(source, 'Cookie value should be specified');
        return;
      }

      // Prevent infinite reloads if cookie was already set or blocked by the browser
      // https://github.com/AdguardTeam/Scriptlets/issues/212
      if (isCookieSetWithValue(document.cookie, name, value)) {
        return;
      }
      var parsedValue = parseKeywordValue(value);
      if (!isValidCookiePath(path)) {
        logMessage(source, "Invalid cookie path: '".concat(path, "'"));
        return;
      }
      if (!document.location.origin.includes(domain)) {
        logMessage(source, "Cookie domain not matched by origin: '".concat(domain, "'"));
        return;
      }
      var cookieToSet = serializeCookie(name, parsedValue, path, domain, false);
      if (!cookieToSet) {
        logMessage(source, 'Invalid cookie name or value');
        return;
      }

      // TODO: Move this concat to serializeCookie
      if (offsetExpiresSec) {
        var parsedOffsetMs = getTrustedCookieOffsetMs(offsetExpiresSec);
        if (!parsedOffsetMs) {
          logMessage(source, "Invalid offsetExpiresSec value: ".concat(offsetExpiresSec));
          return;
        }
        var expires = Date.now() + parsedOffsetMs;
        cookieToSet += "; expires=".concat(new Date(expires).toUTCString());
      }
      document.cookie = cookieToSet;
      hit(source);

      // Get cookie value, it's required for checking purpose
      // in case if $now$ or $currentDate$ value is used
      // https://github.com/AdguardTeam/Scriptlets/issues/291
      var cookieValueToCheck = parseCookieString(document.cookie)[name];

      // Only reload the page if cookie was set
      // https://github.com/AdguardTeam/Scriptlets/issues/212
      if (isCookieSetWithValue(document.cookie, name, cookieValueToCheck)) {
        window.location.reload();
      }
    }
    trustedSetCookieReload$1.names = ['trusted-set-cookie-reload'
    // trusted scriptlets support no aliases
    ];

    trustedSetCookieReload$1.injections = [hit, logMessage, nativeIsNaN, isCookieSetWithValue, serializeCookie, isValidCookiePath, getTrustedCookieOffsetMs, parseKeywordValue, parseCookieString, getCookiePath];

    /* eslint-disable max-len */
    /**
     * @trustedScriptlet trusted-replace-fetch-response
     *
     * @description
     * Replaces response text content of `fetch` requests if **all** given parameters match.
     *
     * ### Syntax
     *
     * ```text
     * example.org#%#//scriptlet('trusted-replace-fetch-response'[, pattern, replacement[, propsToMatch]])
     * ```
     *
     * - `pattern` — optional, argument for matching contents of responseText that should be replaced.
     * If set, `replacement` is required. Possible values:
     *     - `*` to match all text content
     *     - non-empty string
     *     - regular expression
     * - `replacement` — optional, should be set if `pattern` is set. String to replace the response text content
     *   matched by `pattern`. Empty string to remove content. Defaults to empty string.
     * - `propsToMatch` — optional, string of space-separated properties to match; possible props:
     *     - string or regular expression for matching the URL passed to fetch call;
     *       empty string, wildcard `*` or invalid regular expression will match all fetch calls
     *     - colon-separated pairs `name:value` where
     *         <!-- markdownlint-disable-next-line line-length -->
     *         - `name` is [`init` option name](https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/fetch#parameters)
     *         - `value` is string or regular expression for matching the value of the option passed to fetch call;
     *           invalid regular expression will cause any value matching
     * <!-- markdownlint-disable-next-line line-length -->
     * - `verbose` — optional, boolean, if set to 'true' will log original and modified text content of fetch responses.
     *
     * > `verbose` may be useful for debugging but it is not allowed for prod versions of filter lists.
     *
     * > Usage with no arguments will log fetch calls to browser console;
     * > it may be useful for debugging but it is not allowed for prod versions of filter lists.
     *
     * > Scriptlet does nothing if response body can't be converted to text.
     *
     * ### Examples
     *
     * 1. Log all fetch calls
     *
     *     ```adblock
     *     example.org#%#//scriptlet('trusted-replace-fetch-response')
     *     ```
     *
     * 1. Replace response text content of fetch requests with specific url
     *
     *     <!-- markdownlint-disable line-length -->
     *
     *     ```adblock
     *     example.org#%#//scriptlet('trusted-replace-fetch-response', 'adb_detect:true', 'adb_detect:false', 'example.org')
     *     example.org#%#//scriptlet('trusted-replace-fetch-response', '/#EXT-X-VMAP-AD-BREAK[\s\S]*?/', '#EXT-X-ENDLIST', 'example.org')
     *     ```
     *
     *     <!-- markdownlint-enable line-length -->
     *
     * 1. Remove all text content of fetch responses with specific request method
     *
     *     ```adblock
     *     example.org#%#//scriptlet('trusted-replace-fetch-response', '*', '', 'method:GET')
     *     ```
     *
     * 1. Replace response text content of fetch requests matching by URL regex and request methods
     *
     *     <!-- markdownlint-disable line-length -->
     *
     *     ```adblock
     *     example.org#%#//scriptlet('trusted-replace-fetch-response', '/#EXT-X-VMAP-AD-BREAK[\s\S]*?/', '#EXT-X-ENDLIST', '/\.m3u8/ method:/GET|HEAD/')
     *     ```
     *
     *     <!-- markdownlint-enable line-length -->
     *
     * 1. Remove text content of all fetch responses for example.com
     *
     *     ```adblock
     *     example.org#%#//scriptlet('trusted-replace-fetch-response', '*', '', 'example.com')
     *     ```
     *
     * 1. Replace "foo" text content with "bar" of all fetch responses for example.com and log original and modified text content <!-- markdownlint-disable-line line-length -->
     *
     *     ```adblock
     *     example.org#%#//scriptlet('trusted-replace-fetch-response', 'foo', 'bar', 'example.com', 'true')
     *     ```
     *
     * @added v1.7.3.
     */
    /* eslint-enable max-len */
    function trustedReplaceFetchResponse$1(source) {
      var pattern = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : '';
      var replacement = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : '';
      var propsToMatch = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : '';
      var verbose = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : false;
      // do nothing if browser does not support fetch or Proxy (e.g. Internet Explorer)
      // https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/fetch
      // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy
      if (typeof fetch === 'undefined' || typeof Proxy === 'undefined' || typeof Response === 'undefined') {
        return;
      }

      // Only allow pattern as empty string for logging purposes
      if (pattern === '' && replacement !== '') {
        logMessage(source, 'Pattern argument should not be empty string');
        return;
      }
      var shouldLog = pattern === '' && replacement === '';
      var shouldLogContent = verbose === 'true';
      var nativeRequestClone = Request.prototype.clone;
      var nativeFetch = fetch;
      var shouldReplace = false;
      var fetchData;
      var handlerWrapper = function handlerWrapper(target, thisArg, args) {
        fetchData = getFetchData(args, nativeRequestClone);
        if (shouldLog) {
          // log if no propsToMatch given
          logMessage(source, "fetch( ".concat(objectToString$1(fetchData), " )"), true);
          hit(source);
          return Reflect.apply(target, thisArg, args);
        }
        shouldReplace = matchRequestProps(source, propsToMatch, fetchData);
        if (!shouldReplace) {
          return Reflect.apply(target, thisArg, args);
        }

        // eslint-disable-next-line prefer-spread
        return nativeFetch.apply(null, args).then(function (response) {
          return response.text().then(function (bodyText) {
            var patternRegexp = pattern === '*' ? /(\n|.)*/ : toRegExp(pattern);
            if (shouldLogContent) {
              logMessage(source, "Original text content: ".concat(bodyText));
            }
            var modifiedTextContent = bodyText.replace(patternRegexp, replacement);
            if (shouldLogContent) {
              logMessage(source, "Modified text content: ".concat(modifiedTextContent));
            }
            var forgedResponse = forgeResponse(response, modifiedTextContent);
            hit(source);
            return forgedResponse;
          }).catch(function () {
            // log if response body can't be converted to a string
            var fetchDataStr = objectToString$1(fetchData);
            var message = "Response body can't be converted to text: ".concat(fetchDataStr);
            logMessage(source, message);
            return Reflect.apply(target, thisArg, args);
          });
        }).catch(function () {
          return Reflect.apply(target, thisArg, args);
        });
      };
      var fetchHandler = {
        apply: handlerWrapper
      };
      fetch = new Proxy(fetch, fetchHandler); // eslint-disable-line no-global-assign
    }

    trustedReplaceFetchResponse$1.names = ['trusted-replace-fetch-response'
    // trusted scriptlets support no aliases
    ];

    trustedReplaceFetchResponse$1.injections = [hit, logMessage, getFetchData, objectToString$1, matchRequestProps, forgeResponse, toRegExp, isValidStrPattern, escapeRegExp, isEmptyObject, getRequestData, getRequestProps, parseMatchProps, isValidParsedData, getMatchPropsData];

    /* eslint-disable max-len */
    /**
     * @trustedScriptlet trusted-set-local-storage-item
     *
     * @description
     * Adds item with arbitrary key and value to localStorage object, or updates the value of the key if it already exists.
     * Scriptlet won't set item if storage is full.
     *
     * ### Syntax
     *
     * ```adblock
     * example.com#%#//scriptlet('trusted-set-local-storage-item', 'key', 'value')
     * ```
     *
     * - `key` — required, key name to be set.
     * - `value` — required, key value; possible values:
     *     - arbitrary value
     *     - `$now$` keyword for setting current time in ms, corresponds to `Date.now()` and `(new Date).getTime()` calls
     *     - `$currentDate$` keyword for setting string representation of the current date and time,
     *       corresponds to `Date()` and `(new Date).toString()` calls
     *     - `$currentISODate$` keyword for setting current date in the date time string format,
     *       corresponds to `(new Date).toISOString()` call, e.g '2022-11-08T13:53:19.650Z'
     *
     * ### Examples
     *
     * 1. Set local storage item
     *
     *     ```adblock
     *     example.org#%#//scriptlet('trusted-set-local-storage-item', 'player.live.current.mute', 'false')
     *
     *     example.org#%#//scriptlet('trusted-set-local-storage-item', 'COOKIE_CONSENTS', '{"preferences":3,"flag":false}')
     *
     *     example.org#%#//scriptlet('trusted-set-local-storage-item', 'providers', '[16364,88364]')
     *
     *     example.org#%#//scriptlet('trusted-set-local-storage-item', 'providers', '{"providers":[123,456],"consent":"all"}')
     *     ```
     *
     * 1. Set item with current time since unix epoch in ms
     *
     *     ```adblock
     *     example.org#%#//scriptlet('trusted-set-local-storage-item', 'player.live.current.play', '$now$')
     *     ```
     *
     * 1. Set item with current date, e.g 'Tue Nov 08 2022 13:53:19 GMT+0300'
     *
     *     ```adblock
     *     example.org#%#//scriptlet('trusted-set-local-storage-item', 'player.live.current.play', '$currentDate$')
     *     ```
     *
     * 1. Set item without value
     *
     *     ```adblock
     *     example.org#%#//scriptlet('trusted-set-local-storage-item', 'ppu_main_none', '')
     *     ```
     *
     * @added v1.7.3.
     */
    /* eslint-enable max-len */

    function trustedSetLocalStorageItem$1(source, key, value) {
      if (typeof key === 'undefined') {
        logMessage(source, 'Item key should be specified');
        return;
      }
      if (typeof value === 'undefined') {
        logMessage(source, 'Item value should be specified');
        return;
      }
      var parsedValue = parseKeywordValue(value);
      var _window = window,
        localStorage = _window.localStorage;
      setStorageItem(source, localStorage, key, parsedValue);
      hit(source);
    }
    trustedSetLocalStorageItem$1.names = ['trusted-set-local-storage-item'
    // trusted scriptlets support no aliases
    ];

    trustedSetLocalStorageItem$1.injections = [hit, logMessage, nativeIsNaN, setStorageItem, parseKeywordValue];

    /* eslint-disable max-len */
    /**
     * @trustedScriptlet trusted-set-session-storage-item
     *
     * @description
     * Adds item with arbitrary key and value to sessionStorage object, or updates the value of the key if it already exists.
     * Scriptlet won't set item if storage is full.
     *
     * ### Syntax
     *
     * ```adblock
     * example.com#%#//scriptlet('trusted-set-session-storage-item', 'key', 'value')
     * ```
     *
     * - `key` — required, key name to be set.
     * - `value` — required, key value; possible values:
     *     - arbitrary value
     *     - `$now$` keyword for setting current time in ms, corresponds to `Date.now()` and `(new Date).getTime()` calls
     *     - `$currentDate$` keyword for setting string representation of the current date and time,
     *       corresponds to `Date()` and `(new Date).toString()` calls
     *     - `$currentISODate$` keyword for setting current date in the date time string format,
     *       corresponds to `(new Date).toISOString()` call, e.g '2022-11-08T13:53:19.650Z'
     *
     * ### Examples
     *
     * 1. Set session storage item
     *
     *     <!-- markdownlint-disable line-length -->
     *
     *     ```adblock
     *     example.org#%#//scriptlet('trusted-set-session-storage-item', 'player.live.current.mute', 'false')
     *
     *     example.org#%#//scriptlet('trusted-set-session-storage-item', 'COOKIE_CONSENTS', '{"preferences":3,"flag":false}')
     *
     *     example.org#%#//scriptlet('trusted-set-session-storage-item', 'providers', '[16364,88364]')
     *
     *     example.org#%#//scriptlet('trusted-set-session-storage-item', 'providers', '{"providers":[123,456],"consent":"all"}')
     *     ```
     *
     *     <!-- markdownlint-enable line-length -->
     *
     * 1. Set item with current time since unix epoch in ms
     *
     *     ```adblock
     *     example.org#%#//scriptlet('trusted-set-session-storage-item', 'player.live.current.play', '$now$')
     *     ```
     *
     * 1. Set item with current date, e.g 'Tue Nov 08 2022 13:53:19 GMT+0300'
     *
     *     ```adblock
     *     example.org#%#//scriptlet('trusted-set-session-storage-item', 'player.live.current.play', '$currentDate$')
     *     ```
     *
     * 1. Set item without value
     *
     *     ```adblock
     *     example.org#%#//scriptlet('trusted-set-session-storage-item', 'ppu_main_none', '')
     *     ```
     *
     * @added v1.11.16.
     */
    /* eslint-enable max-len */

    function trustedSetSessionStorageItem$1(source, key, value) {
      if (typeof key === 'undefined') {
        logMessage(source, 'Item key should be specified');
        return;
      }
      if (typeof value === 'undefined') {
        logMessage(source, 'Item value should be specified');
        return;
      }
      var parsedValue = parseKeywordValue(value);
      var _window = window,
        sessionStorage = _window.sessionStorage;
      setStorageItem(source, sessionStorage, key, parsedValue);
      hit(source);
    }
    trustedSetSessionStorageItem$1.names = ['trusted-set-session-storage-item'
    // trusted scriptlets support no aliases
    ];

    trustedSetSessionStorageItem$1.injections = [hit, logMessage, nativeIsNaN, setStorageItem, parseKeywordValue];

    /* eslint-disable max-len */
    /**
     * @trustedScriptlet trusted-set-constant
     *
     * @description
     * Creates a constant property and assigns it a specified value.
     *
     * > Actually, it's not a constant. Please note, that it can be rewritten with a value of a different type.
     *
     * > If empty object is present in chain it will be trapped until chain leftovers appear.
     *
     * > Use [set-constant](./about-scriptlets.md#set-constant) to set predefined values and functions.
     *
     * ### Syntax
     *
     * ```text
     * example.org#%#//scriptlet('trusted-set-constant', property, value[, stack])
     * ```
     *
     * - `property` — required, path to a property (joined with `.` if needed). The property must be attached to `window`.
     * - `value` — required, an arbitrary value to be set; value type is being inferred from the argument,
     *   e.g '500' will be set as number; to set string type value wrap argument into another pair of quotes: `'"500"'`;
     * - `stack` — optional, string or regular expression that must match the current function call stack trace;
     *   if regular expression is invalid it will be skipped
     *
     * ### Examples
     *
     * 1. Set property values of different types
     *
     *     ```adblock
     *     ! Set string value wrapping argument into another pair of quotes
     *     example.org#%#//scriptlet('trusted-set-constant', 'click_r', '"null"')
     *
     *     ✔ window.click_r === 'null'
     *     ✔ typeof window.click_r === 'string'
     *
     *     ! Set inferred null value
     *     example.org#%#//scriptlet('trusted-set-constant', 'click_r', 'null')
     *
     *     ✔ window.click_r === null
     *     ✔ typeof window.click_r === 'object'
     *
     *     ! Set number type value
     *     example.org#%#//scriptlet('trusted-set-constant', 'click_r', '48')
     *
     *     ✔ window.click_r === 48
     *     ✔ typeof window.click_r === 'number'
     *
     *     ! Set array or object as property value, argument should be a JSON string
     *     example.org#%#//scriptlet('trusted-set-constant', 'click_r', '[1,"string"]')
     *     example.org#%#//scriptlet('trusted-set-constant', 'click_r', '{"aaa":123,"bbb":{"ccc":"string"}}')
     *     ```
     *
     * 1. Use script stack matching to set value
     *
     *     ```adblock
     *     ! `document.first` will return `1` if the method is related to `checking.js`
     *     example.org#%#//scriptlet('trusted-set-constant', 'document.first', '1', 'checking.js')
     *
     *     ✔ document.first === 1  // if the condition described above is met
     *     ```
     *
     * @added v1.8.2.
     */
    /* eslint-enable max-len */
    function trustedSetConstant$1(source, property, value, stack) {
      if (!property || !matchStackTrace(stack, new Error().stack)) {
        return;
      }
      var constantValue;
      try {
        constantValue = inferValue(value);
      } catch (e) {
        logMessage(source, e);
        return;
      }
      var canceled = false;
      var mustCancel = function mustCancel(value) {
        if (canceled) {
          return canceled;
        }
        canceled = value !== undefined && constantValue !== undefined && typeof value !== typeof constantValue && value !== null;
        return canceled;
      };

      /**
       * Safely sets property on a given object
       *
       * IMPORTANT! this duplicates corresponding func in set-constant scriptlet as
       * reorganizing this to common helpers will most definitely complicate debugging
       *
       * @param {object} base arbitrary reachable object
       * @param {string} prop property name
       * @param {boolean} configurable if set property should be configurable
       * @param {object} handler custom property descriptor object
       * @returns {boolean} true if prop was trapped successfully
       */
      var trapProp = function trapProp(base, prop, configurable, handler) {
        if (!handler.init(base[prop])) {
          return false;
        }
        var origDescriptor = Object.getOwnPropertyDescriptor(base, prop);
        var prevSetter;
        // This is required to prevent scriptlets overwrite each over
        if (origDescriptor instanceof Object) {
          // This check is required to avoid defining non-configurable props
          if (!origDescriptor.configurable) {
            var message = "Property '".concat(prop, "' is not configurable");
            logMessage(source, message);
            return false;
          }
          base[prop] = constantValue;
          if (origDescriptor.set instanceof Function) {
            prevSetter = origDescriptor.set;
          }
        }
        Object.defineProperty(base, prop, {
          configurable,
          get() {
            return handler.get();
          },
          set(a) {
            if (prevSetter !== undefined) {
              prevSetter(a);
            }
            handler.set(a);
          }
        });
        return true;
      };

      /**
       * Traverses given chain to set constant value to its end prop
       * Chains that yet include non-object values (e.g null) are valid and will be
       * traversed when appropriate chain member is set by an external script
       *
       * IMPORTANT! this duplicates corresponding func in set-constant scriptlet as
       * reorganizing this to common helpers will most definitely complicate debugging
       *
       * @param {object} owner object that owns chain
       * @param {string} property chain of owner properties
       */
      var setChainPropAccess = function setChainPropAccess(owner, property) {
        var chainInfo = getPropertyInChain(owner, property);
        var base = chainInfo.base;
        var prop = chainInfo.prop,
          chain = chainInfo.chain;

        // Handler method init is used to keep track of factual value
        // and apply mustCancel() check only on end prop
        var inChainPropHandler = {
          factValue: undefined,
          init(a) {
            this.factValue = a;
            return true;
          },
          get() {
            return this.factValue;
          },
          set(a) {
            // Prevent breakage due to loop assignments like win.obj = win.obj
            if (this.factValue === a) {
              return;
            }
            this.factValue = a;
            if (a instanceof Object) {
              setChainPropAccess(a, chain);
            }
          }
        };
        var endPropHandler = {
          init(a) {
            if (mustCancel(a)) {
              return false;
            }
            return true;
          },
          get() {
            return constantValue;
          },
          set(a) {
            if (!mustCancel(a)) {
              return;
            }
            constantValue = a;
          }
        };

        // End prop case
        if (!chain) {
          var isTrapped = trapProp(base, prop, false, endPropHandler);
          if (isTrapped) {
            hit(source);
          }
          return;
        }

        // Null prop in chain
        if (base !== undefined && base[prop] === null) {
          trapProp(base, prop, true, inChainPropHandler);
          return;
        }

        // Empty object prop in chain
        if ((base instanceof Object || typeof base === 'object') && isEmptyObject(base)) {
          trapProp(base, prop, true, inChainPropHandler);
        }

        // Defined prop in chain
        var propValue = owner[prop];
        if (propValue instanceof Object || typeof propValue === 'object' && propValue !== null) {
          setChainPropAccess(propValue, chain);
        }

        // Undefined prop in chain
        trapProp(base, prop, true, inChainPropHandler);
      };
      setChainPropAccess(window, property);
    }
    trustedSetConstant$1.names = ['trusted-set-constant'
    // trusted scriptlets support no aliases
    ];

    trustedSetConstant$1.injections = [hit, inferValue, logMessage, noopArray, noopObject, noopFunc, noopCallbackFunc, trueFunc, falseFunc, throwFunc, noopPromiseReject, noopPromiseResolve, getPropertyInChain, setPropertyAccess, toRegExp, matchStackTrace, nativeIsNaN, isEmptyObject, getNativeRegexpTest,
    // following helpers should be imported and injected
    // because they are used by helpers above
    shouldAbortInlineOrInjectedScript, backupRegExpValues, restoreRegExpValues];

    /* eslint-disable max-len */
    /**
     * @scriptlet inject-css-in-shadow-dom
     *
     * @description
     * Injects CSS rule into selected Shadow DOM subtrees on a page
     *
     * ### Syntax
     *
     * ```text
     * example.org#%#//scriptlet('inject-css-in-shadow-dom', cssRule[, hostSelector])
     * ```
     *
     * - `cssRule` — required, string representing a single css rule
     * - `hostSelector` — optional, string, selector to match shadow host elements.
     *   CSS rule will be only applied to shadow roots inside these elements.
     *   Defaults to injecting css rule into all available roots.
     *
     * ### Examples
     *
     * 1. Apply style to all shadow dom subtrees
     *
     *     ```adblock
     *     example.org#%#//scriptlet('inject-css-in-shadow-dom', '#advertisement { display: none !important; }')
     *     ```
     *
     * 1. Apply style to a specific shadow dom subtree
     *
     *     ```adblock
     *     example.org#%#//scriptlet('inject-css-in-shadow-dom', '#content { margin-top: 0 !important; }', '#banner')
     *     ```
     *
     * @added v1.8.2.
     */
    /* eslint-enable max-len */

    function injectCssInShadowDom$1(source, cssRule) {
      var hostSelector = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : '';
      // do nothing if browser does not support ShadowRoot, Proxy or Reflect
      // https://developer.mozilla.org/en-US/docs/Web/API/ShadowRoot
      if (!Element.prototype.attachShadow || typeof Proxy === 'undefined' || typeof Reflect === 'undefined') {
        return;
      }

      // Prevent url() and image-set() styles from being applied
      if (cssRule.match(/(url|image-set)\(.*\)/i)) {
        logMessage(source, '"url()" function is not allowed for css rules');
        return;
      }
      var callback = function callback(shadowRoot) {
        try {
          // adoptedStyleSheets and CSSStyleSheet constructor are not yet supported by Safari
          // https://developer.mozilla.org/en-US/docs/Web/API/Document/adoptedStyleSheets
          // https://developer.mozilla.org/en-US/docs/Web/API/CSSStyleSheet/CSSStyleSheet
          var stylesheet = new CSSStyleSheet();
          try {
            stylesheet.insertRule(cssRule);
          } catch (e) {
            logMessage(source, "Unable to apply the rule '".concat(cssRule, "' due to: \n'").concat(e.message, "'"));
            return;
          }
          shadowRoot.adoptedStyleSheets = [...shadowRoot.adoptedStyleSheets, stylesheet];
        } catch (_unused) {
          var styleTag = document.createElement('style');
          styleTag.innerText = cssRule;
          shadowRoot.appendChild(styleTag);
        }
        hit(source);
      };
      hijackAttachShadow(window, hostSelector, callback);
    }
    injectCssInShadowDom$1.names = ['inject-css-in-shadow-dom'];
    injectCssInShadowDom$1.injections = [hit, logMessage, hijackAttachShadow];

    /* eslint-disable max-len */
    /**
     * @scriptlet remove-node-text
     *
     * @description
     * Removes text from DOM nodes.
     *
     * Related UBO scriptlet:
     * https://github.com/gorhill/uBlock/commit/2bb446797a12086f2eebc0c8635b671b8b90c477
     *
     * ### Syntax
     *
     * ```adblock
     * example.org#%#//scriptlet('remove-node-text', nodeName, condition)
     * ```
     *
     * - `nodeName` — required, string or RegExp, specifies DOM node name from which the text will be removed.
     * Must target lowercased node names, e.g `div` instead of `DIV`.
     * - `textMatch` — required, string or RegExp to match against node's text content.
     * If matched, the whole text will be removed. Case sensitive.
     *
     * ### Examples
     *
     * 1. Remove node's text content:
     *
     *     ```adblock
     *     example.org#%#//scriptlet('remove-node-text', 'div', 'some text')
     *     ```
     *
     *     ```html
     *     <!-- before -->
     *     <div>some text</div>
     *     <span>some text</span>
     *
     *     <!-- after -->
     *     <div></div   >
     *     <span>some text</span>
     *     ```
     *
     * 2. Remove node's text content, matching both node name and condition by RegExp:
     *
     *     ```adblock
     *     example.org#%#//scriptlet('remove-node-text', '/[a-z]*[0-9]/', '/text/')
     *     ```
     *
     *     ```html
     *     <!-- before -->
     *     <qrce3>some text</qrce3>
     *     <span>some text</span>
     *
     *     <!-- after -->
     *     <qrce3></qrce3>
     *     <span>some text</span>
     *     ```
     *
     * @added v1.9.37.
     */
    /* eslint-enable max-len */
    function removeNodeText$1(source, nodeName, textMatch) {
      var _parseNodeTextParams = parseNodeTextParams(nodeName, textMatch),
        selector = _parseNodeTextParams.selector,
        nodeNameMatch = _parseNodeTextParams.nodeNameMatch,
        textContentMatch = _parseNodeTextParams.textContentMatch;

      /**
       * Handles nodes by removing text content of matched nodes
       *
       * Note: instead of drilling down all the arguments for both replace-node-text
       * and trusted-replace-node-text scriptlets, only the handler is being passed
       *
       * @param {Node[]} nodes nodes to handle
       * @returns {void}
       */
      var handleNodes = function handleNodes(nodes) {
        return nodes.forEach(function (node) {
          var shouldReplace = isTargetNode(node, nodeNameMatch, textContentMatch);
          if (shouldReplace) {
            var ALL_TEXT_PATTERN = /^[\s\S]*$/;
            var REPLACEMENT = '';
            replaceNodeText(source, node, ALL_TEXT_PATTERN, REPLACEMENT);
          }
        });
      };

      // Apply dedicated handler to already rendered nodes...
      if (document.documentElement) {
        handleExistingNodes(selector, handleNodes);
      }

      // and newly added nodes
      observeDocumentWithTimeout(function (mutations) {
        return handleMutations(mutations, handleNodes);
      });
    }
    removeNodeText$1.names = ['remove-node-text',
    // aliases are needed for matching the related scriptlet converted into our syntax
    'remove-node-text.js', 'ubo-remove-node-text.js', 'rmnt.js', 'ubo-rmnt.js', 'ubo-remove-node-text', 'ubo-rmnt'];
    removeNodeText$1.injections = [observeDocumentWithTimeout, handleExistingNodes, handleMutations, replaceNodeText, isTargetNode, parseNodeTextParams,
    // following helpers should be imported and injected
    // because they are used by helpers above
    hit, nodeListToArray, getAddedNodes, toRegExp];

    /* eslint-disable max-len */
    /**
     * @trustedScriptlet trusted-replace-node-text
     *
     * @description
     * Replaces text in text content of matched DOM nodes.
     *
     * ### Syntax
     *
     * ```text
     * example.org#%#//scriptlet('trusted-replace-node-text', nodeName, textMatch, pattern, replacement)
     * ```
     *
     * - `nodeName` — required, string or RegExp, specifies DOM node name from which the text will be removed.
     * Must target lowercased node names, e.g `div` instead of `DIV`.
     * - `textMatch` — required, string or RegExp to match against node's text content.
     * If matched, the `pattern` will be replaced by the `replacement`. Case sensitive.
     * - `pattern` — required, string or regexp for matching contents of `node.textContent` that should be replaced.
     * - `replacement` — required, string to replace text content matched by `pattern`.
     * - `...extraArgs` — optional, string, if includes 'verbose' will log original and modified text content.
     *
     * > `verbose` may be useful for debugging but it is not allowed for prod versions of filter lists.
     *
     * ### Examples
     *
     * 1. Replace node's text content:
     *
     *     ```adblock
     *     example.org#%#//scriptlet('trusted-replace-node-text', 'div', 'some', 'text', 'other text')
     *     ```
     *
     *     ```html
     *     <!-- before -->
     *     <div>some text</div>
     *     <div>text</div>
     *     <span>some text</span>
     *
     *     <!-- after -->
     *     <div>some other text</div>
     *     <div>text</div>
     *     <span>some text</span>
     *     ```
     *
     * 2. Replace node's text content, matching both node name, text and pattern by RegExp:
     *
     *     ```adblock
     *     example.org#%#//scriptlet('trusted-replace-node-text', '/[a-z]*[0-9]/', '/s\dme/', '/t\dxt/', 'other text')
     *     ```
     *
     *     ```html
     *     <!-- before -->
     *     <qrce3>s0me t3xt</qrce3> // this node is going to be matched by both node name and text
     *     <qrce3>text</qrce3> // this node won't be matched by text content nor text content
     *     <span>some text</span>
     *
     *     <!-- after -->
     *     <qrce3>s0me other text</qrce3> // text content has changed
     *     <qrce3>text</qrce3>
     *     <span>some text</span>
     *     ```
     *
     * 3. Replace node's text content and log original and modified text content:
     *
     *     ```adblock
     *     example.org#%#//scriptlet('trusted-replace-node-text', 'div', 'some', 'text', 'other text', 'verbose')
     *     ```
     *
     * @added v1.9.37.
     */
    /* eslint-enable max-len */
    function trustedReplaceNodeText$1(source, nodeName, textMatch, pattern, replacement) {
      var _parseNodeTextParams = parseNodeTextParams(nodeName, textMatch, pattern),
        selector = _parseNodeTextParams.selector,
        nodeNameMatch = _parseNodeTextParams.nodeNameMatch,
        textContentMatch = _parseNodeTextParams.textContentMatch,
        patternMatch = _parseNodeTextParams.patternMatch;
      for (var _len = arguments.length, extraArgs = new Array(_len > 5 ? _len - 5 : 0), _key = 5; _key < _len; _key++) {
        extraArgs[_key - 5] = arguments[_key];
      }
      var shouldLog = extraArgs.includes('verbose');

      /**
       * Handles nodes by removing text content of matched nodes
       *
       * Note: instead of drilling down all the arguments for both replace-node-text
       * and trusted-replace-node-text scriptlets, only the handler is being passed
       *
       * @param {Node[]} nodes nodes to handle
       * @returns {void}
       */
      var handleNodes = function handleNodes(nodes) {
        return nodes.forEach(function (node) {
          var shouldReplace = isTargetNode(node, nodeNameMatch, textContentMatch);
          if (shouldReplace) {
            if (shouldLog) {
              var originalText = node.textContent;
              if (originalText) {
                logMessage(source, "Original text content: ".concat(originalText));
              }
            }
            replaceNodeText(source, node, patternMatch, replacement);
            if (shouldLog) {
              var modifiedText = node.textContent;
              if (modifiedText) {
                logMessage(source, "Modified text content: ".concat(modifiedText));
              }
            }
          }
        });
      };

      // Apply dedicated handler to already rendered nodes...
      if (document.documentElement) {
        handleExistingNodes(selector, handleNodes);
      }

      // and newly added nodes
      observeDocumentWithTimeout(function (mutations) {
        return handleMutations(mutations, handleNodes);
      });
    }
    trustedReplaceNodeText$1.names = ['trusted-replace-node-text'
    // trusted scriptlets support no aliases
    ];

    trustedReplaceNodeText$1.injections = [observeDocumentWithTimeout, handleExistingNodes, handleMutations, replaceNodeText, isTargetNode, parseNodeTextParams, logMessage,
    // following helpers should be imported and injected
    // because they are used by helpers above
    hit, nodeListToArray, getAddedNodes, toRegExp];

    /* eslint-disable max-len */
    /**
     * @scriptlet evaldata-prune
     *
     * @description
     * Removes specified properties from the result of calling eval (if payloads contains `Object`) and returns to the caller.
     *
     * Related UBO scriptlet:
     * https://github.com/gorhill/uBlock/commit/c8de9041917b61035171e454df886706f27fc4f3
     *
     * ### Syntax
     *
     * ```text
     * example.org#%#//scriptlet('evaldata-prune'[, propsToRemove [, obligatoryProps [, stack]]])
     * ```
     *
     * - `propsToRemove` — optional, string of space-separated properties to remove
     * - `obligatoryProps` — optional, string of space-separated properties
     *   which must be all present for the pruning to occur
     * - `stack` — optional, string or regular expression that must match the current function call stack trace;
     *   if regular expression is invalid it will be skipped
     *
     * > Note please that you can use wildcard `*` for chain property name,
     * > e.g. `ad.*.src` instead of `ad.0.src ad.1.src ad.2.src`.
     *
     * ### Examples
     *
     * 1. Removes property `example` from the payload of the eval call
     *
     *     ```adblock
     *     example.org#%#//scriptlet('evaldata-prune', 'example')
     *     ```
     *
     *     For instance, the following call will return `{ one: 1}`
     *
     *     ```html
     *     eval({ one: 1, example: true })
     *     ```
     *
     * 2. If there are no specified properties in the payload of eval call, pruning will NOT occur
     *
     *     ```adblock
     *     example.org#%#//scriptlet('evaldata-prune', 'one', 'obligatoryProp')
     *     ```
     *
     *     For instance, the following call will return `{ one: 1, two: 2}`
     *
     *     ```html
     *     JSON.parse('{"one":1,"two":2}')
     *     ```
     *
     * 3. A property in a list of properties can be a chain of properties
     *
     *     ```adblock
     *     example.org#%#//scriptlet('evaldata-prune', 'a.b', 'ads.url.first')
     *     ```
     *
     * 4. Removes property `content.ad` from the payload of eval call if its error stack trace contains `test.js`
     *
     *     ```adblock
     *     example.org#%#//scriptlet('evaldata-prune', 'content.ad', '', 'test.js')
     *     ```
     *
     * 5. A property in a list of properties can be a chain of properties with wildcard in it
     *
     *     ```adblock
     *     example.org#%#//scriptlet('evaldata-prune', 'content.*.media.src', 'content.*.media.ad')
     *     ```
     *
     * 6. Call with no arguments will log the current hostname and object payload at the console
     *
     *     ```adblock
     *     example.org#%#//scriptlet('evaldata-prune')
     *     ```
     *
     * 7. Call with only second argument will log the current hostname and matched object payload at the console
     *
     *     ```adblock
     *     example.org#%#//scriptlet('evaldata-prune', '', '"id":"117458"')
     *     ```
     *
     * @added v1.9.37.
     */
    /* eslint-enable max-len */
    function evalDataPrune$1(source, propsToRemove, requiredInitialProps, stack) {
      var prunePaths = getPrunePath(propsToRemove);
      var requiredPaths = getPrunePath(requiredInitialProps);
      var nativeObjects = {
        nativeStringify: window.JSON.stringify
      };
      var evalWrapper = function evalWrapper(target, thisArg, args) {
        var data = Reflect.apply(target, thisArg, args);
        if (typeof data === 'object') {
          data = jsonPruner(source, data, prunePaths, requiredPaths, stack, nativeObjects);
        }
        return data;
      };
      var evalHandler = {
        apply: evalWrapper
      };
      // eslint-disable-next-line no-eval
      window.eval = new Proxy(window.eval, evalHandler);
    }
    evalDataPrune$1.names = ['evaldata-prune',
    // aliases are needed for matching the related scriptlet converted into our syntax
    'evaldata-prune.js', 'ubo-evaldata-prune.js', 'ubo-evaldata-prune'];
    evalDataPrune$1.injections = [hit, matchStackTrace, getWildcardPropertyInChain, logMessage, toRegExp, isPruningNeeded, jsonPruner, getPrunePath,
    // following helpers are needed for helpers above
    getNativeRegexpTest, shouldAbortInlineOrInjectedScript, backupRegExpValues, restoreRegExpValues];

    /* eslint-disable max-len */
    /**
     * @trustedScriptlet trusted-prune-inbound-object
     *
     * @description
     * Removes listed properties from the result of calling specific function (if payload contains `Object`)
     * and returns to the caller.
     *
     * Related UBO scriptlet:
     * https://github.com/gorhill/uBlock/commit/1c9da227d7
     *
     * ### Syntax
     *
     * ```text
     * example.org#%#//scriptlet('trusted-prune-inbound-object', functionName[, propsToRemove [, obligatoryProps [, stack]]])
     * ```
     *
     * - `functionName` — required, the name of the function to trap, it must have an object as an argument
     * - `propsToRemove` — optional, string of space-separated properties to remove
     * - `obligatoryProps` — optional, string of space-separated properties
     *   which must be all present for the pruning to occur
     * - `stack` — optional, string or regular expression that must match the current function call stack trace;
     *   if regular expression is invalid it will be skipped
     *
     * > Note please that you can use wildcard `*` for chain property name,
     * > e.g. `ad.*.src` instead of `ad.0.src ad.1.src ad.2.src`.
     *
     * ### Examples
     *
     * 1. Removes property `example` from the payload of the Object.getOwnPropertyNames call
     *
     *     ```adblock
     *     example.org#%#//scriptlet('trusted-prune-inbound-object', 'Object.getOwnPropertyNames', 'example')
     *     ```
     *
     *     For instance, the following call will return `['one']`
     *
     *     ```html
     *     Object.getOwnPropertyNames({ one: 1, example: true })
     *     ```
     *
     * 2. Removes property `ads` from the payload of the Object.keys call
     *
     *     ```adblock
     *     example.org#%#//scriptlet('trusted-prune-inbound-object', 'Object.keys', 'ads')
     *     ```
     *
     *     For instance, the following call will return `['one', 'two']`
     *
     *     ```html
     *     Object.keys({ one: 1, two: 2, ads: true })
     *     ```
     *
     * 3. Removes property `foo.bar` from the payload of the JSON.stringify call
     *
     *     ```adblock
     *     example.org#%#//scriptlet('trusted-prune-inbound-object', 'JSON.stringify', 'foo.bar')
     *     ```
     *
     *     For instance, the following call will return `'{"foo":{"a":2},"b":3}'`
     *
     *     ```html
     *     JSON.stringify({ foo: { bar: 1, a: 2 }, b: 3 })
     *     ```
     *
     * 4. Removes property `foo.bar` from the payload of the JSON.stringify call if its error stack trace contains `test.js`
     *
     *     ```adblock
     *     example.org#%#//scriptlet('trusted-prune-inbound-object', 'JSON.stringify', 'foo.bar', '', 'test.js')
     *     ```
     *
     * 5. Call with only first and third argument will log the current hostname and matched payload at the console
     *
     *     ```adblock
     *     example.org#%#//scriptlet('trusted-prune-inbound-object', 'JSON.stringify', '', 'bar', '')
     *     ```
     *
     * @added v1.9.91.
     */
    /* eslint-enable max-len */
    function trustedPruneInboundObject$1(source, functionName, propsToRemove, requiredInitialProps) {
      var stack = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : '';
      if (!functionName) {
        return;
      }
      var nativeObjects = {
        nativeStringify: window.JSON.stringify
      };
      var _getPropertyInChain = getPropertyInChain(window, functionName),
        base = _getPropertyInChain.base,
        prop = _getPropertyInChain.prop;
      if (!base || !prop || typeof base[prop] !== 'function') {
        var message = "".concat(functionName, " is not a function");
        logMessage(source, message);
        return;
      }
      var prunePaths = getPrunePath(propsToRemove);
      var requiredPaths = getPrunePath(requiredInitialProps);
      var objectWrapper = function objectWrapper(target, thisArg, args) {
        var data = args[0];
        if (typeof data === 'object') {
          data = jsonPruner(source, data, prunePaths, requiredPaths, stack, nativeObjects);
          args[0] = data;
        }
        return Reflect.apply(target, thisArg, args);
      };
      var objectHandler = {
        apply: objectWrapper
      };
      base[prop] = new Proxy(base[prop], objectHandler);
    }
    trustedPruneInboundObject$1.names = ['trusted-prune-inbound-object'
    // trusted scriptlets support no aliases
    ];

    trustedPruneInboundObject$1.injections = [hit, matchStackTrace, getPropertyInChain, getWildcardPropertyInChain, logMessage, isPruningNeeded, jsonPruner, getPrunePath,
    // following helpers are needed for helpers above
    toRegExp, getNativeRegexpTest, shouldAbortInlineOrInjectedScript, isEmptyObject, backupRegExpValues, restoreRegExpValues];

    /* eslint-disable max-len */
    /**
     * @trustedScriptlet trusted-set-attr
     *
     * @description
     * Sets attribute with arbitrary value on the specified elements. This scriptlet runs once when the page loads
     * and after that on DOM tree changes.
     *
     * ### Syntax
     *
     * ```text
     * example.org#%#//scriptlet('trusted-set-attr', selector, attr[, value])
     * ```
     *
     * - `selector` — required, CSS selector, specifies DOM nodes to set attributes on
     * - `attr` — required, attribute to be set
     * - `value` — optional, the value to assign to the attribute, defaults to ''.
     *
     * ### Examples
     *
     * 1. Set attribute by selector
     *
     *     ```adblock
     *     example.org#%#//scriptlet('trusted-set-attr', 'div.class > a.class', 'test-attribute', '[true, true]')
     *     ```
     *
     *     ```html
     *     <!-- before -->
     *     <div>
     *         <a>Another text</a>
     *         <a class="class">Some text</a>
     *     </div>
     *
     *     <!-- after -->
     *     <div>
     *         <a>Another text</a>
     *         <a class="class" test-attribute="[true, true]">Some text</a>
     *     </div>
     *     ```
     *
     * 1. Set attribute without value
     *
     *     ```adblock
     *     example.org#%#//scriptlet('trusted-set-attr', 'a.class', 'test-attribute')
     *     ```
     *
     *     ```html
     *     <!-- before -->
     *     <a class="class">Some text</div>
     *
     *     <!-- after -->
     *     <a class="class" test-attribute>Some text</div>
     *     ```
     *
     * 1. Set attribute value to `MTIzNTY=`
     *
     *     ```adblock
     *     example.org#%#//scriptlet('trusted-set-attr', 'a.class', 'test-attribute', 'MTIzNTY=')
     *     ```
     *
     *     ```html
     *     <!-- before -->
     *     <a class="class">Some text</div>
     *
     *     <!-- after -->
     *     <a class="class" test-attribute="MTIzNTY=">Some text</div>
     *     ```
     *
     * 1. Set attribute value to `{ playback: false }`
     *
     *     ```adblock
     *     example.org#%#//scriptlet('trusted-set-attr', 'a.class', 'test-attribute', '{ playback: false }')
     *     ```
     *
     *     ```html
     *     <!-- before -->
     *     <a class="class">Some text</div>
     *
     *     <!-- after -->
     *     <a class="class" test-attribute="{ playback: false }">Some text</div>
     *     ```
     *
     * @added v1.10.1.
     */
    /* eslint-enable max-len */
    function trustedSetAttr$1(source, selector, attr) {
      var value = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : '';
      if (!selector || !attr) {
        return;
      }
      setAttributeBySelector(source, selector, attr, value);
      observeDOMChanges(function () {
        return setAttributeBySelector(source, selector, attr, value);
      }, true);
    }
    trustedSetAttr$1.names = ['trusted-set-attr'
    // trusted scriptlets support no aliases
    ];

    trustedSetAttr$1.injections = [setAttributeBySelector, observeDOMChanges, nativeIsNaN,
    // following helpers should be imported and injected
    // because they are used by helpers above
    defaultAttributeSetter, logMessage, throttle, hit];

    /* eslint-disable max-len */
    /**
     * @scriptlet spoof-css
     *
     * @description
     * Spoof CSS property value when `getComputedStyle()` or `getBoundingClientRect()` methods is called.
     *
     * Related UBO scriptlet:
     * https://github.com/gorhill/uBlock/wiki/Resources-Library#spoof-cssjs-
     *
     * ### Syntax
     *
     * ```text
     * example.org#%#//scriptlet('spoof-css', selectors, cssNameProperty, cssNameValue)
     * ```
     *
     * - `selectors` — string of comma-separated selectors to match
     * - `cssPropertyName` — CSS property name
     * - `cssPropertyValue` — CSS property value
     *
     * > Call with `debug` as `cssPropertyName` and `truthy` value as `cssPropertyValue` will trigger debugger statement
     * > when `getComputedStyle()` or `getBoundingClientRect()` methods is called.
     * > It may be useful for debugging but it is not allowed for prod versions of filter lists.
     *
     * ### Examples
     *
     * 1. Spoof CSS property value `display` to `block` for all elements with class `adsbygoogle`:
     *
     *     ```adblock
     *     example.org#%#//scriptlet('spoof-css', '.adsbygoogle', 'display', 'block')
     *     ```
     *
     * 2. Spoof CSS property value `height` to `100` for all elements with class `adsbygoogle` and `advert`:
     *
     *     ```adblock
     *     example.org#%#//scriptlet('spoof-css', '.adsbygoogle, .advert', 'height', '100')
     *     ```
     *
     * 3. To invoke debugger statement:
     *
     *     ```adblock
     *     example.org#%#//scriptlet('spoof-css', '.adsbygoogle', 'debug', 'true')
     *     ```
     *
     *
     * @added v1.10.1.
     */
    /* eslint-enable max-len */

    function spoofCSS$1(source, selectors, cssPropertyName, cssPropertyValue) {
      if (!selectors) {
        return;
      }
      var uboAliases = ['spoof-css.js', 'ubo-spoof-css.js', 'ubo-spoof-css'];

      /**
       * getComputedStyle uses camelCase version of CSS properties
       * for example, "clip-path" is displayed as "clipPath"
       * so it's needed to convert CSS property to camelCase
       *
       * @param {string} cssProperty
       * @returns {string} camelCase version of CSS property
       */
      function convertToCamelCase(cssProperty) {
        if (!cssProperty.includes('-')) {
          return cssProperty;
        }
        var splittedProperty = cssProperty.split('-');
        var firstPart = splittedProperty[0];
        var secondPart = splittedProperty[1];
        return "".concat(firstPart).concat(secondPart[0].toUpperCase()).concat(secondPart.slice(1));
      }
      var shouldDebug = !!(cssPropertyName === 'debug' && cssPropertyValue);
      var propToValueMap = new Map();

      /**
       * UBO spoof-css analog has it's own args sequence:
       * (selectors, ...arguments)
       * arguments contains property-name/property-value pairs, all separated by commas
       *
       * example.com##+js(spoof-css, a[href="x.com"]\, .ads\, .bottom, clip-path, none)
       * example.com##+js(spoof-css, .ad, clip-path, none, display, block)
       * example.com##+js(spoof-css, .ad, debug, 1)
       */
      if (uboAliases.includes(source.name)) {
        var args = source.args;
        var arrayOfProperties = [];
        // Check if one before last argument is 'debug'
        var isDebug = args.at(-2);
        if (isDebug === 'debug') {
          // If it's debug, then we need to skip first (selectors) and last two arguments
          arrayOfProperties = args.slice(1, -2);
        } else {
          // If it's not debug, then we need to skip only first (selectors) argument
          arrayOfProperties = args.slice(1);
        }
        for (var i = 0; i < arrayOfProperties.length; i += 2) {
          if (arrayOfProperties[i] === '') {
            break;
          }
          propToValueMap.set(convertToCamelCase(arrayOfProperties[i]), arrayOfProperties[i + 1]);
        }
      } else if (cssPropertyName && cssPropertyValue && !shouldDebug) {
        propToValueMap.set(convertToCamelCase(cssPropertyName), cssPropertyValue);
      }
      var spoofStyle = function spoofStyle(cssProperty, realCssValue) {
        return propToValueMap.has(cssProperty) ? propToValueMap.get(cssProperty) : realCssValue;
      };
      var setRectValue = function setRectValue(rect, prop, value) {
        Object.defineProperty(rect, prop, {
          value: parseFloat(value)
        });
      };
      var getter = function getter(target, prop, receiver) {
        hit(source);
        if (prop === 'toString') {
          return target.toString.bind(target);
        }
        return Reflect.get(target, prop, receiver);
      };
      var getComputedStyleWrapper = function getComputedStyleWrapper(target, thisArg, args) {
        if (shouldDebug) {
          debugger; // eslint-disable-line no-debugger
        }

        var style = Reflect.apply(target, thisArg, args);
        if (!args[0].matches(selectors)) {
          return style;
        }
        var proxiedStyle = new Proxy(style, {
          get(target, prop) {
            var CSSStyleProp = target[prop];
            if (typeof CSSStyleProp !== 'function') {
              return spoofStyle(prop, CSSStyleProp || '');
            }
            if (prop !== 'getPropertyValue') {
              return CSSStyleProp.bind(target);
            }
            var getPropertyValueFunc = new Proxy(CSSStyleProp, {
              apply(target, thisArg, args) {
                var cssName = args[0];
                var cssValue = thisArg[cssName];
                return spoofStyle(cssName, cssValue);
              },
              get: getter
            });
            return getPropertyValueFunc;
          },
          getOwnPropertyDescriptor(target, prop) {
            if (propToValueMap.has(prop)) {
              return {
                configurable: true,
                enumerable: true,
                value: propToValueMap.get(prop),
                writable: true
              };
            }
            return Reflect.getOwnPropertyDescriptor(target, prop);
          }
        });
        hit(source);
        return proxiedStyle;
      };
      var getComputedStyleHandler = {
        apply: getComputedStyleWrapper,
        get: getter
      };
      window.getComputedStyle = new Proxy(window.getComputedStyle, getComputedStyleHandler);
      var getBoundingClientRectWrapper = function getBoundingClientRectWrapper(target, thisArg, args) {
        if (shouldDebug) {
          debugger; // eslint-disable-line no-debugger
        }

        var rect = Reflect.apply(target, thisArg, args);
        if (!thisArg.matches(selectors)) {
          return rect;
        }
        var top = rect.top,
          bottom = rect.bottom,
          height = rect.height,
          width = rect.width,
          left = rect.left,
          right = rect.right;
        var newDOMRect = new window.DOMRect(rect.x, rect.y, top, bottom, width, height, left, right);
        if (propToValueMap.has('top')) {
          setRectValue(newDOMRect, 'top', propToValueMap.get('top'));
        }
        if (propToValueMap.has('bottom')) {
          setRectValue(newDOMRect, 'bottom', propToValueMap.get('bottom'));
        }
        if (propToValueMap.has('left')) {
          setRectValue(newDOMRect, 'left', propToValueMap.get('left'));
        }
        if (propToValueMap.has('right')) {
          setRectValue(newDOMRect, 'right', propToValueMap.get('right'));
        }
        if (propToValueMap.has('height')) {
          setRectValue(newDOMRect, 'height', propToValueMap.get('height'));
        }
        if (propToValueMap.has('width')) {
          setRectValue(newDOMRect, 'width', propToValueMap.get('width'));
        }
        hit(source);
        return newDOMRect;
      };
      var getBoundingClientRectHandler = {
        apply: getBoundingClientRectWrapper,
        get: getter
      };
      window.Element.prototype.getBoundingClientRect = new Proxy(window.Element.prototype.getBoundingClientRect, getBoundingClientRectHandler);
    }
    spoofCSS$1.names = ['spoof-css',
    // aliases are needed for matching the related scriptlet converted into our syntax
    'spoof-css.js', 'ubo-spoof-css.js', 'ubo-spoof-css'];
    spoofCSS$1.injections = [hit];

    /* eslint-disable max-len */
    /**
     * @scriptlet call-nothrow
     *
     * @description
     * Prevents an exception from being thrown and returns undefined when a specific function is called.
     *
     * Related UBO scriptlet:
     * https://github.com/gorhill/uBlock/wiki/Resources-Library#call-nothrowjs-
     *
     * ### Syntax
     *
     * ```text
     * example.org#%#//scriptlet('call-nothrow', functionName)
     * ```
     *
     * - `functionName` — required, the name of the function to trap
     *
     * ### Examples
     *
     * 1. Prevents an exception from being thrown when `Object.defineProperty` is called:
     *
     *     ```adblock
     *     example.org#%#//scriptlet('call-nothrow', 'Object.defineProperty')
     *     ```
     *
     *     For instance, the following call normally throws an error, but the scriptlet catches it and returns undefined:
     *
     *     ```javascript
     *     Object.defineProperty(window, 'foo', { value: true });
     *     Object.defineProperty(window, 'foo', { value: false });
     *     ```
     *
     * 2. Prevents an exception from being thrown when `JSON.parse` is called:
     *
     *     ```adblock
     *     example.org#%#//scriptlet('call-nothrow', 'JSON.parse')
     *     ```
     *
     *     For instance, the following call normally throws an error, but the scriptlet catches it and returns undefined:
     *
     *     ```javascript
     *     JSON.parse('foo');
     *     ```
     *
     * @added v1.10.1.
     */
    /* eslint-enable max-len */
    function callNoThrow$1(source, functionName) {
      if (!functionName) {
        return;
      }
      var _getPropertyInChain = getPropertyInChain(window, functionName),
        base = _getPropertyInChain.base,
        prop = _getPropertyInChain.prop;
      if (!base || !prop || typeof base[prop] !== 'function') {
        var message = "".concat(functionName, " is not a function");
        logMessage(source, message);
        return;
      }
      var objectWrapper = function objectWrapper() {
        var result;
        try {
          result = Reflect.apply(...arguments);
        } catch (e) {
          var _message = "Error calling ".concat(functionName, ": ").concat(e.message);
          logMessage(source, _message);
        }
        hit(source);
        return result;
      };
      var objectHandler = {
        apply: objectWrapper
      };
      base[prop] = new Proxy(base[prop], objectHandler);
    }
    callNoThrow$1.names = ['call-nothrow',
    // aliases are needed for matching the related scriptlet converted into our syntax
    'call-nothrow.js', 'ubo-call-nothrow.js', 'ubo-call-nothrow'];
    callNoThrow$1.injections = [hit, getPropertyInChain, logMessage,
    // following helpers are needed for helpers above
    isEmptyObject];

    /* eslint-disable max-len */
    /**
     * @trustedScriptlet trusted-create-element
     *
     * @description
     * Creates an element with specified attributes and text content, and appends it to the specified parent element.
     *
     * ### Syntax
     *
     * <!-- markdownlint-disable line-length -->
     *
     * ```text
     * example.com#%#//scriptlet('trusted-create-element', parentSelector, tagName[, attributePairs[, textContent[, cleanupDelayMs]]])
     * ```
     *
     * <!-- markdownlint-enable line-length -->
     *
     * - `parentSelector` — required, CSS selector of the parent element to append the created element to.
     * - `tagName` — required, tag name of the created element.
     * - `attributePairs` — optional, space-separated list of attribute name and value pairs separated by `=`.
     *   Value can be omitted. If value is set, it should be wrapped in quotes.
     *   If quotes are needed inside value, they should be escaped with backslash.
     *   Defaults to no attributes.
     * - `textContent` — optional, text content of the created element. Defaults to empty string.
     * - `cleanupDelayMs` — optional, delay in milliseconds before the created element is removed from the DOM.
     *   Defaults to no cleanup.
     *
     * ### Examples
     *
     * 1. Create a div element with a single attribute
     *
     *     ```adblock
     *     example.com#%#//scriptlet('trusted-create-element', 'body', 'div', 'data-cur="1"')
     *     ```
     *
     * 1. Create a div element with text content
     *
     *     ```adblock
     *     example.com#%#//scriptlet('trusted-create-element', 'body', 'div', '', 'Hello world!')
     *     ```
     *
     * 1. Create a button element with multiple attributes, including attribute without value, and text content
     *
     *     <!-- markdownlint-disable line-length -->
     *
     *     ```adblock
     *     example.com#%#//scriptlet('trusted-create-element', 'body', 'button', 'disabled aria-hidden="true" style="width: 0px"', 'Press here')
     *     ```
     *
     *     <!-- markdownlint-enable line-length -->
     *
     * 1. Create a button element with an attribute whose value contains quotes
     *
     *     ```adblock
     *     example.com#%#//scriptlet('trusted-create-element', 'body', 'button', 'data="a\\"quote"')
     *     ```
     *
     * 1. Create a paragraph element with text content and remove it after 5 seconds
     *
     *     ```adblock
     *     example.com#%#//scriptlet('trusted-create-element', '.container > article', 'p', '', 'Hello world!', '5000')
     *     ```
     *
     * @added v1.10.1.
     */
    /* eslint-enable max-len */
    function trustedCreateElement$1(source, parentSelector, tagName) {
      var attributePairs = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : '';
      var textContent = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : '';
      var cleanupDelayMs = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : NaN;
      if (!parentSelector || !tagName) {
        return;
      }

      /**
       * Prevent infinite loops when creating iframes
       * because scriptlet is automatically injected into the newly created iframe.
       */
      var IFRAME_WINDOW_NAME = 'trusted-create-element-window';
      if (window.name === IFRAME_WINDOW_NAME) {
        return;
      }
      var logError = function logError(prefix, error) {
        logMessage(source, "".concat(prefix, " due to ").concat(getErrorMessage(error)));
      };
      var element;
      try {
        element = document.createElement(tagName);
        element.textContent = textContent;
      } catch (e) {
        logError("Cannot create element with tag name '".concat(tagName, "'"), e);
        return;
      }
      var attributes = [];
      try {
        attributes = parseAttributePairs(attributePairs);
      } catch (e) {
        logError("Cannot parse attributePairs param: '".concat(attributePairs, "'"), e);
        return;
      }
      attributes.forEach(function (attr) {
        try {
          element.setAttribute(attr.name, attr.value);
        } catch (e) {
          logError("Cannot set attribute '".concat(attr.name, "' with value '").concat(attr.value, "'"), e);
        }
      });
      var timerId;
      var elementCreated = false;
      var elementRemoved = false;

      /**
       * Finds parent element by `parentElSelector` and appends the `el` element to it.
       *
       * If `removeElDelayMs` is not `NaN`,
       * schedules the `el` element to be removed after `removeElDelayMs` milliseconds.
       *
       * @param parentElSelector CSS selector of the parent element.
       * @param el HTML element to append to the parent element.
       * @param removeElDelayMs Delay in milliseconds after which the `el` element is removed from the DOM.
       *
       * @returns True if the `el` element was successfully appended to the parent element, otherwise false.
       */
      var findParentAndAppendEl = function findParentAndAppendEl(parentElSelector, el, removeElDelayMs) {
        var parentEl;
        try {
          parentEl = document.querySelector(parentElSelector);
        } catch (e) {
          logError("Cannot find parent element by selector '".concat(parentElSelector, "'"), e);
          return false;
        }
        if (!parentEl) {
          logMessage(source, "No parent element found by selector: '".concat(parentElSelector, "'"));
          return false;
        }
        try {
          if (!parentEl.contains(el)) {
            parentEl.append(el);
          }
          if (el instanceof HTMLIFrameElement && el.contentWindow) {
            el.contentWindow.name = IFRAME_WINDOW_NAME;
          }
          elementCreated = true;
          hit(source);
        } catch (e) {
          logError("Cannot append child to parent by selector '".concat(parentElSelector, "'"), e);
          return false;
        }
        if (!nativeIsNaN(removeElDelayMs)) {
          timerId = setTimeout(function () {
            el.remove();
            elementRemoved = true;
            clearTimeout(timerId);
          }, removeElDelayMs);
        }
        return true;
      };
      if (!findParentAndAppendEl(parentSelector, element, cleanupDelayMs)) {
        observeDocumentWithTimeout(function (mutations, observer) {
          if (elementRemoved || elementCreated || findParentAndAppendEl(parentSelector, element, cleanupDelayMs)) {
            observer.disconnect();
          }
        });
      }
    }
    trustedCreateElement$1.names = ['trusted-create-element'
    // trusted scriptlets support no aliases
    ];

    trustedCreateElement$1.injections = [hit, logMessage, observeDocumentWithTimeout, nativeIsNaN, parseAttributePairs, getErrorMessage];

    /**
     * @scriptlet href-sanitizer
     *
     * @description
     * Set the `href` attribute to a value found in text content of the targeted `a` element,
     * or in an attribute of the targeted `a` element,
     * or in a URL parameter of the targeted `a` element's `href` attribute.
     * This scriptlet runs once when the page loads and after that on DOM tree changes.
     *
     * Related UBO scriptlet:
     * https://github.com/uBlockOrigin/uBlock-issues/wiki/Resources-Library#href-sanitizerjs-
     *
     * ### Syntax
     *
     * ```text
     * example.org#%#//scriptlet('href-sanitizer', selector[, attribute])
     * ```
     *
     * - `selector` — required, a CSS selector to match the elements to be sanitized,
     *   which should be anchor elements (`<a>`) with `href` attribute.
     * - `attribute` — optional, default to `text`:
     *     - `text` — use the text content of the matched element,
     *     - `[attribute-name]` copy the value from attribute `attribute-name` on the same element,
     *     - `?parameter` copy the value from URL parameter `parameter` of the same element's `href` attribute.
     *
     * ### Examples
     *
     * 1. Set the `href` attribute to a value found in text content of the targeted `a` element:
     *
     *     ```adblock
     *     example.org#%#//scriptlet('href-sanitizer', 'a[href*="foo.com"]')
     *     ```
     *
     *     ```html
     *     <!-- before -->
     *     <div>
     *         <a href="https://foo.com/bar">https://example.org/test?foo</a>
     *     </div>
     *
     *     <!-- after -->
     *     <div>
     *         <a href="https://example.org/test?foo">https://example.org/test?foo</a>
     *     </div>
     *     ```
     *
     * 2. Set the `href` attribute to a value found in an attribute of the targeted `a` element:
     *
     *     ```adblock
     *     example.org#%#//scriptlet('href-sanitizer', 'a[href*="foo.com"]', '[data-href]')
     *     ```
     *
     *     ```html
     *     <!-- before -->
     *     <div>
     *         <a href="https://foo.com/bar" data-href="https://example.org/test?foo"></a>
     *     </div>
     *
     *     <!-- after -->
     *     <div>
     *         <a href="https://example.org/test?foo" data-href="https://example.org/test?foo"></a>
     *     </div>
     *     ```
     *
     * 3. Set the `href` attribute to a value found in a URL parameter of the targeted `a` element's `href` attribute:
     *
     *     ```adblock
     *     example.org#%#//scriptlet('href-sanitizer', 'a[href*="tracker.com"]', '?redirect')
     *     ```
     *
     *     ```html
     *     <!-- before -->
     *     <div>
     *         <a href="https://tracker.com/foo?redirect=https://example.org/"></a>
     *     </div>
     *
     *     <!-- after -->
     *     <div>
     *         <a href="https://example.org/"></a>
     *     </div>
     *     ```
     *
     * @added v1.10.25.
     */

    function hrefSanitizer$1(source, selector) {
      var attribute = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 'text';
      if (!selector) {
        logMessage(source, 'Selector is required.');
        return;
      }

      // Regular expression to find not valid characters at the beginning and at the end of the string,
      // \x21-\x7e is a range that includes the ASCII characters from ! (hex 21) to ~ (hex 7E).
      // This range covers numbers, English letters, and common symbols.
      // \p{Letter} matches any kind of letter from any language.
      // It's required to fix Twitter case, 'textContent' of the link contains '…' at the end,
      // so it have to be removed, otherwise it will not work properly.
      var regexpNotValidAtStart = /^(?:[\0- \x7F-\xA9\xAB-\xB4\xB6-\xB9\xBB-\xBF\xD7\xF7\u02C2-\u02C5\u02D2-\u02DF\u02E5-\u02EB\u02ED\u02EF-\u036F\u0375\u0378\u0379\u037E\u0380-\u0385\u0387\u038B\u038D\u03A2\u03F6\u0482-\u0489\u0530\u0557\u0558\u055A-\u055F\u0589-\u05CF\u05EB-\u05EE\u05F3-\u061F\u064B-\u066D\u0670\u06D4\u06D6-\u06E4\u06E7-\u06ED\u06F0-\u06F9\u06FD\u06FE\u0700-\u070F\u0711\u0730-\u074C\u07A6-\u07B0\u07B2-\u07C9\u07EB-\u07F3\u07F6-\u07F9\u07FB-\u07FF\u0816-\u0819\u081B-\u0823\u0825-\u0827\u0829-\u083F\u0859-\u085F\u086B-\u086F\u0888\u088F-\u089F\u08CA-\u0903\u093A-\u093C\u093E-\u094F\u0951-\u0957\u0962-\u0970\u0981-\u0984\u098D\u098E\u0991\u0992\u09A9\u09B1\u09B3-\u09B5\u09BA-\u09BC\u09BE-\u09CD\u09CF-\u09DB\u09DE\u09E2-\u09EF\u09F2-\u09FB\u09FD-\u0A04\u0A0B-\u0A0E\u0A11\u0A12\u0A29\u0A31\u0A34\u0A37\u0A3A-\u0A58\u0A5D\u0A5F-\u0A71\u0A75-\u0A84\u0A8E\u0A92\u0AA9\u0AB1\u0AB4\u0ABA-\u0ABC\u0ABE-\u0ACF\u0AD1-\u0ADF\u0AE2-\u0AF8\u0AFA-\u0B04\u0B0D\u0B0E\u0B11\u0B12\u0B29\u0B31\u0B34\u0B3A-\u0B3C\u0B3E-\u0B5B\u0B5E\u0B62-\u0B70\u0B72-\u0B82\u0B84\u0B8B-\u0B8D\u0B91\u0B96-\u0B98\u0B9B\u0B9D\u0BA0-\u0BA2\u0BA5-\u0BA7\u0BAB-\u0BAD\u0BBA-\u0BCF\u0BD1-\u0C04\u0C0D\u0C11\u0C29\u0C3A-\u0C3C\u0C3E-\u0C57\u0C5B\u0C5C\u0C5E\u0C5F\u0C62-\u0C7F\u0C81-\u0C84\u0C8D\u0C91\u0CA9\u0CB4\u0CBA-\u0CBC\u0CBE-\u0CDC\u0CDF\u0CE2-\u0CF0\u0CF3-\u0D03\u0D0D\u0D11\u0D3B\u0D3C\u0D3E-\u0D4D\u0D4F-\u0D53\u0D57-\u0D5E\u0D62-\u0D79\u0D80-\u0D84\u0D97-\u0D99\u0DB2\u0DBC\u0DBE\u0DBF\u0DC7-\u0E00\u0E31\u0E34-\u0E3F\u0E47-\u0E80\u0E83\u0E85\u0E8B\u0EA4\u0EA6\u0EB1\u0EB4-\u0EBC\u0EBE\u0EBF\u0EC5\u0EC7-\u0EDB\u0EE0-\u0EFF\u0F01-\u0F3F\u0F48\u0F6D-\u0F87\u0F8D-\u0FFF\u102B-\u103E\u1040-\u104F\u1056-\u1059\u105E-\u1060\u1062-\u1064\u1067-\u106D\u1071-\u1074\u1082-\u108D\u108F-\u109F\u10C6\u10C8-\u10CC\u10CE\u10CF\u10FB\u1249\u124E\u124F\u1257\u1259\u125E\u125F\u1289\u128E\u128F\u12B1\u12B6\u12B7\u12BF\u12C1\u12C6\u12C7\u12D7\u1311\u1316\u1317\u135B-\u137F\u1390-\u139F\u13F6\u13F7\u13FE-\u1400\u166D\u166E\u1680\u169B-\u169F\u16EB-\u16F0\u16F9-\u16FF\u1712-\u171E\u1732-\u173F\u1752-\u175F\u176D\u1771-\u177F\u17B4-\u17D6\u17D8-\u17DB\u17DD-\u181F\u1879-\u187F\u1885\u1886\u18A9\u18AB-\u18AF\u18F6-\u18FF\u191F-\u194F\u196E\u196F\u1975-\u197F\u19AC-\u19AF\u19CA-\u19FF\u1A17-\u1A1F\u1A55-\u1AA6\u1AA8-\u1B04\u1B34-\u1B44\u1B4D-\u1B82\u1BA1-\u1BAD\u1BB0-\u1BB9\u1BE6-\u1BFF\u1C24-\u1C4C\u1C50-\u1C59\u1C7E\u1C7F\u1C89-\u1C8F\u1CBB\u1CBC\u1CC0-\u1CE8\u1CED\u1CF4\u1CF7-\u1CF9\u1CFB-\u1CFF\u1DC0-\u1DFF\u1F16\u1F17\u1F1E\u1F1F\u1F46\u1F47\u1F4E\u1F4F\u1F58\u1F5A\u1F5C\u1F5E\u1F7E\u1F7F\u1FB5\u1FBD\u1FBF-\u1FC1\u1FC5\u1FCD-\u1FCF\u1FD4\u1FD5\u1FDC-\u1FDF\u1FED-\u1FF1\u1FF5\u1FFD-\u2070\u2072-\u207E\u2080-\u208F\u209D-\u2101\u2103-\u2106\u2108\u2109\u2114\u2116-\u2118\u211E-\u2123\u2125\u2127\u2129\u212E\u213A\u213B\u2140-\u2144\u214A-\u214D\u214F-\u2182\u2185-\u2BFF\u2CE5-\u2CEA\u2CEF-\u2CF1\u2CF4-\u2CFF\u2D26\u2D28-\u2D2C\u2D2E\u2D2F\u2D68-\u2D6E\u2D70-\u2D7F\u2D97-\u2D9F\u2DA7\u2DAF\u2DB7\u2DBF\u2DC7\u2DCF\u2DD7\u2DDF-\u2E2E\u2E30-\u3004\u3007-\u3030\u3036-\u303A\u303D-\u3040\u3097-\u309C\u30A0\u30FB\u3100-\u3104\u3130\u318F-\u319F\u31C0-\u31EF\u3200-\u33FF\u4DC0-\u4DFF\uA48D-\uA4CF\uA4FE\uA4FF\uA60D-\uA60F\uA620-\uA629\uA62C-\uA63F\uA66F-\uA67E\uA69E\uA69F\uA6E6-\uA716\uA720\uA721\uA789\uA78A\uA7CB-\uA7CF\uA7D2\uA7D4\uA7DA-\uA7F1\uA802\uA806\uA80B\uA823-\uA83F\uA874-\uA881\uA8B4-\uA8F1\uA8F8-\uA8FA\uA8FC\uA8FF-\uA909\uA926-\uA92F\uA947-\uA95F\uA97D-\uA983\uA9B3-\uA9CE\uA9D0-\uA9DF\uA9E5\uA9F0-\uA9F9\uA9FF\uAA29-\uAA3F\uAA43\uAA4C-\uAA5F\uAA77-\uAA79\uAA7B-\uAA7D\uAAB0\uAAB2-\uAAB4\uAAB7\uAAB8\uAABE\uAABF\uAAC1\uAAC3-\uAADA\uAADE\uAADF\uAAEB-\uAAF1\uAAF5-\uAB00\uAB07\uAB08\uAB0F\uAB10\uAB17-\uAB1F\uAB27\uAB2F\uAB5B\uAB6A-\uAB6F\uABE3-\uABFF\uD7A4-\uD7AF\uD7C7-\uD7CA\uD7FC-\uD7FF\uE000-\uF8FF\uFA6E\uFA6F\uFADA-\uFAFF\uFB07-\uFB12\uFB18-\uFB1C\uFB1E\uFB29\uFB37\uFB3D\uFB3F\uFB42\uFB45\uFBB2-\uFBD2\uFD3E-\uFD4F\uFD90\uFD91\uFDC8-\uFDEF\uFDFC-\uFE6F\uFE75\uFEFD-\uFF20\uFF3B-\uFF40\uFF5B-\uFF65\uFFBF-\uFFC1\uFFC8\uFFC9\uFFD0\uFFD1\uFFD8\uFFD9\uFFDD-\uFFFF]|\uD800[\uDC0C\uDC27\uDC3B\uDC3E\uDC4E\uDC4F\uDC5E-\uDC7F\uDCFB-\uDE7F\uDE9D-\uDE9F\uDED1-\uDEFF\uDF20-\uDF2C\uDF41\uDF4A-\uDF4F\uDF76-\uDF7F\uDF9E\uDF9F\uDFC4-\uDFC7\uDFD0-\uDFFF]|\uD801[\uDC9E-\uDCAF\uDCD4-\uDCD7\uDCFC-\uDCFF\uDD28-\uDD2F\uDD64-\uDD6F\uDD7B\uDD8B\uDD93\uDD96\uDDA2\uDDB2\uDDBA\uDDBD-\uDDFF\uDF37-\uDF3F\uDF56-\uDF5F\uDF68-\uDF7F\uDF86\uDFB1\uDFBB-\uDFFF]|\uD802[\uDC06\uDC07\uDC09\uDC36\uDC39-\uDC3B\uDC3D\uDC3E\uDC56-\uDC5F\uDC77-\uDC7F\uDC9F-\uDCDF\uDCF3\uDCF6-\uDCFF\uDD16-\uDD1F\uDD3A-\uDD7F\uDDB8-\uDDBD\uDDC0-\uDDFF\uDE01-\uDE0F\uDE14\uDE18\uDE36-\uDE5F\uDE7D-\uDE7F\uDE9D-\uDEBF\uDEC8\uDEE5-\uDEFF\uDF36-\uDF3F\uDF56-\uDF5F\uDF73-\uDF7F\uDF92-\uDFFF]|\uD803[\uDC49-\uDC7F\uDCB3-\uDCBF\uDCF3-\uDCFF\uDD24-\uDE7F\uDEAA-\uDEAF\uDEB2-\uDEFF\uDF1D-\uDF26\uDF28-\uDF2F\uDF46-\uDF6F\uDF82-\uDFAF\uDFC5-\uDFDF\uDFF7-\uDFFF]|\uD804[\uDC00-\uDC02\uDC38-\uDC70\uDC73\uDC74\uDC76-\uDC82\uDCB0-\uDCCF\uDCE9-\uDD02\uDD27-\uDD43\uDD45\uDD46\uDD48-\uDD4F\uDD73-\uDD75\uDD77-\uDD82\uDDB3-\uDDC0\uDDC5-\uDDD9\uDDDB\uDDDD-\uDDFF\uDE12\uDE2C-\uDE3E\uDE41-\uDE7F\uDE87\uDE89\uDE8E\uDE9E\uDEA9-\uDEAF\uDEDF-\uDF04\uDF0D\uDF0E\uDF11\uDF12\uDF29\uDF31\uDF34\uDF3A-\uDF3C\uDF3E-\uDF4F\uDF51-\uDF5C\uDF62-\uDFFF]|\uD805[\uDC35-\uDC46\uDC4B-\uDC5E\uDC62-\uDC7F\uDCB0-\uDCC3\uDCC6\uDCC8-\uDD7F\uDDAF-\uDDD7\uDDDC-\uDDFF\uDE30-\uDE43\uDE45-\uDE7F\uDEAB-\uDEB7\uDEB9-\uDEFF\uDF1B-\uDF3F\uDF47-\uDFFF]|\uD806[\uDC2C-\uDC9F\uDCE0-\uDCFE\uDD07\uDD08\uDD0A\uDD0B\uDD14\uDD17\uDD30-\uDD3E\uDD40\uDD42-\uDD9F\uDDA8\uDDA9\uDDD1-\uDDE0\uDDE2\uDDE4-\uDDFF\uDE01-\uDE0A\uDE33-\uDE39\uDE3B-\uDE4F\uDE51-\uDE5B\uDE8A-\uDE9C\uDE9E-\uDEAF\uDEF9-\uDFFF]|\uD807[\uDC09\uDC2F-\uDC3F\uDC41-\uDC71\uDC90-\uDCFF\uDD07\uDD0A\uDD31-\uDD45\uDD47-\uDD5F\uDD66\uDD69\uDD8A-\uDD97\uDD99-\uDEDF\uDEF3-\uDF01\uDF03\uDF11\uDF34-\uDFAF\uDFB1-\uDFFF]|\uD808[\uDF9A-\uDFFF]|\uD809[\uDC00-\uDC7F\uDD44-\uDFFF]|[\uD80A\uD80E-\uD810\uD812-\uD819\uD824-\uD82A\uD82D\uD82E\uD830-\uD834\uD836\uD83C-\uD83F\uD87B-\uD87D\uD87F\uD889-\uDBFF][\uDC00-\uDFFF]|\uD80B[\uDC00-\uDF8F\uDFF1-\uDFFF]|\uD80D[\uDC30-\uDC40\uDC47-\uDFFF]|\uD811[\uDE47-\uDFFF]|\uD81A[\uDE39-\uDE3F\uDE5F-\uDE6F\uDEBF-\uDECF\uDEEE-\uDEFF\uDF30-\uDF3F\uDF44-\uDF62\uDF78-\uDF7C\uDF90-\uDFFF]|\uD81B[\uDC00-\uDE3F\uDE80-\uDEFF\uDF4B-\uDF4F\uDF51-\uDF92\uDFA0-\uDFDF\uDFE2\uDFE4-\uDFFF]|\uD821[\uDFF8-\uDFFF]|\uD823[\uDCD6-\uDCFF\uDD09-\uDFFF]|\uD82B[\uDC00-\uDFEF\uDFF4\uDFFC\uDFFF]|\uD82C[\uDD23-\uDD31\uDD33-\uDD4F\uDD53\uDD54\uDD56-\uDD63\uDD68-\uDD6F\uDEFC-\uDFFF]|\uD82F[\uDC6B-\uDC6F\uDC7D-\uDC7F\uDC89-\uDC8F\uDC9A-\uDFFF]|\uD835[\uDC55\uDC9D\uDCA0\uDCA1\uDCA3\uDCA4\uDCA7\uDCA8\uDCAD\uDCBA\uDCBC\uDCC4\uDD06\uDD0B\uDD0C\uDD15\uDD1D\uDD3A\uDD3F\uDD45\uDD47-\uDD49\uDD51\uDEA6\uDEA7\uDEC1\uDEDB\uDEFB\uDF15\uDF35\uDF4F\uDF6F\uDF89\uDFA9\uDFC3\uDFCC-\uDFFF]|\uD837[\uDC00-\uDEFF\uDF1F-\uDF24\uDF2B-\uDFFF]|\uD838[\uDC00-\uDC2F\uDC6E-\uDCFF\uDD2D-\uDD36\uDD3E-\uDD4D\uDD4F-\uDE8F\uDEAE-\uDEBF\uDEEC-\uDFFF]|\uD839[\uDC00-\uDCCF\uDCEC-\uDFDF\uDFE7\uDFEC\uDFEF\uDFFF]|\uD83A[\uDCC5-\uDCFF\uDD44-\uDD4A\uDD4C-\uDFFF]|\uD83B[\uDC00-\uDDFF\uDE04\uDE20\uDE23\uDE25\uDE26\uDE28\uDE33\uDE38\uDE3A\uDE3C-\uDE41\uDE43-\uDE46\uDE48\uDE4A\uDE4C\uDE50\uDE53\uDE55\uDE56\uDE58\uDE5A\uDE5C\uDE5E\uDE60\uDE63\uDE65\uDE66\uDE6B\uDE73\uDE78\uDE7D\uDE7F\uDE8A\uDE9C-\uDEA0\uDEA4\uDEAA\uDEBC-\uDFFF]|\uD869[\uDEE0-\uDEFF]|\uD86D[\uDF3A-\uDF3F]|\uD86E[\uDC1E\uDC1F]|\uD873[\uDEA2-\uDEAF]|\uD87A[\uDFE1-\uDFFF]|\uD87E[\uDE1E-\uDFFF]|\uD884[\uDF4B-\uDF4F]|\uD888[\uDFB0-\uDFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF])+/;
      var regexpNotValidAtEnd = /(?:[\0- \x7F-\xA9\xAB-\xB4\xB6-\xB9\xBB-\xBF\xD7\xF7\u02C2-\u02C5\u02D2-\u02DF\u02E5-\u02EB\u02ED\u02EF-\u036F\u0375\u0378\u0379\u037E\u0380-\u0385\u0387\u038B\u038D\u03A2\u03F6\u0482-\u0489\u0530\u0557\u0558\u055A-\u055F\u0589-\u05CF\u05EB-\u05EE\u05F3-\u061F\u064B-\u066D\u0670\u06D4\u06D6-\u06E4\u06E7-\u06ED\u06F0-\u06F9\u06FD\u06FE\u0700-\u070F\u0711\u0730-\u074C\u07A6-\u07B0\u07B2-\u07C9\u07EB-\u07F3\u07F6-\u07F9\u07FB-\u07FF\u0816-\u0819\u081B-\u0823\u0825-\u0827\u0829-\u083F\u0859-\u085F\u086B-\u086F\u0888\u088F-\u089F\u08CA-\u0903\u093A-\u093C\u093E-\u094F\u0951-\u0957\u0962-\u0970\u0981-\u0984\u098D\u098E\u0991\u0992\u09A9\u09B1\u09B3-\u09B5\u09BA-\u09BC\u09BE-\u09CD\u09CF-\u09DB\u09DE\u09E2-\u09EF\u09F2-\u09FB\u09FD-\u0A04\u0A0B-\u0A0E\u0A11\u0A12\u0A29\u0A31\u0A34\u0A37\u0A3A-\u0A58\u0A5D\u0A5F-\u0A71\u0A75-\u0A84\u0A8E\u0A92\u0AA9\u0AB1\u0AB4\u0ABA-\u0ABC\u0ABE-\u0ACF\u0AD1-\u0ADF\u0AE2-\u0AF8\u0AFA-\u0B04\u0B0D\u0B0E\u0B11\u0B12\u0B29\u0B31\u0B34\u0B3A-\u0B3C\u0B3E-\u0B5B\u0B5E\u0B62-\u0B70\u0B72-\u0B82\u0B84\u0B8B-\u0B8D\u0B91\u0B96-\u0B98\u0B9B\u0B9D\u0BA0-\u0BA2\u0BA5-\u0BA7\u0BAB-\u0BAD\u0BBA-\u0BCF\u0BD1-\u0C04\u0C0D\u0C11\u0C29\u0C3A-\u0C3C\u0C3E-\u0C57\u0C5B\u0C5C\u0C5E\u0C5F\u0C62-\u0C7F\u0C81-\u0C84\u0C8D\u0C91\u0CA9\u0CB4\u0CBA-\u0CBC\u0CBE-\u0CDC\u0CDF\u0CE2-\u0CF0\u0CF3-\u0D03\u0D0D\u0D11\u0D3B\u0D3C\u0D3E-\u0D4D\u0D4F-\u0D53\u0D57-\u0D5E\u0D62-\u0D79\u0D80-\u0D84\u0D97-\u0D99\u0DB2\u0DBC\u0DBE\u0DBF\u0DC7-\u0E00\u0E31\u0E34-\u0E3F\u0E47-\u0E80\u0E83\u0E85\u0E8B\u0EA4\u0EA6\u0EB1\u0EB4-\u0EBC\u0EBE\u0EBF\u0EC5\u0EC7-\u0EDB\u0EE0-\u0EFF\u0F01-\u0F3F\u0F48\u0F6D-\u0F87\u0F8D-\u0FFF\u102B-\u103E\u1040-\u104F\u1056-\u1059\u105E-\u1060\u1062-\u1064\u1067-\u106D\u1071-\u1074\u1082-\u108D\u108F-\u109F\u10C6\u10C8-\u10CC\u10CE\u10CF\u10FB\u1249\u124E\u124F\u1257\u1259\u125E\u125F\u1289\u128E\u128F\u12B1\u12B6\u12B7\u12BF\u12C1\u12C6\u12C7\u12D7\u1311\u1316\u1317\u135B-\u137F\u1390-\u139F\u13F6\u13F7\u13FE-\u1400\u166D\u166E\u1680\u169B-\u169F\u16EB-\u16F0\u16F9-\u16FF\u1712-\u171E\u1732-\u173F\u1752-\u175F\u176D\u1771-\u177F\u17B4-\u17D6\u17D8-\u17DB\u17DD-\u181F\u1879-\u187F\u1885\u1886\u18A9\u18AB-\u18AF\u18F6-\u18FF\u191F-\u194F\u196E\u196F\u1975-\u197F\u19AC-\u19AF\u19CA-\u19FF\u1A17-\u1A1F\u1A55-\u1AA6\u1AA8-\u1B04\u1B34-\u1B44\u1B4D-\u1B82\u1BA1-\u1BAD\u1BB0-\u1BB9\u1BE6-\u1BFF\u1C24-\u1C4C\u1C50-\u1C59\u1C7E\u1C7F\u1C89-\u1C8F\u1CBB\u1CBC\u1CC0-\u1CE8\u1CED\u1CF4\u1CF7-\u1CF9\u1CFB-\u1CFF\u1DC0-\u1DFF\u1F16\u1F17\u1F1E\u1F1F\u1F46\u1F47\u1F4E\u1F4F\u1F58\u1F5A\u1F5C\u1F5E\u1F7E\u1F7F\u1FB5\u1FBD\u1FBF-\u1FC1\u1FC5\u1FCD-\u1FCF\u1FD4\u1FD5\u1FDC-\u1FDF\u1FED-\u1FF1\u1FF5\u1FFD-\u2070\u2072-\u207E\u2080-\u208F\u209D-\u2101\u2103-\u2106\u2108\u2109\u2114\u2116-\u2118\u211E-\u2123\u2125\u2127\u2129\u212E\u213A\u213B\u2140-\u2144\u214A-\u214D\u214F-\u2182\u2185-\u2BFF\u2CE5-\u2CEA\u2CEF-\u2CF1\u2CF4-\u2CFF\u2D26\u2D28-\u2D2C\u2D2E\u2D2F\u2D68-\u2D6E\u2D70-\u2D7F\u2D97-\u2D9F\u2DA7\u2DAF\u2DB7\u2DBF\u2DC7\u2DCF\u2DD7\u2DDF-\u2E2E\u2E30-\u3004\u3007-\u3030\u3036-\u303A\u303D-\u3040\u3097-\u309C\u30A0\u30FB\u3100-\u3104\u3130\u318F-\u319F\u31C0-\u31EF\u3200-\u33FF\u4DC0-\u4DFF\uA48D-\uA4CF\uA4FE\uA4FF\uA60D-\uA60F\uA620-\uA629\uA62C-\uA63F\uA66F-\uA67E\uA69E\uA69F\uA6E6-\uA716\uA720\uA721\uA789\uA78A\uA7CB-\uA7CF\uA7D2\uA7D4\uA7DA-\uA7F1\uA802\uA806\uA80B\uA823-\uA83F\uA874-\uA881\uA8B4-\uA8F1\uA8F8-\uA8FA\uA8FC\uA8FF-\uA909\uA926-\uA92F\uA947-\uA95F\uA97D-\uA983\uA9B3-\uA9CE\uA9D0-\uA9DF\uA9E5\uA9F0-\uA9F9\uA9FF\uAA29-\uAA3F\uAA43\uAA4C-\uAA5F\uAA77-\uAA79\uAA7B-\uAA7D\uAAB0\uAAB2-\uAAB4\uAAB7\uAAB8\uAABE\uAABF\uAAC1\uAAC3-\uAADA\uAADE\uAADF\uAAEB-\uAAF1\uAAF5-\uAB00\uAB07\uAB08\uAB0F\uAB10\uAB17-\uAB1F\uAB27\uAB2F\uAB5B\uAB6A-\uAB6F\uABE3-\uABFF\uD7A4-\uD7AF\uD7C7-\uD7CA\uD7FC-\uD7FF\uE000-\uF8FF\uFA6E\uFA6F\uFADA-\uFAFF\uFB07-\uFB12\uFB18-\uFB1C\uFB1E\uFB29\uFB37\uFB3D\uFB3F\uFB42\uFB45\uFBB2-\uFBD2\uFD3E-\uFD4F\uFD90\uFD91\uFDC8-\uFDEF\uFDFC-\uFE6F\uFE75\uFEFD-\uFF20\uFF3B-\uFF40\uFF5B-\uFF65\uFFBF-\uFFC1\uFFC8\uFFC9\uFFD0\uFFD1\uFFD8\uFFD9\uFFDD-\uFFFF]|\uD800[\uDC0C\uDC27\uDC3B\uDC3E\uDC4E\uDC4F\uDC5E-\uDC7F\uDCFB-\uDE7F\uDE9D-\uDE9F\uDED1-\uDEFF\uDF20-\uDF2C\uDF41\uDF4A-\uDF4F\uDF76-\uDF7F\uDF9E\uDF9F\uDFC4-\uDFC7\uDFD0-\uDFFF]|\uD801[\uDC9E-\uDCAF\uDCD4-\uDCD7\uDCFC-\uDCFF\uDD28-\uDD2F\uDD64-\uDD6F\uDD7B\uDD8B\uDD93\uDD96\uDDA2\uDDB2\uDDBA\uDDBD-\uDDFF\uDF37-\uDF3F\uDF56-\uDF5F\uDF68-\uDF7F\uDF86\uDFB1\uDFBB-\uDFFF]|\uD802[\uDC06\uDC07\uDC09\uDC36\uDC39-\uDC3B\uDC3D\uDC3E\uDC56-\uDC5F\uDC77-\uDC7F\uDC9F-\uDCDF\uDCF3\uDCF6-\uDCFF\uDD16-\uDD1F\uDD3A-\uDD7F\uDDB8-\uDDBD\uDDC0-\uDDFF\uDE01-\uDE0F\uDE14\uDE18\uDE36-\uDE5F\uDE7D-\uDE7F\uDE9D-\uDEBF\uDEC8\uDEE5-\uDEFF\uDF36-\uDF3F\uDF56-\uDF5F\uDF73-\uDF7F\uDF92-\uDFFF]|\uD803[\uDC49-\uDC7F\uDCB3-\uDCBF\uDCF3-\uDCFF\uDD24-\uDE7F\uDEAA-\uDEAF\uDEB2-\uDEFF\uDF1D-\uDF26\uDF28-\uDF2F\uDF46-\uDF6F\uDF82-\uDFAF\uDFC5-\uDFDF\uDFF7-\uDFFF]|\uD804[\uDC00-\uDC02\uDC38-\uDC70\uDC73\uDC74\uDC76-\uDC82\uDCB0-\uDCCF\uDCE9-\uDD02\uDD27-\uDD43\uDD45\uDD46\uDD48-\uDD4F\uDD73-\uDD75\uDD77-\uDD82\uDDB3-\uDDC0\uDDC5-\uDDD9\uDDDB\uDDDD-\uDDFF\uDE12\uDE2C-\uDE3E\uDE41-\uDE7F\uDE87\uDE89\uDE8E\uDE9E\uDEA9-\uDEAF\uDEDF-\uDF04\uDF0D\uDF0E\uDF11\uDF12\uDF29\uDF31\uDF34\uDF3A-\uDF3C\uDF3E-\uDF4F\uDF51-\uDF5C\uDF62-\uDFFF]|\uD805[\uDC35-\uDC46\uDC4B-\uDC5E\uDC62-\uDC7F\uDCB0-\uDCC3\uDCC6\uDCC8-\uDD7F\uDDAF-\uDDD7\uDDDC-\uDDFF\uDE30-\uDE43\uDE45-\uDE7F\uDEAB-\uDEB7\uDEB9-\uDEFF\uDF1B-\uDF3F\uDF47-\uDFFF]|\uD806[\uDC2C-\uDC9F\uDCE0-\uDCFE\uDD07\uDD08\uDD0A\uDD0B\uDD14\uDD17\uDD30-\uDD3E\uDD40\uDD42-\uDD9F\uDDA8\uDDA9\uDDD1-\uDDE0\uDDE2\uDDE4-\uDDFF\uDE01-\uDE0A\uDE33-\uDE39\uDE3B-\uDE4F\uDE51-\uDE5B\uDE8A-\uDE9C\uDE9E-\uDEAF\uDEF9-\uDFFF]|\uD807[\uDC09\uDC2F-\uDC3F\uDC41-\uDC71\uDC90-\uDCFF\uDD07\uDD0A\uDD31-\uDD45\uDD47-\uDD5F\uDD66\uDD69\uDD8A-\uDD97\uDD99-\uDEDF\uDEF3-\uDF01\uDF03\uDF11\uDF34-\uDFAF\uDFB1-\uDFFF]|\uD808[\uDF9A-\uDFFF]|\uD809[\uDC00-\uDC7F\uDD44-\uDFFF]|[\uD80A\uD80E-\uD810\uD812-\uD819\uD824-\uD82A\uD82D\uD82E\uD830-\uD834\uD836\uD83C-\uD83F\uD87B-\uD87D\uD87F\uD889-\uDBFF][\uDC00-\uDFFF]|\uD80B[\uDC00-\uDF8F\uDFF1-\uDFFF]|\uD80D[\uDC30-\uDC40\uDC47-\uDFFF]|\uD811[\uDE47-\uDFFF]|\uD81A[\uDE39-\uDE3F\uDE5F-\uDE6F\uDEBF-\uDECF\uDEEE-\uDEFF\uDF30-\uDF3F\uDF44-\uDF62\uDF78-\uDF7C\uDF90-\uDFFF]|\uD81B[\uDC00-\uDE3F\uDE80-\uDEFF\uDF4B-\uDF4F\uDF51-\uDF92\uDFA0-\uDFDF\uDFE2\uDFE4-\uDFFF]|\uD821[\uDFF8-\uDFFF]|\uD823[\uDCD6-\uDCFF\uDD09-\uDFFF]|\uD82B[\uDC00-\uDFEF\uDFF4\uDFFC\uDFFF]|\uD82C[\uDD23-\uDD31\uDD33-\uDD4F\uDD53\uDD54\uDD56-\uDD63\uDD68-\uDD6F\uDEFC-\uDFFF]|\uD82F[\uDC6B-\uDC6F\uDC7D-\uDC7F\uDC89-\uDC8F\uDC9A-\uDFFF]|\uD835[\uDC55\uDC9D\uDCA0\uDCA1\uDCA3\uDCA4\uDCA7\uDCA8\uDCAD\uDCBA\uDCBC\uDCC4\uDD06\uDD0B\uDD0C\uDD15\uDD1D\uDD3A\uDD3F\uDD45\uDD47-\uDD49\uDD51\uDEA6\uDEA7\uDEC1\uDEDB\uDEFB\uDF15\uDF35\uDF4F\uDF6F\uDF89\uDFA9\uDFC3\uDFCC-\uDFFF]|\uD837[\uDC00-\uDEFF\uDF1F-\uDF24\uDF2B-\uDFFF]|\uD838[\uDC00-\uDC2F\uDC6E-\uDCFF\uDD2D-\uDD36\uDD3E-\uDD4D\uDD4F-\uDE8F\uDEAE-\uDEBF\uDEEC-\uDFFF]|\uD839[\uDC00-\uDCCF\uDCEC-\uDFDF\uDFE7\uDFEC\uDFEF\uDFFF]|\uD83A[\uDCC5-\uDCFF\uDD44-\uDD4A\uDD4C-\uDFFF]|\uD83B[\uDC00-\uDDFF\uDE04\uDE20\uDE23\uDE25\uDE26\uDE28\uDE33\uDE38\uDE3A\uDE3C-\uDE41\uDE43-\uDE46\uDE48\uDE4A\uDE4C\uDE50\uDE53\uDE55\uDE56\uDE58\uDE5A\uDE5C\uDE5E\uDE60\uDE63\uDE65\uDE66\uDE6B\uDE73\uDE78\uDE7D\uDE7F\uDE8A\uDE9C-\uDEA0\uDEA4\uDEAA\uDEBC-\uDFFF]|\uD869[\uDEE0-\uDEFF]|\uD86D[\uDF3A-\uDF3F]|\uD86E[\uDC1E\uDC1F]|\uD873[\uDEA2-\uDEAF]|\uD87A[\uDFE1-\uDFFF]|\uD87E[\uDE1E-\uDFFF]|\uD884[\uDF4B-\uDF4F]|\uD888[\uDFB0-\uDFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF])+$/;

      /**
       * Extracts text from an element based on the specified attribute.
       *
       * @param anchor The element from which to extract the text.
       * @param attr The attribute indicating how to extract the text.
       * @returns The extracted text.
       */
      var extractNewHref = function extractNewHref(anchor, attr) {
        if (attr === 'text') {
          if (!anchor.textContent) {
            return '';
          }
          return anchor.textContent.replace(regexpNotValidAtStart, '').replace(regexpNotValidAtEnd, '');
        }
        if (attr.startsWith('?')) {
          try {
            var url = new URL(anchor.href, document.location.href);
            return url.searchParams.get(attr.slice(1)) || '';
          } catch (ex) {
            logMessage(source, "Cannot retrieve the parameter '".concat(attr.slice(1), "' from the URL '").concat(anchor.href));
            return '';
          }
        }
        if (attr.startsWith('[') && attr.endsWith(']')) {
          return anchor.getAttribute(attr.slice(1, -1)) || '';
        }
        return '';
      };

      /**
       * Validates a URL, if valid return URL,
       * otherwise return null.
       *
       * @param text The URL to be validated
       * @returns URL for valid URL, otherwise null.
       */
      var getValidURL = function getValidURL(text) {
        if (!text) {
          return null;
        }
        try {
          var _URL = new URL(text, document.location.href),
            href = _URL.href,
            protocol = _URL.protocol;
          if (protocol !== 'http:' && protocol !== 'https:') {
            logMessage(source, "Protocol not allowed: \"".concat(protocol, "\", from URL: \"").concat(href, "\""));
            return null;
          }
          return href;
        } catch (_unused) {
          return null;
        }
      };

      /**
       * Checks if the given element is a sanitizable anchor element.
       *
       * @param element The element to check.
       * @returns True if the element is a sanitizable anchor element, false otherwise.
       */
      var isSanitizableAnchor = function isSanitizableAnchor(element) {
        return element.nodeName.toLowerCase() === 'a' && element.hasAttribute('href');
      };

      /**
       * Sanitizes the href attribute of elements matching the given selector.
       *
       * @param elementSelector The CSS selector to match the elements.
       */
      var sanitize = function sanitize(elementSelector) {
        var elements;
        try {
          elements = document.querySelectorAll(elementSelector);
        } catch (e) {
          logMessage(source, "Invalid selector \"".concat(elementSelector, "\""));
          return;
        }
        elements.forEach(function (elem) {
          try {
            if (!isSanitizableAnchor(elem)) {
              return;
            }
            var newHref = extractNewHref(elem, attribute);
            var newValidHref = getValidURL(newHref);
            if (!newValidHref) {
              logMessage(source, "Invalid URL: ".concat(newHref));
              return;
            }
            var oldHref = elem.href; // Required to log the original URL.

            elem.setAttribute('href', newValidHref);
            if (newValidHref !== oldHref) {
              logMessage(source, "Sanitized \"".concat(oldHref, "\" to \"").concat(newValidHref, "\"."));
            }
          } catch (ex) {
            logMessage(source, "Failed to sanitize ".concat(elem, "."));
          }
        });
        hit(source);
      };
      var run = function run() {
        sanitize(selector);
        observeDOMChanges(function () {
          return sanitize(selector);
        }, true);
      };
      if (document.readyState === 'loading') {
        window.addEventListener('DOMContentLoaded', run, {
          once: true
        });
      } else {
        run();
      }
    }
    hrefSanitizer$1.names = ['href-sanitizer',
    // aliases are needed for matching the related scriptlet converted into our syntax
    'href-sanitizer.js', 'ubo-href-sanitizer.js', 'ubo-href-sanitizer'];
    hrefSanitizer$1.injections = [observeDOMChanges, hit, logMessage,
    // following helpers should be imported and injected
    // because they are used by helpers above
    throttle];

    /**
     * @scriptlet json-prune-fetch-response
     *
     * @description
     * Removes specified properties from the JSON response of a fetch call.
     *
     * Related UBO scriptlet:
     * https://github.com/gorhill/uBlock/commit/749cec0f095f659d6c0b90eb89b729e9deb07c87
     *
     * ### Syntax
     *
     * ```text
     * example.org#%#//scriptlet('json-prune-fetch-response'[, propsToRemove[, obligatoryProps[, propsToMatch[, stack]]]])
     * ```
     *
     * - `propsToRemove` — optional, string of space-separated properties to remove
     * - `obligatoryProps` — optional, string of space-separated properties
     *   which must be all present for the pruning to occur
     * - `propsToMatch` — optional, string of space-separated properties to match; possible props:
     *     - string or regular expression for matching the URL passed to fetch call;
     *       empty string, wildcard `*` or invalid regular expression will match all fetch calls
     *     - colon-separated pairs `name:value` where
     *         <!-- markdownlint-disable-next-line line-length -->
     *         - `name` is [`init` option name](https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/fetch#parameters)
     *         - `value` is string or regular expression for matching the value of the option passed to fetch call;
     *           invalid regular expression will cause any value matching
     * - `stack` — optional, string or regular expression that must match the current function call stack trace;
     *   if regular expression is invalid it will be skipped
     *
     * > Note please that you can use wildcard `*` for chain property name,
     * > e.g. `ad.*.src` instead of `ad.0.src ad.1.src ad.2.src`.
     *
     * > Usage with with only propsToMatch argument will log fetch calls to browser console.
     * > It may be useful for debugging but it is not allowed for prod versions of filter lists.
     *
     * > Scriptlet does nothing if response body can't be converted to JSON.
     *
     * ### Examples
     *
     * 1. Removes property `example` from the JSON response of any fetch call
     *
     *     ```adblock
     *     example.org#%#//scriptlet('json-prune-fetch-response', 'example')
     *     ```
     *
     *     For instance, if the JSON response of a fetch call is:
     *
     *     ```js
     *     {one: 1, example: true}
     *     ```
     *
     *     then the response will be modified to:
     *
     *     ```js
     *     {one: 1}
     *     ```
     *
     * 2. A property in a list of properties can be a chain of properties
     *
     *     ```adblock
     *     example.org#%#//scriptlet('json-prune-fetch-response', 'a.b', 'ads.url.first')
     *     ```
     *
     * 3. Removes property `content.ad` from the JSON response of a fetch call if URL contains `content.json`
     *
     *     ```adblock
     *     example.org#%#//scriptlet('json-prune-fetch-response', 'content.ad', '', 'content.json')
     *     ```
     *
     * 4. Removes property `content.ad` from the JSON response of a fetch call if its error stack trace contains `test.js`
     *
     *     ```adblock
     *     example.org#%#//scriptlet('json-prune-fetch-response', 'content.ad', '', '', 'test.js')
     *     ```
     *
     * 5. A property in a list of properties can be a chain of properties with wildcard in it
     *
     *     ```adblock
     *     example.org#%#//scriptlet('json-prune-fetch-response', 'content.*.media.src', 'content.*.media.ad')
     *     ```
     *
     * 6. Log all JSON responses of a fetch call
     *
     *     ```adblock
     *     example.org#%#//scriptlet('json-prune-fetch-response')
     *     ```
     *
     * @added v1.10.25.
     */
    function jsonPruneFetchResponse$1(source, propsToRemove, obligatoryProps) {
      var propsToMatch = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : '';
      var stack = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : '';
      // do nothing if browser does not support fetch or Proxy (e.g. Internet Explorer)
      // https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/fetch
      // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy
      if (typeof fetch === 'undefined' || typeof Proxy === 'undefined' || typeof Response === 'undefined') {
        return;
      }
      var prunePaths = getPrunePath(propsToRemove);
      var requiredPaths = getPrunePath(obligatoryProps);
      var nativeStringify = window.JSON.stringify;
      var nativeRequestClone = window.Request.prototype.clone;
      var nativeResponseClone = window.Response.prototype.clone;
      var nativeFetch = window.fetch;
      var fetchHandlerWrapper = async function fetchHandlerWrapper(target, thisArg, args) {
        var fetchData = getFetchData(args, nativeRequestClone);
        if (!matchRequestProps(source, propsToMatch, fetchData)) {
          return Reflect.apply(target, thisArg, args);
        }
        var originalResponse;
        var clonedResponse;
        try {
          // eslint-disable-next-line prefer-spread
          originalResponse = await nativeFetch.apply(null, args);
          clonedResponse = nativeResponseClone.call(originalResponse);
        } catch (_unused) {
          logMessage(source, "Could not make an original fetch request: ".concat(fetchData.url));
          return Reflect.apply(target, thisArg, args);
        }
        var json;
        try {
          json = await originalResponse.json();
        } catch (e) {
          var message = "Response body can't be converted to json: ".concat(objectToString$1(fetchData));
          logMessage(source, message);
          return clonedResponse;
        }
        var modifiedJson = jsonPruner(source, json, prunePaths, requiredPaths, stack, {
          nativeStringify,
          nativeRequestClone,
          nativeResponseClone,
          nativeFetch
        });
        var forgedResponse = forgeResponse(originalResponse, nativeStringify(modifiedJson));
        hit(source);
        return forgedResponse;
      };
      var fetchHandler = {
        apply: fetchHandlerWrapper
      };
      window.fetch = new Proxy(window.fetch, fetchHandler);
    }
    jsonPruneFetchResponse$1.names = ['json-prune-fetch-response',
    // aliases are needed for matching the related scriptlet converted into our syntax
    'json-prune-fetch-response.js', 'ubo-json-prune-fetch-response.js', 'ubo-json-prune-fetch-response'];
    jsonPruneFetchResponse$1.injections = [hit, logMessage, getFetchData, objectToString$1, matchRequestProps, jsonPruner, getPrunePath, forgeResponse, isPruningNeeded, matchStackTrace, toRegExp, isValidStrPattern, escapeRegExp, isEmptyObject, getRequestData, getRequestProps, parseMatchProps, isValidParsedData, getMatchPropsData, getWildcardPropertyInChain, shouldAbortInlineOrInjectedScript, getNativeRegexpTest, backupRegExpValues, restoreRegExpValues];

    /**
     * @scriptlet no-protected-audience
     *
     * @description
     * Prevents using the Protected Audience API.
     * https://wicg.github.io/turtledove/
     *
     * ### Syntax
     *
     * ```adblock
     * example.org#%#//scriptlet('no-protected-audience')
     * ```
     *
     * @added v1.10.25.
     */
    function noProtectedAudience$1(source) {
      // Prevent XMLDocuments from being tampered with generic scriptlet rule
      if (Document instanceof Object === false) {
        return;
      }

      // This is not a complete list of methods, but rather a minimal set to suppress the API
      var protectedAudienceMethods = {
        joinAdInterestGroup: noopResolveVoid,
        runAdAuction: noopResolveNull,
        leaveAdInterestGroup: noopResolveVoid,
        clearOriginJoinedAdInterestGroups: noopResolveVoid,
        createAuctionNonce: noopStr,
        updateAdInterestGroups: noopFunc
      };
      for (var _i = 0, _Object$keys = Object.keys(protectedAudienceMethods); _i < _Object$keys.length; _i++) {
        var key = _Object$keys[_i];
        /**
         * TODO Remove type castings when Protected Audience API types become available on DOM definitions.
         * https://github.com/WICG/turtledove/issues/759
         */
        var methodName = key;
        var prototype = Navigator.prototype;
        if (!Object.prototype.hasOwnProperty.call(prototype, methodName) || prototype[methodName] instanceof Function === false) {
          continue;
        }
        prototype[methodName] = protectedAudienceMethods[methodName];
      }
      hit(source);
    }
    noProtectedAudience$1.names = ['no-protected-audience'];
    noProtectedAudience$1.injections = [hit, noopStr, noopFunc, noopResolveVoid, noopResolveNull];

    /* eslint-disable max-len */
    /**
     * @trustedScriptlet trusted-suppress-native-method
     *
     * @description
     * Prevents a call of a given native method, matching the call by incoming arguments.
     *
     * ### Syntax
     *
     * ```text
     * example.org#%#//scriptlet('trusted-suppress-native-method', methodPath, signatureStr[, how[, stack]])
     * ```
     *
     * <!-- markdownlint-disable line-length -->
     *
     * - `methodPath` – required, string path to a native method (joined with `.` if needed). The property must be attached to `window`.
     * - `signatureStr` –  required, string of `|`-separated argument matchers.
     * Supported value types with corresponding matchers:
     *
     *     - string – exact string, part of the string or regexp pattern. Empty string `""` to match an empty string. Regexp patterns inside object matchers are not supported.
     *     - number, boolean, null, undefined – exact value,
     *
     *     - object – partial of the object with the values as mentioned above, i.e by another object, that includes property names and values to be matched,
     *     - array – partial of the array with the values to be included in the incoming array, without considering the order of values.
     *
     * To ignore specific argument, explicitly use whitespace as a matcher, e.g `' | |{"prop":"val"}'` to skip matching first and second arguments.
     *
     * <!-- markdownlint-enable line-length -->
     *
     * - `how` – optional, string, one of the following:
     *     - `abort` – default, aborts the call by throwing an error,
     *     - `prevent` – replaces the method call with the call of an empty function.
     * - `stack` — optional, string or regular expression that must match the current function call stack trace.
     *
     * ### Examples
     * <!-- markdownlint-disable-next-line line-length -->
     * 1. Prevent `localStorage.setItem('test-key', 'test-value')` call matching first argument by regexp pattern and the second one by substring:
     *
     *     ```adblock
     *     example.org#%#//scriptlet('trusted-suppress-native-method', 'localStorage.setItem', '/key/|"value"', 'prevent')
     *     ```
     *
     * 1. Abort `obj.hasOwnProperty('test')` call matching the first argument:
     *
     *     ```adblock
     *     example.org#%#//scriptlet('trusted-suppress-native-method', 'Object.prototype.hasOwnProperty', '"test"')
     *     ```
     *
     * 1. Prevent `Node.prototype.appendChild` call on element with the id `test-id` by object matcher:
     *
     *     ```adblock
     *     example.org#%#//scriptlet('trusted-suppress-native-method', 'Node.prototype.appendChild', '{"id":"str"}', 'prevent')
     *     ```
     *
     * 1. Abort all `document.querySelectorAll` calls with `div` as the first argument:
     *
     *     ```adblock
     *     example.org#%#//scriptlet('trusted-suppress-native-method', 'Document.prototype.querySelectorAll', '"div"')
     *     ```
     *
     * 1. Abort `Array.prototype.concat([1, 'str', true, null])` calls by matching array argument contents:
     *
     *     ```adblock
     *     example.org#%#//scriptlet('trusted-suppress-native-method', 'Array.prototype.concat', '[1, "str", true]')
     *     ```
     *
     * 1. Use `stack` argument to match by the call, while also matching the second argument:
     *
     *     <!-- markdownlint-disable line-length -->
     *
     *     ```adblock
     *     example.org#%#//scriptlet('trusted-suppress-native-method', 'sessionStorage.setItem', ' |"item-value"', 'abort', 'someFuncName')
     *     ```
     *
     *     <!-- markdownlint-enable line-length -->
     *
     * @added v1.10.25.
     */
    /* eslint-enable max-len */
    function trustedSuppressNativeMethod$1(source, methodPath, signatureStr) {
      var how = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : 'abort';
      var stack = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : '';
      if (!methodPath || !signatureStr) {
        return;
      }
      var IGNORE_ARG_SYMBOL = ' ';
      var suppress = how === 'abort' ? getAbortFunc() : function () {};
      var signatureMatcher;
      try {
        signatureMatcher = signatureStr.split('|').map(function (value) {
          return value === IGNORE_ARG_SYMBOL ? value : inferValue(value);
        });
      } catch (e) {
        logMessage(source, "Could not parse the signature matcher: ".concat(getErrorMessage(e)));
        return;
      }

      /**
       * getPropertyInChain's return type `ChainBase` only makes sense
       * while traversing the chain, but not to outside receivers.
       *
       * This is done as the least invasive way to make the typings work,
       * compared to @ts-ignore or scattered assertions.
       */
      var getPathParts = getPropertyInChain;
      var _getPathParts = getPathParts(window, methodPath),
        base = _getPathParts.base,
        chain = _getPathParts.chain,
        prop = _getPathParts.prop;

      // Undefined `chain` indicates successful reaching the end prop.
      if (typeof chain !== 'undefined') {
        logMessage(source, "Could not reach the end of the prop chain: ".concat(methodPath));
        return;
      }
      var nativeMethod = base[prop];
      if (!nativeMethod || typeof nativeMethod !== 'function') {
        logMessage(source, "Could not retrieve the method: ".concat(methodPath));
        return;
      }

      /**
       * Matches the incoming arguments with the signature matcher.
       *
       * @param nativeArguments original arguments of the native method call
       * @param matchArguments matcher to match against the native argument
       * @returns true, if each of the signature matchers match their corresponding argument.
       */
      function matchMethodCall(nativeArguments, matchArguments) {
        return matchArguments.every(function (matcher, i) {
          if (matcher === IGNORE_ARG_SYMBOL) {
            return true;
          }
          var argument = nativeArguments[i];
          return isValueMatched(argument, matcher);
        });
      }

      // This flag allows to prevent infinite loops when trapping props that are used by scriptlet's own code.
      var isMatchingSuspended = false;
      function apply(target, thisArg, argumentsList) {
        if (isMatchingSuspended) {
          return Reflect.apply(target, thisArg, argumentsList);
        }
        isMatchingSuspended = true;
        if (stack && !matchStackTrace(stack, new Error().stack || '')) {
          return Reflect.apply(target, thisArg, argumentsList);
        }
        var isMatching = matchMethodCall(argumentsList, signatureMatcher);
        isMatchingSuspended = false;
        if (isMatching) {
          hit(source);
          return suppress();
        }
        return Reflect.apply(target, thisArg, argumentsList);
      }
      base[prop] = new Proxy(nativeMethod, {
        apply
      });
    }
    trustedSuppressNativeMethod$1.names = ['trusted-suppress-native-method'];
    trustedSuppressNativeMethod$1.injections = [hit, logMessage, getPropertyInChain, inferValue, isValueMatched, getAbortFunc, matchStackTrace, getErrorMessage,
    // following helpers should be imported and injected
    // because they are used by helpers above
    shouldAbortInlineOrInjectedScript, getNativeRegexpTest, toRegExp, nativeIsNaN, randomId, createOnErrorHandler, isEmptyObject, isArbitraryObject, isStringMatched, isArrayMatched, isObjectMatched, backupRegExpValues, restoreRegExpValues];

    /**
     * @scriptlet json-prune-xhr-response
     *
     * @description
     * Removes specified properties from the JSON response of a `XMLHttpRequest` call.
     *
     * Related UBO scriptlet:
     * https://github.com/gorhill/uBlock/commit/3152896d428c54c76cfd66c3da110bd4d6506cbc
     *
     * ### Syntax
     *
     * ```text
     * example.org#%#//scriptlet('json-prune-xhr-response'[, propsToRemove[, obligatoryProps[, propsToMatch[, stack]]]])
     * ```
     *
     * - `propsToRemove` — optional, string of space-separated properties to remove
     * - `obligatoryProps` — optional, string of space-separated properties
     *   which must be all present for the pruning to occur
     * - `propsToMatch` — optional, string of space-separated properties to match for extra condition; possible props:
     *     - string or regular expression for matching the URL passed to `XMLHttpRequest.open()` call;
     *     - colon-separated pairs `name:value` where
     *         - `name` — string or regular expression for matching XMLHttpRequest property name
     *         - `value` — string or regular expression for matching the value of the option
     *           passed to `XMLHttpRequest.open()` call
     * - `stack` — optional, string or regular expression that must match the current function call stack trace;
     *   if regular expression is invalid it will be skipped
     *
     * > Note please that you can use wildcard `*` for chain property name,
     * > e.g. `ad.*.src` instead of `ad.0.src ad.1.src ad.2.src`.
     *
     * > Usage with with only propsToMatch argument will log XMLHttpRequest calls to browser console.
     * > It may be useful for debugging but it is not allowed for prod versions of filter lists.
     *
     * > Scriptlet does nothing if response body can't be converted to JSON.
     *
     * ### Examples
     *
     * 1. Removes property `example` from the JSON response of any XMLHttpRequest call
     *
     *     ```adblock
     *     example.org#%#//scriptlet('json-prune-xhr-response', 'example')
     *     ```
     *
     *     For instance, if the JSON response of a XMLHttpRequest call is:
     *
     *     ```js
     *     {one: 1, example: true}
     *     ```
     *
     *     then the response will be modified to:
     *
     *     ```js
     *     {one: 1}
     *     ```
     *
     * 2. A property in a list of properties can be a chain of properties
     *
     *     ```adblock
     *     example.org#%#//scriptlet('json-prune-xhr-response', 'a.b', 'ads.url.first')
     *     ```
     *
     * 3. Removes property `content.ad` from the JSON response of a XMLHttpRequest call if URL contains `content.json`
     *
     *     ```adblock
     *     example.org#%#//scriptlet('json-prune-xhr-response', 'content.ad', '', 'content.json')
     *     ```
     *
     * 4. Removes property `content.ad` from the JSON response of a XMLHttpRequest call
     * if its error stack trace contains `test.js`
     *
     *     ```adblock
     *     example.org#%#//scriptlet('json-prune-xhr-response', 'content.ad', '', '', 'test.js')
     *     ```
     *
     * 5. A property in a list of properties can be a chain of properties with wildcard in it
     *
     *     ```adblock
     *     example.org#%#//scriptlet('json-prune-xhr-response', 'content.*.media.src', 'content.*.media.ad')
     *     ```
     *
     * 6. Log all JSON responses of a XMLHttpRequest call
     *
     *     ```adblock
     *     example.org#%#//scriptlet('json-prune-xhr-response')
     *     ```
     *
     * @added v1.10.25.
     */

    function jsonPruneXhrResponse$1(source, propsToRemove, obligatoryProps) {
      var propsToMatch = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : '';
      var stack = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : '';
      // Do nothing if browser does not support Proxy (e.g. Internet Explorer)
      // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy
      if (typeof Proxy === 'undefined') {
        return;
      }
      var shouldLog = !propsToRemove && !obligatoryProps;
      var prunePaths = getPrunePath(propsToRemove);
      var requiredPaths = getPrunePath(obligatoryProps);
      var nativeParse = window.JSON.parse;
      var nativeStringify = window.JSON.stringify;
      var nativeOpen = window.XMLHttpRequest.prototype.open;
      var nativeSend = window.XMLHttpRequest.prototype.send;
      var setRequestHeaderWrapper = function setRequestHeaderWrapper(setRequestHeader, thisArgument, argsList) {
        // Collect headers
        thisArgument.collectedHeaders.push(argsList);
        return Reflect.apply(setRequestHeader, thisArgument, argsList);
      };
      var setRequestHeaderHandler = {
        apply: setRequestHeaderWrapper
      };
      var xhrData;
      var openWrapper = function openWrapper(target, thisArg, args) {
        // eslint-disable-next-line prefer-spread
        xhrData = getXhrData.apply(null, args);
        if (matchRequestProps(source, propsToMatch, xhrData) || shouldLog) {
          thisArg.xhrShouldBePruned = true;
          thisArg.headersReceived = !!thisArg.headersReceived;
        }

        // Trap setRequestHeader of target xhr object to mimic request headers later
        if (thisArg.xhrShouldBePruned && !thisArg.headersReceived) {
          thisArg.headersReceived = true;
          thisArg.collectedHeaders = [];

          // setRequestHeader can only be called on open xhr object,
          // so we can safely proxy it here
          thisArg.setRequestHeader = new Proxy(thisArg.setRequestHeader, setRequestHeaderHandler);
        }
        return Reflect.apply(target, thisArg, args);
      };
      var sendWrapper = function sendWrapper(target, thisArg, args) {
        // Stack trace cannot be checked in jsonPruner helper,
        // because in this case it returns stack trace of our script,
        // so it has to be checked earlier
        var stackTrace = new Error().stack || '';
        if (!thisArg.xhrShouldBePruned || stack && !matchStackTrace(stack, stackTrace)) {
          return Reflect.apply(target, thisArg, args);
        }

        /**
         * Create separate XHR request with original request's input
         * to be able to collect response data without triggering
         * listeners on original XHR object
         */
        var forgedRequest = new XMLHttpRequest();
        forgedRequest.addEventListener('readystatechange', function () {
          if (forgedRequest.readyState !== 4) {
            return;
          }
          var readyState = forgedRequest.readyState,
            response = forgedRequest.response,
            responseText = forgedRequest.responseText,
            responseURL = forgedRequest.responseURL,
            responseXML = forgedRequest.responseXML,
            status = forgedRequest.status,
            statusText = forgedRequest.statusText;

          // Extract content from response
          var content = responseText || response;
          if (typeof content !== 'string' && typeof content !== 'object') {
            return;
          }
          var modifiedContent;
          if (typeof content === 'string') {
            try {
              var jsonContent = nativeParse(content);
              if (shouldLog) {
                // eslint-disable-next-line max-len
                logMessage(source, "".concat(window.location.hostname, "\n").concat(nativeStringify(jsonContent, null, 2), "\nStack trace:\n").concat(stackTrace), true);
                logMessage(source, jsonContent, true, false);
                modifiedContent = content;
              } else {
                modifiedContent = jsonPruner(source, jsonContent, prunePaths, requiredPaths, stack = '', {
                  nativeStringify
                });
                // Convert content to appropriate response type, only if it has been modified
                try {
                  var responseType = thisArg.responseType;
                  switch (responseType) {
                    case '':
                    case 'text':
                      modifiedContent = nativeStringify(modifiedContent);
                      break;
                    case 'arraybuffer':
                      modifiedContent = new TextEncoder().encode(nativeStringify(modifiedContent)).buffer;
                      break;
                    case 'blob':
                      modifiedContent = new Blob([nativeStringify(modifiedContent)]);
                      break;
                    default:
                      break;
                  }
                } catch (error) {
                  var message = "Response body cannot be converted to reponse type: '".concat(content, "'");
                  logMessage(source, message);
                  modifiedContent = content;
                }
              }
            } catch (error) {
              var _message = "Response body cannot be converted to json: '".concat(content, "'");
              logMessage(source, _message);
              modifiedContent = content;
            }
          }

          // Manually put required values into target XHR object
          // as thisArg can't be redefined and XHR objects can't be (re)assigned or copied
          Object.defineProperties(thisArg, {
            // original values
            readyState: {
              value: readyState,
              writable: false
            },
            responseURL: {
              value: responseURL,
              writable: false
            },
            responseXML: {
              value: responseXML,
              writable: false
            },
            status: {
              value: status,
              writable: false
            },
            statusText: {
              value: statusText,
              writable: false
            },
            // modified values
            response: {
              value: modifiedContent,
              writable: false
            },
            responseText: {
              value: modifiedContent,
              writable: false
            }
          });

          // Mock events
          setTimeout(function () {
            var stateEvent = new Event('readystatechange');
            thisArg.dispatchEvent(stateEvent);
            var loadEvent = new Event('load');
            thisArg.dispatchEvent(loadEvent);
            var loadEndEvent = new Event('loadend');
            thisArg.dispatchEvent(loadEndEvent);
          }, 1);
          hit(source);
        });
        nativeOpen.apply(forgedRequest, [xhrData.method, xhrData.url, Boolean(xhrData.async)]);

        // Mimic request headers before sending
        // setRequestHeader can only be called on open request objects
        thisArg.collectedHeaders.forEach(function (header) {
          forgedRequest.setRequestHeader(header[0], header[1]);
        });
        thisArg.collectedHeaders = [];
        try {
          nativeSend.call(forgedRequest, args);
        } catch (_unused) {
          return Reflect.apply(target, thisArg, args);
        }
        return undefined;
      };
      var openHandler = {
        apply: openWrapper
      };
      var sendHandler = {
        apply: sendWrapper
      };
      XMLHttpRequest.prototype.open = new Proxy(XMLHttpRequest.prototype.open, openHandler);
      XMLHttpRequest.prototype.send = new Proxy(XMLHttpRequest.prototype.send, sendHandler);
    }
    jsonPruneXhrResponse$1.names = ['json-prune-xhr-response',
    // aliases are needed for matching the related scriptlet converted into our syntax
    'json-prune-xhr-response.js', 'ubo-json-prune-xhr-response.js', 'ubo-json-prune-xhr-response'];
    jsonPruneXhrResponse$1.injections = [hit, logMessage, toRegExp, jsonPruner, getPrunePath, objectToString$1, matchRequestProps, getXhrData, isPruningNeeded, matchStackTrace, getMatchPropsData, getRequestProps, isValidParsedData, parseMatchProps, isValidStrPattern, escapeRegExp, isEmptyObject, getWildcardPropertyInChain, shouldAbortInlineOrInjectedScript, getNativeRegexpTest, backupRegExpValues, restoreRegExpValues];

    /**
     * @trustedScriptlet trusted-dispatch-event
     *
     * @description
     * Dispatches a custom event on a specified target.
     *
     * ### Syntax
     *
     * ```text
     * example.org#%#//scriptlet('trusted-dispatch-event', event[, target])
     * ```
     *
     * - `event` — required, name of the event to dispatch
     * - `target` — optional, target on which event will be invoked. Possible values:
     *     - CSS selector — dispatch event on the element with the specified selector
     *     - `window` — dispatch event on the window object
     *     - if not set, then "document" is used — it's default value
     *
     * ### Examples
     *
     * 1. Dispatches a custom event "click" on the document.
     *
     *     ```adblock
     *     example.org#%#//scriptlet('trusted-dispatch-event', 'click')
     *     ```
     *
     * 2. Dispatches a custom event "submit" on the element with the class "test".
     *
     *     ```adblock
     *     example.org#%#//scriptlet('trusted-dispatch-event', 'submit', '.test')
     *     ```
     *
     * 3. Dispatches a custom event "load" on the window object.
     *
     *     ```adblock
     *     example.org#%#//scriptlet('trusted-dispatch-event', 'load', 'window')
     *     ```
     *
     * @added v1.11.1.
     */

    function trustedDispatchEvent$1(source, event, target) {
      if (!event) {
        return;
      }
      var hasBeenDispatched = false;
      var eventTarget = document;
      if (target === 'window') {
        eventTarget = window;
      }
      var events = new Set();
      var dispatch = function dispatch() {
        var customEvent = new Event(event);
        if (typeof target === 'string' && target !== 'window') {
          eventTarget = document.querySelector(target);
        }
        var isEventAdded = events.has(event);
        if (!hasBeenDispatched && isEventAdded && eventTarget) {
          hasBeenDispatched = true;
          hit(source);
          eventTarget.dispatchEvent(customEvent);
        }
      };
      var wrapper = function wrapper(eventListener, thisArg, args) {
        var eventName = args[0];
        if (thisArg && eventName) {
          events.add(eventName);
          setTimeout(function () {
            dispatch();
          }, 1);
        }
        return Reflect.apply(eventListener, thisArg, args);
      };
      var handler = {
        apply: wrapper
      };
      EventTarget.prototype.addEventListener = new Proxy(EventTarget.prototype.addEventListener, handler);
    }
    trustedDispatchEvent$1.names = ['trusted-dispatch-event'];
    trustedDispatchEvent$1.injections = [hit];

    /* eslint-disable max-len */
    /**
     * @trustedScriptlet trusted-replace-outbound-text
     *
     * @description
     * Replace the text in the outbound function call.
     *
     * Related UBO scriptlet:
     * https://github.com/gorhill/uBlock/commit/21e1ee30ee36c1b9a7a3c9f43ac97e52d8e79661
     *
     * ### Syntax
     *
     * <!-- markdownlint-disable line-length -->
     * ```text
     * example.org#%#//scriptlet('trusted-replace-outbound-text', methodPath[, textToReplace[, replacement[, decodeMethod[, stack[, logContent]]]]])
     * ```
     * <!-- markdownlint-enable line-length -->
     *
     * - `methodPath` — required, the name of the function to trap, it must have an object as an argument.
     *   Call with only `methodPath` as an argument will log all text content of the specified function to console,
     *   but only if function call returns a string, otherwise it will log information that content is not a string.
     * - `textToReplace` — optional, string or regular expression which should be replaced.
     *   By default it's set to `''`. If it's not set to other value and `logContent` is set, it will log the original content.
     * - `replacement` — optional, string which replace the matched text.
     *   By default it's set to '', so matched content will removed.
     * - `decodeMethod` — optional, string which specifies the method used to decode the content.
     *   For now supported value is 'base64'. By default it's set to `''` and no decoding is performed.
     *   If it's set and `logContent` is also set and `textToReplace` and `replacement` are not set,
     *   then it will log the decoded content.
     * - `stack` — optional, string or regular expression that must match the current function call stack trace.
     *   If regular expression is invalid it will be skipped.
     * - `logContent` — optional, if set to any value, the original and modified content will be logged.
     *   By default it's set to '' and no content will be logged.
     *
     * > Logging content may be useful for debugging but it is not allowed for prod versions of filter lists.
     *
     * ### Examples
     *
     * <!-- markdownlint-disable line-length -->
     *
     * 1. Replace `foo` with 'bar' from the payload of the atob call:
     *
     *     ```adblock
     *     example.org#%#//scriptlet('trusted-replace-outbound-text', 'atob', 'foo', 'bar')
     *     ```
     *
     *     For instance, the following call will return `bar`
     *
     *     ```html
     *     const text = btoa('foo');
     *     atob(text);
     *     ```
     *
     * 1. Replace `disable_ads:false` with 'disable_ads:true' from the payload of the `Array.prototype.join` if content is encoded in base64:
     *
     *     ```adblock
     *     example.org#%#//scriptlet('trusted-replace-outbound-text', 'Array.prototype.join', 'disable_ads:false', 'disable_ads:true', 'base64')
     *     ```
     *
     *     For instance, the following call will return `ZGlzYWJsZV9hZHM6dHJ1ZQ==` which is `'disable_ads:true'` after decoding
     *
     *     ```html
     *     const arrayBase64 = ['ZGlzYWJsZV9h','ZHM6ZmFsc2U=']; // `ZGlzYWJsZV9hZHM6ZmFsc2U=` after decoding is `disable_ads:false`
     *     arrayBase64.join('');
     *     ```
     *
     * 1. Replace `"loadAds":true` with `"loadAds":false` from the payload of the JSON.stringify if the stack trace contains `testStackFunction`:
     *
     *     ```adblock
     *     example.org#%#//scriptlet('trusted-replace-outbound-text', 'JSON.stringify', '"loadAds":true', '"loadAds":false', '', 'testStackFunction')
     *     ```
     *
     *     For instance, the following call will return `'{"loadAds":false,"content":"bar"}'`
     *
     *     ```html
     *     const testStackFunction = () => JSON.stringify({ loadAds: true, content: 'bar' });
     *     testStackFunction();
     *     ```
     *
     * 1. Call with `decodeMethod` and `logContent` arguments will log original and decoded text content of the specified function:
     *
     *     ```adblock
     *     example.org#%#//scriptlet('trusted-replace-outbound-text', 'Array.prototype.join', '', '', 'base64', '', 'true')
     *     ```
     *
     * 1. Call with only first argument will log text content of the specified function:
     *
     *     ```adblock
     *     example.org#%#//scriptlet('trusted-replace-outbound-text', 'atob')
     *     ```
     *
     * 1. Call with `logContent` argument will log original and modified text content of the specified function:
     *
     *     ```adblock
     *     example.org#%#//scriptlet('trusted-replace-outbound-text', 'atob', 'foo', 'bar', '', '', 'true')
     *     ```
     *
     * <!-- markdownlint-enable line-length -->
     *
     * @added v1.11.1.
     */
    /* eslint-enable max-len */
    function trustedReplaceOutboundText$1(source, methodPath) {
      var textToReplace = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : '';
      var replacement = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : '';
      var decodeMethod = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : '';
      var stack = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : '';
      var logContent = arguments.length > 6 && arguments[6] !== undefined ? arguments[6] : '';
      if (!methodPath) {
        return;
      }
      var getPathParts = getPropertyInChain;
      var _getPathParts = getPathParts(window, methodPath),
        base = _getPathParts.base,
        chain = _getPathParts.chain,
        prop = _getPathParts.prop;
      if (typeof chain !== 'undefined') {
        logMessage(source, "Could not reach the end of the prop chain: ".concat(methodPath));
        return;
      }
      var nativeMethod = base[prop];
      if (!nativeMethod || typeof nativeMethod !== 'function') {
        logMessage(source, "Could not retrieve the method: ".concat(methodPath));
        return;
      }

      /**
       * A simple check if a string is a valid base64 encoded string.
       * If after decoding and encoding the string is not the same as the original string,
       * then the string is not a valid base64 encoded string.
       *
       * @param str - The string to be checked.
       * @returns A boolean indicating whether the string is a valid base64 encoded string.
       */
      var isValidBase64 = function isValidBase64(str) {
        try {
          if (str === '') {
            return false;
          }
          var decodedString = atob(str);
          var encodedString = btoa(decodedString);
          // Encoded string may contains padding characters, so it's necessary to remove it before comparison
          var stringWithoutPadding = str.replace(/=+$/, '');
          var encodedStringWithoutPadding = encodedString.replace(/=+$/, '');
          return encodedStringWithoutPadding === stringWithoutPadding;
        } catch (e) {
          return false;
        }
      };

      /**
       * Decodes the content, replaces the matched pattern with the specified text replacement,
       * and returns the modified content.
       * If the decode method is not specified, then content is modified without decoding.
       *
       * @param content - The original content to be decoded and replaced.
       * @param pattern - The regular expression pattern to match.
       * @param textReplacement - The text to replace the matched pattern.
       * @param decode - The method used to decode the content. For now only supported value is 'base64'.
       * @param log - The string, if set, decoded content should be logged.
       * @returns The content after modifying.
       */
      var decodeAndReplaceContent = function decodeAndReplaceContent(content, pattern, textReplacement, decode, log) {
        switch (decode) {
          case 'base64':
            try {
              if (!isValidBase64(content)) {
                logMessage(source, "Text content is not a valid base64 encoded string: ".concat(content));
                return content;
              }
              var decodedContent = atob(content);
              if (log) {
                logMessage(source, "Decoded text content: ".concat(decodedContent));
              }
              var modifiedContent = textToReplace ? decodedContent.replace(pattern, textReplacement) : decodedContent;
              if (log) {
                var message = modifiedContent !== decodedContent ? "Modified decoded text content: ".concat(modifiedContent) : 'Decoded text content was not modified';
                logMessage(source, message);
              }
              var encodedContent = btoa(modifiedContent);
              return encodedContent;
            } catch (e) {
              return content;
            }
          default:
            return content.replace(pattern, textReplacement);
        }
      };
      var logOriginalContent = !textToReplace || !!logContent;
      var logModifiedContent = !!logContent;
      var logDecodedContent = !!decodeMethod && !!logContent;

      // This flag allows to prevent infinite loops when trapping props that are used by scriptlet's own code.
      var isMatchingSuspended = false;
      var objectWrapper = function objectWrapper(target, thisArg, argumentsList) {
        if (isMatchingSuspended) {
          return Reflect.apply(target, thisArg, argumentsList);
        }
        isMatchingSuspended = true;
        hit(source);
        var result = Reflect.apply(target, thisArg, argumentsList);
        if (stack && !matchStackTrace(stack, new Error().stack || '')) {
          return result;
        }
        if (typeof result === 'string') {
          if (logOriginalContent) {
            logMessage(source, "Original text content: ".concat(result));
          }
          var patternRegexp = toRegExp(textToReplace);
          var modifiedContent = textToReplace || logDecodedContent ? decodeAndReplaceContent(result, patternRegexp, replacement, decodeMethod, logContent) : result;
          if (logModifiedContent) {
            var message = modifiedContent !== result ? "Modified text content: ".concat(modifiedContent) : 'Text content was not modified';
            logMessage(source, message);
          }
          isMatchingSuspended = false;
          return modifiedContent;
        }
        isMatchingSuspended = false;
        logMessage(source, 'Content is not a string');
        return result;
      };
      var objectHandler = {
        apply: objectWrapper
      };
      base[prop] = new Proxy(nativeMethod, objectHandler);
    }
    trustedReplaceOutboundText$1.names = ['trusted-replace-outbound-text'
    // trusted scriptlets support no aliases
    ];

    trustedReplaceOutboundText$1.injections = [hit, matchStackTrace, getPropertyInChain, getWildcardPropertyInChain, logMessage,
    // following helpers are needed for helpers above
    shouldAbortInlineOrInjectedScript, getNativeRegexpTest, toRegExp, isEmptyObject, backupRegExpValues, restoreRegExpValues];

    /**
     * @redirect amazon-apstag
     *
     * @description
     * Mocks Amazon's apstag.js
     *
     * Related UBO redirect resource:
     * https://github.com/gorhill/uBlock/blob/master/src/web_accessible_resources/amazon_apstag.js
     *
     * ### Examples
     *
     * ```adblock
     * ||amazon-adsystem.com/aax2/apstag.js$script,redirect=amazon-apstag
     * ```
     *
     * @added v1.2.3.
     */
    function AmazonApstag$1(source) {
      var apstagWrapper = {
        fetchBids(a, b) {
          if (typeof b === 'function') {
            b([]);
          }
        },
        init: noopFunc,
        setDisplayBids: noopFunc,
        targetingKeys: noopFunc
      };
      window.apstag = apstagWrapper;
      hit(source);
    }
    AmazonApstag$1.names = ['amazon-apstag', 'ubo-amazon_apstag.js', 'amazon_apstag.js'];
    AmazonApstag$1.injections = [hit, noopFunc];

    /* eslint-disable func-names, no-underscore-dangle */

    /**
     * @redirect didomi-loader
     *
     * @description
     * Mocks Didomi's CMP loader script.
     * https://developers.didomi.io/
     *
     * ### Examples
     *
     * ```adblock
     * ||sdk.privacy-center.org/fbf86806f86e/loader.js$script,redirect=didomi-loader
     * ```
     *
     * @added v1.6.2.
     */
    function DidomiLoader$1(source) {
      function UserConsentStatusForVendorSubscribe() {}
      UserConsentStatusForVendorSubscribe.prototype.filter = function () {
        return new UserConsentStatusForVendorSubscribe();
      };
      UserConsentStatusForVendorSubscribe.prototype.subscribe = noopFunc;
      function UserConsentStatusForVendor() {}
      UserConsentStatusForVendor.prototype.first = function () {
        return new UserConsentStatusForVendorSubscribe();
      };
      UserConsentStatusForVendor.prototype.filter = function () {
        return new UserConsentStatusForVendorSubscribe();
      };
      UserConsentStatusForVendor.prototype.subscribe = noopFunc;
      var DidomiWrapper = {
        isConsentRequired: falseFunc,
        getUserConsentStatusForPurpose: trueFunc,
        getUserConsentStatus: trueFunc,
        getUserStatus: noopFunc,
        getRequiredPurposes: noopArray,
        getUserConsentStatusForVendor: trueFunc,
        Purposes: {
          Cookies: 'cookies'
        },
        notice: {
          configure: noopFunc,
          hide: noopFunc,
          isVisible: falseFunc,
          show: noopFunc,
          showDataProcessing: trueFunc
        },
        isUserConsentStatusPartial: falseFunc,
        on() {
          return {
            actions: {},
            emitter: {},
            services: {},
            store: {}
          };
        },
        shouldConsentBeCollected: falseFunc,
        getUserConsentStatusForAll: noopFunc,
        getObservableOnUserConsentStatusForVendor() {
          return new UserConsentStatusForVendor();
        }
      };
      window.Didomi = DidomiWrapper;
      var didomiStateWrapper = {
        didomiExperimentId: '',
        didomiExperimentUserGroup: '',
        didomiGDPRApplies: 1,
        didomiIABConsent: '',
        didomiPurposesConsent: '',
        didomiPurposesConsentDenied: '',
        didomiPurposesConsentUnknown: '',
        didomiVendorsConsent: '',
        didomiVendorsConsentDenied: '',
        didomiVendorsConsentUnknown: '',
        didomiVendorsRawConsent: '',
        didomiVendorsRawConsentDenied: '',
        didomiVendorsRawConsentUnknown: ''
      };
      window.didomiState = didomiStateWrapper;
      var tcData = {
        eventStatus: 'tcloaded',
        gdprApplies: false,
        listenerId: noopFunc,
        vendor: {
          consents: []
        },
        purpose: {
          consents: []
        }
      };

      // https://github.com/InteractiveAdvertisingBureau/GDPR-Transparency-and-Consent-Framework/blob/master/TCFv2/IAB%20Tech%20Lab%20-%20CMP%20API%20v2.md#how-does-the-cmp-provide-the-api
      var __tcfapiWrapper = function __tcfapiWrapper(command, version, callback) {
        if (typeof callback !== 'function' || command === 'removeEventListener') {
          return;
        }
        callback(tcData, true);
      };
      window.__tcfapi = __tcfapiWrapper;
      var didomiEventListenersWrapper = {
        stub: true,
        push: noopFunc
      };
      window.didomiEventListeners = didomiEventListenersWrapper;
      var didomiOnReadyWrapper = {
        stub: true,
        push(arg) {
          if (typeof arg !== 'function') {
            return;
          }
          if (document.readyState !== 'complete') {
            window.addEventListener('load', function () {
              setTimeout(arg(window.Didomi));
            });
          } else {
            setTimeout(arg(window.Didomi));
          }
        }
      };
      window.didomiOnReady = window.didomiOnReady || didomiOnReadyWrapper;
      if (Array.isArray(window.didomiOnReady)) {
        window.didomiOnReady.forEach(function (arg) {
          if (typeof arg === 'function') {
            try {
              setTimeout(arg(window.Didomi));
            } catch (e) {
              /* empty */
            }
          }
        });
      }
      hit(source);
    }
    DidomiLoader$1.names = ['didomi-loader'];
    DidomiLoader$1.injections = [hit, noopFunc, noopArray, trueFunc, falseFunc];

    /* eslint-disable func-names */

    /**
     * @redirect fingerprintjs2
     *
     * @description
     * Mocks FingerprintJS v2
     * https://github.com/fingerprintjs
     *
     * Related UBO redirect resource:
     * https://github.com/gorhill/uBlock/blob/master/src/web_accessible_resources/fingerprint2.js
     *
     * ### Examples
     *
     * ```adblock
     * ||example.com/modules/js/lib/fgp/fingerprint2.js$script,redirect=fingerprintjs2
     * ```
     *
     * @added v1.5.0.
     */
    function Fingerprintjs2$1(source) {
      var browserId = '';
      for (var i = 0; i < 8; i += 1) {
        browserId += (Math.random() * 0x10000 + 0x1000).toString(16).slice(-4);
      }
      var Fingerprint2 = function Fingerprint2() {};
      Fingerprint2.get = function (options, callback) {
        if (!callback) {
          callback = options;
        }
        setTimeout(function () {
          if (callback) {
            callback(browserId, []);
          }
        }, 1);
      };
      Fingerprint2.prototype = {
        get: Fingerprint2.get
      };
      window.Fingerprint2 = Fingerprint2;
      hit(source);
    }
    Fingerprintjs2$1.names = ['fingerprintjs2',
    // redirect aliases are needed for conversion:
    // prefixed for us
    'ubo-fingerprint2.js',
    // original ubo name
    'fingerprint2.js'];
    Fingerprintjs2$1.injections = [hit];

    /* eslint-disable func-names */

    /**
     * @redirect fingerprintjs3
     *
     * @description
     * Mocks FingerprintJS v3
     * https://github.com/fingerprintjs
     *
     * Related UBO redirect resource:
     * https://github.com/gorhill/uBlock/blob/master/src/web_accessible_resources/fingerprint3.js
     *
     * ### Examples
     *
     * ```adblock
     * ||example.com/js/ufe/isomorphic/thirdparty/fp.min.js$script,redirect=fingerprintjs3
     * ```
     *
     * @added v1.6.2.
     */
    function Fingerprintjs3$1(source) {
      var visitorId = function () {
        var id = '';
        for (var i = 0; i < 8; i += 1) {
          id += (Math.random() * 0x10000 + 0x1000).toString(16).slice(-4);
        }
        return id;
      }();
      var FingerprintJS = function FingerprintJS() {};
      FingerprintJS.prototype = {
        load() {
          return Promise.resolve(new FingerprintJS());
        },
        get() {
          return Promise.resolve({
            visitorId
          });
        },
        hashComponents: noopStr
      };
      window.FingerprintJS = new FingerprintJS();
      hit(source);
    }
    Fingerprintjs3$1.names = ['fingerprintjs3',
    // redirect aliases are needed for conversion:
    // prefixed for us
    'ubo-fingerprint3.js',
    // original ubo name
    'fingerprint3.js'];
    Fingerprintjs3$1.injections = [hit, noopStr];

    /* eslint-disable func-names */

    /**
     * @redirect gemius
     *
     * @description
     * Mocks Gemius Analytics.
     * https://flowplayer.com/developers/plugins/gemius
     *
     * ### Examples
     *
     * ```adblock
     * ||example.org/gplayer.js$script,redirect=gemius
     * ```
     *
     * @added v1.5.0.
     */
    function Gemius$1(source) {
      var GemiusPlayer = function GemiusPlayer() {};
      GemiusPlayer.prototype = {
        setVideoObject: noopFunc,
        newProgram: noopFunc,
        programEvent: noopFunc,
        newAd: noopFunc,
        adEvent: noopFunc
      };
      window.GemiusPlayer = GemiusPlayer;
      hit(source);
    }
    Gemius$1.names = ['gemius'];
    Gemius$1.injections = [hit, noopFunc];

    /**
     * @redirect google-analytics
     *
     * @description
     * Mocks Google's Analytics and Tag Manager APIs.
     * Covers functionality of
     * the [obsolete googletagmanager-gtm redirect](https://github.com/AdguardTeam/Scriptlets/issues/127).
     *
     * Related UBO redirect resource:
     * https://github.com/gorhill/uBlock/blob/master/src/web_accessible_resources/google-analytics_analytics.js
     *
     * ### Examples
     *
     * ```adblock
     * ||google-analytics.com/analytics.js$script,redirect=google-analytics
     * ||googletagmanager.com/gtm.js$script,redirect=google-analytics
     * ```
     *
     * @added v1.0.10.
     */
    function GoogleAnalytics$1(source) {
      var _window$googleAnalyti;
      // eslint-disable-next-line func-names
      var Tracker = function Tracker() {}; // constructor
      var proto = Tracker.prototype;
      proto.get = noopFunc;
      proto.set = noopFunc;
      proto.send = noopFunc;
      var googleAnalyticsName = window.GoogleAnalyticsObject || 'ga';
      var queue = (_window$googleAnalyti = window[googleAnalyticsName]) === null || _window$googleAnalyti === void 0 ? void 0 : _window$googleAnalyti.q;

      // a -- fake arg for 'ga.length < 1' antiadblock checking
      // eslint-disable-next-line no-unused-vars
      function ga(a) {
        var len = arguments.length;
        if (len === 0) {
          return;
        }
        // eslint-disable-next-line prefer-rest-params
        var lastArg = arguments[len - 1];
        var replacer;
        if (lastArg instanceof Object && lastArg !== null && typeof lastArg.hitCallback === 'function') {
          replacer = lastArg.hitCallback;
        } else if (typeof lastArg === 'function') {
          // https://github.com/AdguardTeam/Scriptlets/issues/98
          replacer = function replacer() {
            lastArg(ga.create());
          };
        }
        try {
          setTimeout(replacer, 1);
          // eslint-disable-next-line no-empty
        } catch (ex) {}
      }
      ga.create = function () {
        return new Tracker();
      };
      // https://github.com/AdguardTeam/Scriptlets/issues/134
      ga.getByName = function () {
        return new Tracker();
      };
      ga.getAll = function () {
        return [new Tracker()];
      };
      ga.remove = noopFunc;
      ga.loaded = true;
      window[googleAnalyticsName] = ga;
      if (Array.isArray(queue)) {
        var push = function push(arg) {
          ga(...arg);
        };
        queue.push = push;
        queue.forEach(push);
      }
      var _window = window,
        dataLayer = _window.dataLayer,
        google_optimize = _window.google_optimize; // eslint-disable-line camelcase
      if (dataLayer instanceof Object === false) {
        return;
      }
      if (dataLayer.hide instanceof Object && typeof dataLayer.hide.end === 'function') {
        dataLayer.hide.end();
      }

      /**
       * checks data object and delays callback
       *
       * @param {object|Array} dataObj gtag payload
       * @param {string} funcName callback prop name
       */
      var handleCallback = function handleCallback(dataObj, funcName) {
        if (dataObj && typeof dataObj[funcName] === 'function') {
          setTimeout(dataObj[funcName]);
        }
      };
      if (typeof dataLayer.push === 'function') {
        dataLayer.push = function (data) {
          if (data instanceof Object) {
            handleCallback(data, 'eventCallback');
            // eslint-disable-next-line no-restricted-syntax, guard-for-in
            for (var key in data) {
              handleCallback(data[key], 'event_callback');
            }
            // eslint-disable-next-line no-prototype-builtins
            if (!data.hasOwnProperty('eventCallback') && !data.hasOwnProperty('eventCallback')) {
              [].push.call(window.dataLayer, data);
            }
          }
          if (Array.isArray(data)) {
            data.forEach(function (arg) {
              handleCallback(arg, 'callback');
            });
          }
          return noopFunc;
        };
      }

      // https://github.com/AdguardTeam/Scriptlets/issues/81
      // eslint-disable-next-line camelcase
      if (google_optimize instanceof Object && typeof google_optimize.get === 'function') {
        var googleOptimizeWrapper = {
          get: noopFunc
        };
        window.google_optimize = googleOptimizeWrapper;
      }
      hit(source);
    }
    GoogleAnalytics$1.names = ['google-analytics', 'ubo-google-analytics_analytics.js', 'google-analytics_analytics.js',
    // https://github.com/AdguardTeam/Scriptlets/issues/127
    'googletagmanager-gtm', 'ubo-googletagmanager_gtm.js', 'googletagmanager_gtm.js'];
    GoogleAnalytics$1.injections = [hit, noopFunc, noopNull, noopArray];

    /* eslint-disable no-underscore-dangle */

    /**
     * @redirect google-analytics-ga
     *
     * @description
     * Mocks old Google Analytics API.
     *
     * Related UBO redirect resource:
     * https://github.com/gorhill/uBlock/blob/master/src/web_accessible_resources/google-analytics_ga.js
     *
     * ### Examples
     *
     * ```adblock
     * ||google-analytics.com/ga.js$script,redirect=google-analytics-ga
     * ```
     *
     * @added v1.0.10.
     */
    function GoogleAnalyticsGa$1(source) {
      // Gaq constructor
      function Gaq() {}
      Gaq.prototype.Na = noopFunc;
      Gaq.prototype.O = noopFunc;
      Gaq.prototype.Sa = noopFunc;
      Gaq.prototype.Ta = noopFunc;
      Gaq.prototype.Va = noopFunc;
      Gaq.prototype._createAsyncTracker = noopFunc;
      Gaq.prototype._getAsyncTracker = noopFunc;
      Gaq.prototype._getPlugin = noopFunc;
      Gaq.prototype.push = function (data) {
        if (typeof data === 'function') {
          data();
          return;
        }
        if (Array.isArray(data) === false) {
          return;
        }
        // https://developers.google.com/analytics/devguides/collection/gajs/methods/gaJSApiDomainDirectory#_gat.GA_Tracker_._link
        // https://github.com/uBlockOrigin/uBlock-issues/issues/1807
        if (typeof data[0] === 'string' && /(^|\.)_link$/.test(data[0]) && typeof data[1] === 'string') {
          window.location.assign(data[1]);
        }
        // https://github.com/gorhill/uBlock/issues/2162
        if (data[0] === '_set' && data[1] === 'hitCallback' && typeof data[2] === 'function') {
          data[2]();
        }
      };
      var gaq = new Gaq();
      var asyncTrackers = window._gaq || [];
      if (Array.isArray(asyncTrackers)) {
        while (asyncTrackers[0]) {
          gaq.push(asyncTrackers.shift());
        }
      }
      // eslint-disable-next-line no-multi-assign
      window._gaq = gaq.qf = gaq;

      // Gat constructor
      function Gat() {}

      // Mock tracker api
      var api = ['_addIgnoredOrganic', '_addIgnoredRef', '_addItem', '_addOrganic', '_addTrans', '_clearIgnoredOrganic', '_clearIgnoredRef', '_clearOrganic', '_cookiePathCopy', '_deleteCustomVar', '_getName', '_setAccount', '_getAccount', '_getClientInfo', '_getDetectFlash', '_getDetectTitle', '_getLinkerUrl', '_getLocalGifPath', '_getServiceMode', '_getVersion', '_getVisitorCustomVar', '_initData', '_link', '_linkByPost', '_setAllowAnchor', '_setAllowHash', '_setAllowLinker', '_setCampContentKey', '_setCampMediumKey', '_setCampNameKey', '_setCampNOKey', '_setCampSourceKey', '_setCampTermKey', '_setCampaignCookieTimeout', '_setCampaignTrack', '_setClientInfo', '_setCookiePath', '_setCookiePersistence', '_setCookieTimeout', '_setCustomVar', '_setDetectFlash', '_setDetectTitle', '_setDomainName', '_setLocalGifPath', '_setLocalRemoteServerMode', '_setLocalServerMode', '_setReferrerOverride', '_setRemoteServerMode', '_setSampleRate', '_setSessionTimeout', '_setSiteSpeedSampleRate', '_setSessionCookieTimeout', '_setVar', '_setVisitorCookieTimeout', '_trackEvent', '_trackPageLoadTime', '_trackPageview', '_trackSocial', '_trackTiming', '_trackTrans', '_visitCode'];
      var tracker = api.reduce(function (res, funcName) {
        res[funcName] = noopFunc;
        return res;
      }, {});
      tracker._getLinkerUrl = function (a) {
        return a;
      };
      // https://github.com/AdguardTeam/Scriptlets/issues/154
      tracker._link = function (url) {
        if (typeof url !== 'string') {
          return;
        }
        try {
          window.location.assign(url);
        } catch (e) {
          logMessage(source, e);
        }
      };
      Gat.prototype._anonymizeIP = noopFunc;
      Gat.prototype._createTracker = noopFunc;
      Gat.prototype._forceSSL = noopFunc;
      Gat.prototype._getPlugin = noopFunc;
      Gat.prototype._getTracker = function () {
        return tracker;
      };
      Gat.prototype._getTrackerByName = function () {
        return tracker;
      };
      Gat.prototype._getTrackers = noopFunc;
      Gat.prototype.aa = noopFunc;
      Gat.prototype.ab = noopFunc;
      Gat.prototype.hb = noopFunc;
      Gat.prototype.la = noopFunc;
      Gat.prototype.oa = noopFunc;
      Gat.prototype.pa = noopFunc;
      Gat.prototype.u = noopFunc;
      var gat = new Gat();
      window._gat = gat;
      hit(source);
    }
    GoogleAnalyticsGa$1.names = ['google-analytics-ga', 'ubo-google-analytics_ga.js', 'google-analytics_ga.js'];
    GoogleAnalyticsGa$1.injections = [hit, noopFunc, logMessage];

    /* eslint-disable func-names, no-underscore-dangle */

    /**
     * @redirect google-ima3
     *
     * @description
     * Mocks the IMA SDK of Google.
     *
     * Related Mozilla shim:
     * https://searchfox.org/mozilla-central/source/browser/extensions/webcompat/shims/google-ima.js
     *
     * ### Examples
     *
     * ```adblock
     * ||imasdk.googleapis.com/js/sdkloader/ima3.js$script,redirect=google-ima3
     * ```
     *
     * @added v1.6.2.
     */

    function GoogleIma3$1(source) {
      var _window$google$ima;
      var VERSION = '3.453.0';
      var ima = {};
      var AdDisplayContainer = function AdDisplayContainer(containerElement) {
        var divElement = document.createElement('div');
        divElement.style.setProperty('display', 'none', 'important');
        divElement.style.setProperty('visibility', 'collapse', 'important');
        if (containerElement) {
          containerElement.appendChild(divElement);
        }
      };
      AdDisplayContainer.prototype.destroy = noopFunc;
      AdDisplayContainer.prototype.initialize = noopFunc;
      var ImaSdkSettings = function ImaSdkSettings() {};
      ImaSdkSettings.CompanionBackfillMode = {
        ALWAYS: 'always',
        ON_MASTER_AD: 'on_master_ad'
      };
      ImaSdkSettings.VpaidMode = {
        DISABLED: 0,
        ENABLED: 1,
        INSECURE: 2
      };
      ImaSdkSettings.prototype = {
        c: true,
        f: {},
        i: false,
        l: '',
        p: '',
        r: 0,
        t: '',
        v: '',
        getCompanionBackfill: noopFunc,
        getDisableCustomPlaybackForIOS10Plus() {
          return this.i;
        },
        getDisabledFlashAds: function getDisabledFlashAds() {
          return true;
        },
        getFeatureFlags() {
          return this.f;
        },
        getLocale() {
          return this.l;
        },
        getNumRedirects() {
          return this.r;
        },
        getPlayerType() {
          return this.t;
        },
        getPlayerVersion() {
          return this.v;
        },
        getPpid() {
          return this.p;
        },
        getVpaidMode() {
          return this.C;
        },
        isCookiesEnabled() {
          return this.c;
        },
        isVpaidAdapter() {
          return this.M;
        },
        setCompanionBackfill: noopFunc,
        setAutoPlayAdBreaks(a) {
          this.K = a;
        },
        setCookiesEnabled(c) {
          this.c = !!c;
        },
        setDisableCustomPlaybackForIOS10Plus(i) {
          this.i = !!i;
        },
        setDisableFlashAds: noopFunc,
        setFeatureFlags(f) {
          this.f = !!f;
        },
        setIsVpaidAdapter(a) {
          this.M = a;
        },
        setLocale(l) {
          this.l = !!l;
        },
        setNumRedirects(r) {
          this.r = !!r;
        },
        setPageCorrelator(a) {
          this.R = a;
        },
        setPlayerType(t) {
          this.t = !!t;
        },
        setPlayerVersion(v) {
          this.v = !!v;
        },
        setPpid(p) {
          this.p = !!p;
        },
        setVpaidMode(a) {
          this.C = a;
        },
        setSessionId: noopFunc,
        setStreamCorrelator: noopFunc,
        setVpaidAllowed: noopFunc,
        CompanionBackfillMode: {
          ALWAYS: 'always',
          ON_MASTER_AD: 'on_master_ad'
        },
        VpaidMode: {
          DISABLED: 0,
          ENABLED: 1,
          INSECURE: 2
        }
      };
      var EventHandler = function EventHandler() {
        this.listeners = new Map();
        this._dispatch = function (e) {
          var listeners = this.listeners.get(e.type);
          listeners = listeners ? listeners.values() : [];
          for (var _i = 0, _Array$from = Array.from(listeners); _i < _Array$from.length; _i++) {
            var listener = _Array$from[_i];
            try {
              listener(e);
            } catch (r) {
              logMessage(source, r);
            }
          }
        };
        this.addEventListener = function (types, callback, options, context) {
          if (!Array.isArray(types)) {
            types = [types];
          }
          for (var i = 0; i < types.length; i += 1) {
            var type = types[i];
            if (!this.listeners.has(type)) {
              this.listeners.set(type, new Map());
            }
            this.listeners.get(type).set(callback, callback.bind(context || this));
          }
        };
        this.removeEventListener = function (types, callback) {
          if (!Array.isArray(types)) {
            types = [types];
          }
          for (var i = 0; i < types.length; i += 1) {
            var _this$listeners$get;
            var type = types[i];
            (_this$listeners$get = this.listeners.get(type)) === null || _this$listeners$get === void 0 ? void 0 : _this$listeners$get.delete(callback);
          }
        };
      };
      var AdsManager = new EventHandler();
      /* eslint-disable no-use-before-define */
      AdsManager.volume = 1;
      AdsManager.collapse = noopFunc;
      AdsManager.configureAdsManager = noopFunc;
      AdsManager.destroy = noopFunc;
      AdsManager.discardAdBreak = noopFunc;
      AdsManager.expand = noopFunc;
      AdsManager.focus = noopFunc;
      AdsManager.getAdSkippableState = function () {
        return false;
      };
      AdsManager.getCuePoints = function () {
        return [0];
      };
      AdsManager.getCurrentAd = function () {
        return currentAd;
      };
      AdsManager.getCurrentAdCuePoints = function () {
        return [];
      };
      AdsManager.getRemainingTime = function () {
        return 0;
      };
      AdsManager.getVolume = function () {
        return this.volume;
      };
      AdsManager.init = noopFunc;
      AdsManager.isCustomClickTrackingUsed = function () {
        return false;
      };
      AdsManager.isCustomPlaybackUsed = function () {
        return false;
      };
      AdsManager.pause = noopFunc;
      AdsManager.requestNextAdBreak = noopFunc;
      AdsManager.resize = noopFunc;
      AdsManager.resume = noopFunc;
      AdsManager.setVolume = function (v) {
        this.volume = v;
      };
      AdsManager.skip = noopFunc;
      AdsManager.start = function () {
        // eslint-disable-next-line no-restricted-syntax
        for (var _i2 = 0, _arr = [AdEvent.Type.ALL_ADS_COMPLETED, AdEvent.Type.CONTENT_RESUME_REQUESTED]; _i2 < _arr.length; _i2++) {
          var type = _arr[_i2];
          try {
            this._dispatch(new ima.AdEvent(type));
          } catch (e) {
            logMessage(source, e);
          }
        }
      };
      AdsManager.stop = noopFunc;
      AdsManager.updateAdsRenderingSettings = noopFunc;
      /* eslint-enable no-use-before-define */

      var manager = Object.create(AdsManager);
      var AdsManagerLoadedEvent = function AdsManagerLoadedEvent(type, adsRequest, userRequestContext) {
        this.type = type;
        this.adsRequest = adsRequest;
        this.userRequestContext = userRequestContext;
      };
      AdsManagerLoadedEvent.prototype = {
        getAdsManager: function getAdsManager() {
          return manager;
        },
        getUserRequestContext() {
          if (this.userRequestContext) {
            return this.userRequestContext;
          }
          return {};
        }
      };
      AdsManagerLoadedEvent.Type = {
        ADS_MANAGER_LOADED: 'adsManagerLoaded'
      };
      var AdsLoader = EventHandler;
      AdsLoader.prototype.settings = new ImaSdkSettings();
      AdsLoader.prototype.contentComplete = noopFunc;
      AdsLoader.prototype.destroy = noopFunc;
      AdsLoader.prototype.getSettings = function () {
        return this.settings;
      };
      AdsLoader.prototype.getVersion = function () {
        return VERSION;
      };
      AdsLoader.prototype.requestAds = function (adsRequest, userRequestContext) {
        var _this = this;
        requestAnimationFrame(function () {
          var ADS_MANAGER_LOADED = AdsManagerLoadedEvent.Type.ADS_MANAGER_LOADED;
          var event = new ima.AdsManagerLoadedEvent(ADS_MANAGER_LOADED, adsRequest, userRequestContext);
          _this._dispatch(event);
        });
        var e = new ima.AdError('adPlayError', 1205, 1205, 'The browser prevented playback initiated without user interaction.', adsRequest, userRequestContext);
        requestAnimationFrame(function () {
          _this._dispatch(new ima.AdErrorEvent(e));
        });
      };
      var AdsRenderingSettings = noopFunc;
      var AdsRequest = function AdsRequest() {};
      AdsRequest.prototype = {
        setAdWillAutoPlay: noopFunc,
        setAdWillPlayMuted: noopFunc,
        setContinuousPlayback: noopFunc
      };
      var AdPodInfo = function AdPodInfo() {};
      AdPodInfo.prototype = {
        getAdPosition: function getAdPosition() {
          return 1;
        },
        getIsBumper: function getIsBumper() {
          return false;
        },
        getMaxDuration: function getMaxDuration() {
          return -1;
        },
        getPodIndex: function getPodIndex() {
          return 1;
        },
        getTimeOffset: function getTimeOffset() {
          return 0;
        },
        getTotalAds: function getTotalAds() {
          return 1;
        }
      };
      var UniversalAdIdInfo = function UniversalAdIdInfo() {};
      UniversalAdIdInfo.prototype.getAdIdRegistry = function () {
        return '';
      };
      UniversalAdIdInfo.prototype.getAdIsValue = function () {
        return '';
      };
      var Ad = function Ad() {};
      Ad.prototype = {
        pi: new AdPodInfo(),
        getAdId: function getAdId() {
          return '';
        },
        getAdPodInfo() {
          return this.pi;
        },
        getAdSystem: function getAdSystem() {
          return '';
        },
        getAdvertiserName: function getAdvertiserName() {
          return '';
        },
        getApiFramework: function getApiFramework() {
          return null;
        },
        getCompanionAds: function getCompanionAds() {
          return [];
        },
        getContentType: function getContentType() {
          return '';
        },
        getCreativeAdId: function getCreativeAdId() {
          return '';
        },
        getDealId: function getDealId() {
          return '';
        },
        getDescription: function getDescription() {
          return '';
        },
        getDuration: function getDuration() {
          return 8.5;
        },
        getHeight: function getHeight() {
          return 0;
        },
        getMediaUrl: function getMediaUrl() {
          return null;
        },
        getMinSuggestedDuration: function getMinSuggestedDuration() {
          return -2;
        },
        getSkipTimeOffset: function getSkipTimeOffset() {
          return -1;
        },
        getSurveyUrl: function getSurveyUrl() {
          return null;
        },
        getTitle: function getTitle() {
          return '';
        },
        getTraffickingParametersString: function getTraffickingParametersString() {
          return '';
        },
        getUiElements: function getUiElements() {
          return [''];
        },
        getUniversalAdIdRegistry: function getUniversalAdIdRegistry() {
          return 'unknown';
        },
        getUniversalAdIds: function getUniversalAdIds() {
          return [new UniversalAdIdInfo()];
        },
        getUniversalAdIdValue: function getUniversalAdIdValue() {
          return 'unknown';
        },
        getVastMediaBitrate: function getVastMediaBitrate() {
          return 0;
        },
        getVastMediaHeight: function getVastMediaHeight() {
          return 0;
        },
        getVastMediaWidth: function getVastMediaWidth() {
          return 0;
        },
        getWidth: function getWidth() {
          return 0;
        },
        getWrapperAdIds: function getWrapperAdIds() {
          return [''];
        },
        getWrapperAdSystems: function getWrapperAdSystems() {
          return [''];
        },
        getWrapperCreativeIds: function getWrapperCreativeIds() {
          return [''];
        },
        isLinear: function isLinear() {
          return true;
        },
        isSkippable() {
          return true;
        }
      };
      var CompanionAd = function CompanionAd() {};
      CompanionAd.prototype = {
        getAdSlotId: function getAdSlotId() {
          return '';
        },
        getContent: function getContent() {
          return '';
        },
        getContentType: function getContentType() {
          return '';
        },
        getHeight: function getHeight() {
          return 1;
        },
        getWidth: function getWidth() {
          return 1;
        }
      };
      var AdError = function AdError(type, code, vast, message, adsRequest, userRequestContext) {
        this.errorCode = code;
        this.message = message;
        this.type = type;
        this.adsRequest = adsRequest;
        this.userRequestContext = userRequestContext;
        this.getErrorCode = function () {
          return this.errorCode;
        };
        this.getInnerError = function () {
          return null;
        };
        this.getMessage = function () {
          return this.message;
        };
        this.getType = function () {
          return this.type;
        };
        this.getVastErrorCode = function () {
          return this.vastErrorCode;
        };
        this.toString = function () {
          return "AdError ".concat(this.errorCode, ": ").concat(this.message);
        };
      };
      AdError.ErrorCode = {};
      AdError.Type = {};
      var isEngadget = function isEngadget() {
        try {
          // eslint-disable-next-line no-restricted-syntax
          for (var _i3 = 0, _Object$values = Object.values(window.vidible._getContexts()); _i3 < _Object$values.length; _i3++) {
            var _ctx$getPlayer, _ctx$getPlayer$div;
            var ctx = _Object$values[_i3];
            // eslint-disable-next-line no-restricted-properties
            if ((_ctx$getPlayer = ctx.getPlayer()) !== null && _ctx$getPlayer !== void 0 && (_ctx$getPlayer$div = _ctx$getPlayer.div) !== null && _ctx$getPlayer$div !== void 0 && _ctx$getPlayer$div.innerHTML.includes('www.engadget.com')) {
              return true;
            }
          }
        } catch (e) {} // eslint-disable-line no-empty
        return false;
      };
      var currentAd = isEngadget() ? undefined : new Ad();
      var AdEvent = function AdEvent(type) {
        this.type = type;
      };
      AdEvent.prototype = {
        getAd: function getAd() {
          return currentAd;
        },
        getAdData: function getAdData() {}
      };
      AdEvent.Type = {
        AD_BREAK_READY: 'adBreakReady',
        AD_BUFFERING: 'adBuffering',
        AD_CAN_PLAY: 'adCanPlay',
        AD_METADATA: 'adMetadata',
        AD_PROGRESS: 'adProgress',
        ALL_ADS_COMPLETED: 'allAdsCompleted',
        CLICK: 'click',
        COMPLETE: 'complete',
        CONTENT_PAUSE_REQUESTED: 'contentPauseRequested',
        CONTENT_RESUME_REQUESTED: 'contentResumeRequested',
        DURATION_CHANGE: 'durationChange',
        EXPANDED_CHANGED: 'expandedChanged',
        FIRST_QUARTILE: 'firstQuartile',
        IMPRESSION: 'impression',
        INTERACTION: 'interaction',
        LINEAR_CHANGE: 'linearChange',
        LINEAR_CHANGED: 'linearChanged',
        LOADED: 'loaded',
        LOG: 'log',
        MIDPOINT: 'midpoint',
        PAUSED: 'pause',
        RESUMED: 'resume',
        SKIPPABLE_STATE_CHANGED: 'skippableStateChanged',
        SKIPPED: 'skip',
        STARTED: 'start',
        THIRD_QUARTILE: 'thirdQuartile',
        USER_CLOSE: 'userClose',
        VIDEO_CLICKED: 'videoClicked',
        VIDEO_ICON_CLICKED: 'videoIconClicked',
        VIEWABLE_IMPRESSION: 'viewable_impression',
        VOLUME_CHANGED: 'volumeChange',
        VOLUME_MUTED: 'mute'
      };
      var AdErrorEvent = function AdErrorEvent(error) {
        this.error = error;
        this.type = 'adError';
        this.getError = function () {
          return this.error;
        };
        this.getUserRequestContext = function () {
          var _this$error;
          if ((_this$error = this.error) !== null && _this$error !== void 0 && _this$error.userRequestContext) {
            return this.error.userRequestContext;
          }
          return {};
        };
      };
      AdErrorEvent.Type = {
        AD_ERROR: 'adError'
      };
      var CustomContentLoadedEvent = function CustomContentLoadedEvent() {};
      CustomContentLoadedEvent.Type = {
        CUSTOM_CONTENT_LOADED: 'deprecated-event'
      };
      var CompanionAdSelectionSettings = function CompanionAdSelectionSettings() {};
      CompanionAdSelectionSettings.CreativeType = {
        ALL: 'All',
        FLASH: 'Flash',
        IMAGE: 'Image'
      };
      CompanionAdSelectionSettings.ResourceType = {
        ALL: 'All',
        HTML: 'Html',
        IFRAME: 'IFrame',
        STATIC: 'Static'
      };
      CompanionAdSelectionSettings.SizeCriteria = {
        IGNORE: 'IgnoreSize',
        SELECT_EXACT_MATCH: 'SelectExactMatch',
        SELECT_NEAR_MATCH: 'SelectNearMatch'
      };
      var AdCuePoints = function AdCuePoints() {};
      AdCuePoints.prototype = {
        getCuePoints: function getCuePoints() {
          return [];
        },
        getAdIdRegistry: function getAdIdRegistry() {
          return '';
        },
        getAdIdValue: function getAdIdValue() {
          return '';
        }
      };
      var AdProgressData = noopFunc;
      Object.assign(ima, {
        AdCuePoints,
        AdDisplayContainer,
        AdError,
        AdErrorEvent,
        AdEvent,
        AdPodInfo,
        AdProgressData,
        AdsLoader,
        AdsManager: manager,
        AdsManagerLoadedEvent,
        AdsRenderingSettings,
        AdsRequest,
        CompanionAd,
        CompanionAdSelectionSettings,
        CustomContentLoadedEvent,
        gptProxyInstance: {},
        ImaSdkSettings,
        OmidAccessMode: {
          DOMAIN: 'domain',
          FULL: 'full',
          LIMITED: 'limited'
        },
        OmidVerificationVendor: {
          1: 'OTHER',
          2: 'MOAT',
          3: 'DOUBLEVERIFY',
          4: 'INTEGRAL_AD_SCIENCE',
          5: 'PIXELATE',
          6: 'NIELSEN',
          7: 'COMSCORE',
          8: 'MEETRICS',
          9: 'GOOGLE',
          OTHER: 1,
          MOAT: 2,
          DOUBLEVERIFY: 3,
          INTEGRAL_AD_SCIENCE: 4,
          PIXELATE: 5,
          NIELSEN: 6,
          COMSCORE: 7,
          MEETRICS: 8,
          GOOGLE: 9
        },
        settings: new ImaSdkSettings(),
        UiElements: {
          AD_ATTRIBUTION: 'adAttribution',
          COUNTDOWN: 'countdown'
        },
        UniversalAdIdInfo,
        VERSION,
        ViewMode: {
          FULLSCREEN: 'fullscreen',
          NORMAL: 'normal'
        }
      });
      if (!window.google) {
        window.google = {};
      }

      // Workaround for https://github.com/AdguardTeam/Scriptlets/issues/331
      // To avoid conflicts with the DAI SDK, we need to make sure that the
      // google.ima.dai namespace is not overwritten.
      // TODO: Later we should create a mock for the DAI SDK as well.
      // See https://github.com/AdguardTeam/Scriptlets/issues/239
      if ((_window$google$ima = window.google.ima) !== null && _window$google$ima !== void 0 && _window$google$ima.dai) {
        ima.dai = window.google.ima.dai;
      }
      window.google.ima = ima;
      hit(source);
    }
    GoogleIma3$1.names = ['google-ima3',
    // prefixed name
    'ubo-google-ima.js',
    // original ubo name
    'google-ima.js'];
    GoogleIma3$1.injections = [hit, noopFunc, logMessage];

    /* eslint-disable max-len */
    /**
     * @redirect googlesyndication-adsbygoogle
     *
     * @description
     * Mocks Google AdSense API.
     *
     * Related UBO redirect resource:
     * https://github.com/gorhill/uBlock/blob/master/src/web_accessible_resources/googlesyndication_adsbygoogle.js
     *
     * ### Examples
     *
     * ```adblock
     * ||pagead2.googlesyndication.com/pagead/js/adsbygoogle.js$script,redirect=googlesyndication-adsbygoogle
     * ```
     *
     * @added v1.0.10.
     */
    /* eslint-enable max-len */
    function GoogleSyndicationAdsByGoogle$1(source) {
      window.adsbygoogle = {
        // https://github.com/AdguardTeam/Scriptlets/issues/113
        // length: 0,
        loaded: true,
        // https://github.com/AdguardTeam/Scriptlets/issues/184
        push(arg) {
          if (typeof this.length === 'undefined') {
            this.length = 0;
            this.length += 1;
          }
          if (arg !== null && arg instanceof Object && arg.constructor.name === 'Object') {
            // eslint-disable-next-line no-restricted-syntax
            for (var _i = 0, _Object$keys = Object.keys(arg); _i < _Object$keys.length; _i++) {
              var key = _Object$keys[_i];
              if (typeof arg[key] === 'function') {
                try {
                  // https://github.com/AdguardTeam/Scriptlets/issues/252
                  // argument "{}" is needed to fix issue with undefined argument
                  arg[key].call(this, {});
                } catch (_unused) {
                  /* empty */
                }
              }
            }
          }
        }
      };
      var adElems = document.querySelectorAll('.adsbygoogle');
      var css = 'height:1px!important;max-height:1px!important;max-width:1px!important;width:1px!important;';
      var statusAttrName = 'data-adsbygoogle-status';
      var ASWIFT_IFRAME_MARKER = 'aswift_';
      var GOOGLE_ADS_IFRAME_MARKER = 'google_ads_iframe_';
      var executed = false;
      for (var i = 0; i < adElems.length; i += 1) {
        var adElemChildNodes = adElems[i].childNodes;
        var childNodesQuantity = adElemChildNodes.length;
        // childNodes of .adsbygoogle can be defined if scriptlet was executed before
        // so we should check that childNodes are exactly defined by us
        // TODO: remake after scriptlets context developing in 1.3
        var areIframesDefined = false;
        if (childNodesQuantity > 0) {
          // it should be only 2 child iframes if scriptlet was executed
          areIframesDefined = childNodesQuantity === 2
          // the first of child nodes should be aswift iframe
          && adElemChildNodes[0].nodeName.toLowerCase() === 'iframe' && adElemChildNodes[0].id.includes(ASWIFT_IFRAME_MARKER)
          // the second of child nodes should be google_ads iframe
          && adElemChildNodes[1].nodeName.toLowerCase() === 'iframe' && adElemChildNodes[1].id.includes(GOOGLE_ADS_IFRAME_MARKER);
        }
        if (!areIframesDefined) {
          // here we do the job if scriptlet has not been executed earlier
          adElems[i].setAttribute(statusAttrName, 'done');
          var aswiftIframe = document.createElement('iframe');
          aswiftIframe.id = "".concat(ASWIFT_IFRAME_MARKER).concat(i);
          aswiftIframe.style = css;
          adElems[i].appendChild(aswiftIframe);
          var innerAswiftIframe = document.createElement('iframe');
          aswiftIframe.contentWindow.document.body.appendChild(innerAswiftIframe);
          var googleadsIframe = document.createElement('iframe');
          googleadsIframe.id = "".concat(GOOGLE_ADS_IFRAME_MARKER).concat(i);
          googleadsIframe.style = css;
          adElems[i].appendChild(googleadsIframe);
          var innerGoogleadsIframe = document.createElement('iframe');
          googleadsIframe.contentWindow.document.body.appendChild(innerGoogleadsIframe);
          executed = true;
        }
      }
      if (executed) {
        hit(source);
      }
    }
    GoogleSyndicationAdsByGoogle$1.names = ['googlesyndication-adsbygoogle', 'ubo-googlesyndication_adsbygoogle.js', 'googlesyndication_adsbygoogle.js'];
    GoogleSyndicationAdsByGoogle$1.injections = [hit];

    /* eslint-disable func-names */

    /**
     * @redirect googletagservices-gpt
     *
     * @description
     * Mocks Google Publisher Tag API.
     *
     * Related UBO redirect resource:
     * https://github.com/gorhill/uBlock/blob/master/src/web_accessible_resources/googletagservices_gpt.js
     *
     * ### Examples
     *
     * ```adblock
     * ||googletagservices.com/tag/js/gpt.js$script,redirect=googletagservices-gpt
     * ```
     *
     * @added v1.0.10.
     */
    function GoogleTagServicesGpt$1(source) {
      var slots = new Map();
      var slotsById = new Map();
      var slotsPerPath = new Map();
      var slotCreatives = new Map();
      var eventCallbacks = new Map();
      var gTargeting = new Map();
      var addEventListener = function addEventListener(name, listener) {
        if (!eventCallbacks.has(name)) {
          eventCallbacks.set(name, new Set());
        }
        eventCallbacks.get(name).add(listener);
        return this;
      };
      var removeEventListener = function removeEventListener(name, listener) {
        if (eventCallbacks.has(name)) {
          return eventCallbacks.get(name).delete(listener);
        }
        return false;
      };
      var fireSlotEvent = function fireSlotEvent(name, slot) {
        return new Promise(function (resolve) {
          requestAnimationFrame(function () {
            var size = [0, 0];
            var callbacksSet = eventCallbacks.get(name) || [];
            var callbackArray = Array.from(callbacksSet);
            for (var i = 0; i < callbackArray.length; i += 1) {
              callbackArray[i]({
                isEmpty: true,
                size,
                slot
              });
            }
            resolve();
          });
        });
      };
      var emptySlotElement = function emptySlotElement(slot) {
        var node = document.getElementById(slot.getSlotElementId());
        while (node !== null && node !== void 0 && node.lastChild) {
          node.lastChild.remove();
        }
      };
      var recreateIframeForSlot = function recreateIframeForSlot(slot) {
        var _document$getElementB;
        var eid = "google_ads_iframe_".concat(slot.getId());
        (_document$getElementB = document.getElementById(eid)) === null || _document$getElementB === void 0 ? void 0 : _document$getElementB.remove();
        var node = document.getElementById(slot.getSlotElementId());
        if (node) {
          var f = document.createElement('iframe');
          f.id = eid;
          f.srcdoc = '<body></body>';
          f.style = 'position:absolute; width:0; height:0; left:0; right:0; z-index:-1; border:0';
          f.setAttribute('width', 0);
          f.setAttribute('height', 0);
          // https://github.com/AdguardTeam/Scriptlets/issues/259
          f.setAttribute('data-load-complete', true);
          f.setAttribute('data-google-container-id', true);
          f.setAttribute('sandbox', '');
          node.appendChild(f);
        }
      };
      var displaySlot = function displaySlot(slot) {
        if (!slot) {
          return;
        }
        var id = slot.getSlotElementId();
        if (!document.getElementById(id)) {
          return;
        }
        var parent = document.getElementById(id);
        if (parent) {
          parent.appendChild(document.createElement('div'));
        }
        emptySlotElement(slot);
        recreateIframeForSlot(slot);
        fireSlotEvent('slotRenderEnded', slot);
        fireSlotEvent('slotRequested', slot);
        fireSlotEvent('slotResponseReceived', slot);
        fireSlotEvent('slotOnload', slot);
        fireSlotEvent('impressionViewable', slot);
      };
      var companionAdsService = {
        addEventListener,
        removeEventListener,
        enableSyncLoading: noopFunc,
        setRefreshUnfilledSlots: noopFunc,
        getSlots: noopArray
      };
      var contentService = {
        addEventListener,
        removeEventListener,
        setContent: noopFunc
      };
      function PassbackSlot() {} // constructor

      PassbackSlot.prototype.display = noopFunc;
      PassbackSlot.prototype.get = noopNull;
      PassbackSlot.prototype.set = noopThis;
      PassbackSlot.prototype.setClickUrl = noopThis;
      PassbackSlot.prototype.setTagForChildDirectedTreatment = noopThis;
      PassbackSlot.prototype.setTargeting = noopThis;
      PassbackSlot.prototype.updateTargetingFromMap = noopThis;
      function SizeMappingBuilder() {} // constructor
      SizeMappingBuilder.prototype.addSize = noopThis;
      SizeMappingBuilder.prototype.build = noopNull;
      var getTargetingValue = function getTargetingValue(v) {
        if (typeof v === 'string') {
          return [v];
        }
        try {
          return Array.prototype.flat.call(v);
        } catch (_unused) {
          // do nothing
        }
        return [];
      };
      var updateTargeting = function updateTargeting(targeting, map) {
        if (typeof map === 'object') {
          for (var key in map) {
            if (Object.prototype.hasOwnProperty.call(map, key)) {
              targeting.set(key, getTargetingValue(map[key]));
            }
          }
        }
      };
      var defineSlot = function defineSlot(adUnitPath, creatives, optDiv) {
        if (slotsById.has(optDiv)) {
          var _document$getElementB2;
          (_document$getElementB2 = document.getElementById(optDiv)) === null || _document$getElementB2 === void 0 ? void 0 : _document$getElementB2.remove();
          return slotsById.get(optDiv);
        }
        var attributes = new Map();
        var targeting = new Map();
        var exclusions = new Set();
        var response = {
          advertiserId: undefined,
          campaignId: undefined,
          creativeId: undefined,
          creativeTemplateId: undefined,
          lineItemId: undefined
        };
        var sizes = [{
          getHeight: function getHeight() {
            return 2;
          },
          getWidth: function getWidth() {
            return 2;
          }
        }];
        var num = (slotsPerPath.get(adUnitPath) || 0) + 1;
        slotsPerPath.set(adUnitPath, num);
        var id = "".concat(adUnitPath, "_").concat(num);
        var clickUrl = '';
        var collapseEmptyDiv = null;
        var services = new Set();
        var slot = {
          addService(e) {
            services.add(e);
            return slot;
          },
          clearCategoryExclusions: noopThis,
          clearTargeting(k) {
            if (k === undefined) {
              targeting.clear();
            } else {
              targeting.delete(k);
            }
          },
          defineSizeMapping(mapping) {
            slotCreatives.set(optDiv, mapping);
            return this;
          },
          get: function get(k) {
            return attributes.get(k);
          },
          getAdUnitPath: function getAdUnitPath() {
            return adUnitPath;
          },
          getAttributeKeys: function getAttributeKeys() {
            return Array.from(attributes.keys());
          },
          getCategoryExclusions: function getCategoryExclusions() {
            return Array.from(exclusions);
          },
          getClickUrl: function getClickUrl() {
            return clickUrl;
          },
          getCollapseEmptyDiv: function getCollapseEmptyDiv() {
            return collapseEmptyDiv;
          },
          getContentUrl: function getContentUrl() {
            return '';
          },
          getDivStartsCollapsed: function getDivStartsCollapsed() {
            return null;
          },
          getDomId: function getDomId() {
            return optDiv;
          },
          getEscapedQemQueryId: function getEscapedQemQueryId() {
            return '';
          },
          getFirstLook: function getFirstLook() {
            return 0;
          },
          getId: function getId() {
            return id;
          },
          getHtml: function getHtml() {
            return '';
          },
          getName: function getName() {
            return id;
          },
          getOutOfPage: function getOutOfPage() {
            return false;
          },
          getResponseInformation: function getResponseInformation() {
            return response;
          },
          getServices: function getServices() {
            return Array.from(services);
          },
          getSizes: function getSizes() {
            return sizes;
          },
          getSlotElementId: function getSlotElementId() {
            return optDiv;
          },
          getSlotId: function getSlotId() {
            return slot;
          },
          getTargeting: function getTargeting(k) {
            return targeting.get(k) || gTargeting.get(k) || [];
          },
          getTargetingKeys: function getTargetingKeys() {
            return Array.from(new Set(Array.of(...gTargeting.keys(), ...targeting.keys())));
          },
          getTargetingMap: function getTargetingMap() {
            return Object.assign(Object.fromEntries(gTargeting.entries()), Object.fromEntries(targeting.entries()));
          },
          set(k, v) {
            attributes.set(k, v);
            return slot;
          },
          setCategoryExclusion(e) {
            exclusions.add(e);
            return slot;
          },
          setClickUrl(u) {
            clickUrl = u;
            return slot;
          },
          setCollapseEmptyDiv(v) {
            collapseEmptyDiv = !!v;
            return slot;
          },
          setSafeFrameConfig: noopThis,
          setTagForChildDirectedTreatment: noopThis,
          setTargeting(k, v) {
            targeting.set(k, getTargetingValue(v));
            return slot;
          },
          toString: function toString() {
            return id;
          },
          updateTargetingFromMap(map) {
            updateTargeting(targeting, map);
            return slot;
          }
        };
        slots.set(adUnitPath, slot);
        slotsById.set(optDiv, slot);
        slotCreatives.set(optDiv, creatives);
        return slot;
      };
      var pubAdsService = {
        addEventListener,
        removeEventListener,
        clear: noopFunc,
        clearCategoryExclusions: noopThis,
        clearTagForChildDirectedTreatment: noopThis,
        clearTargeting(k) {
          if (k === undefined) {
            gTargeting.clear();
          } else {
            gTargeting.delete(k);
          }
        },
        collapseEmptyDivs: noopFunc,
        defineOutOfPagePassback() {
          return new PassbackSlot();
        },
        definePassback() {
          return new PassbackSlot();
        },
        disableInitialLoad: noopFunc,
        display: noopFunc,
        enableAsyncRendering: noopFunc,
        enableLazyLoad: noopFunc,
        enableSingleRequest: noopFunc,
        enableSyncRendering: noopFunc,
        enableVideoAds: noopFunc,
        get: noopNull,
        getAttributeKeys: noopArray,
        getTargeting: noopArray,
        getTargetingKeys: noopArray,
        getSlots: noopArray,
        isInitialLoadDisabled: trueFunc,
        refresh: noopFunc,
        set: noopThis,
        setCategoryExclusion: noopThis,
        setCentering: noopFunc,
        setCookieOptions: noopThis,
        setForceSafeFrame: noopThis,
        setLocation: noopThis,
        setPrivacySettings: noopThis,
        setPublisherProvidedId: noopThis,
        setRequestNonPersonalizedAds: noopThis,
        setSafeFrameConfig: noopThis,
        setTagForChildDirectedTreatment: noopThis,
        setTargeting: noopThis,
        setVideoContent: noopThis,
        updateCorrelator: noopFunc
      };
      var _window = window,
        _window$googletag = _window.googletag,
        googletag = _window$googletag === void 0 ? {} : _window$googletag;
      var _googletag$cmd = googletag.cmd,
        cmd = _googletag$cmd === void 0 ? [] : _googletag$cmd;
      googletag.apiReady = true;
      googletag.cmd = [];
      googletag.cmd.push = function (a) {
        try {
          a();
          // eslint-disable-next-line no-empty
        } catch (ex) {}
        return 1;
      };
      googletag.companionAds = function () {
        return companionAdsService;
      };
      googletag.content = function () {
        return contentService;
      };
      googletag.defineOutOfPageSlot = defineSlot;
      googletag.defineSlot = defineSlot;
      googletag.destroySlots = function () {
        slots.clear();
        slotsById.clear();
      };
      googletag.disablePublisherConsole = noopFunc;
      googletag.display = function (arg) {
        var id;
        if (arg !== null && arg !== void 0 && arg.getSlotElementId) {
          id = arg.getSlotElementId();
        } else if (arg !== null && arg !== void 0 && arg.nodeType) {
          id = arg.id;
        } else {
          id = String(arg);
        }
        displaySlot(slotsById.get(id));
      };
      googletag.enableServices = noopFunc;
      googletag.getVersion = noopStr;
      googletag.pubads = function () {
        return pubAdsService;
      };
      googletag.pubadsReady = true;
      googletag.setAdIframeTitle = noopFunc;
      googletag.sizeMapping = function () {
        return new SizeMappingBuilder();
      };
      window.googletag = googletag;
      while (cmd.length !== 0) {
        googletag.cmd.push(cmd.shift());
      }
      hit(source);
    }
    GoogleTagServicesGpt$1.names = ['googletagservices-gpt', 'ubo-googletagservices_gpt.js', 'googletagservices_gpt.js'];
    GoogleTagServicesGpt$1.injections = [hit, noopFunc, noopThis, noopNull, noopArray, noopStr, trueFunc];

    /* eslint-disable func-names */

    /**
     * @redirect matomo
     *
     * @description
     * Mocks the piwik.js file of Matomo (formerly Piwik).
     *
     * ### Examples
     *
     * ```adblock
     * ||example.org/piwik.js$script,redirect=matomo
     * ```
     *
     * @added v1.5.0.
     */

    function Matomo$1(source) {
      var Tracker = function Tracker() {};
      Tracker.prototype.setDoNotTrack = noopFunc;
      Tracker.prototype.setDomains = noopFunc;
      Tracker.prototype.setCustomDimension = noopFunc;
      Tracker.prototype.trackPageView = noopFunc;
      var AsyncTracker = function AsyncTracker() {};
      AsyncTracker.prototype.addListener = noopFunc;
      var matomoWrapper = {
        getTracker: Tracker,
        getAsyncTracker: AsyncTracker
      };
      window.Piwik = matomoWrapper;
      hit(source);
    }
    Matomo$1.names = ['matomo'];
    Matomo$1.injections = [hit, noopFunc];

    /**
     * @redirect metrika-yandex-tag
     *
     * @description
     * Mocks Yandex Metrika API.
     * https://yandex.ru/support/metrica/objects/method-reference.html
     *
     * ### Examples
     *
     * ```adblock
     * ||mc.yandex.ru/metrika/tag.js$script,redirect=metrika-yandex-tag
     * ```
     *
     * @added v1.0.10.
     */
    function metrikaYandexTag$1(source) {
      var asyncCallbackFromOptions = function asyncCallbackFromOptions(id, param) {
        var options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
        var callback = options.callback;
        var ctx = options.ctx;
        if (typeof callback === 'function') {
          callback = ctx !== undefined ? callback.bind(ctx) : callback;
          setTimeout(function () {
            return callback();
          });
        }
      };

      /**
       * https://yandex.ru/support/metrica/objects/addfileextension.html
       */
      var addFileExtension = noopFunc;

      /**
       * https://yandex.ru/support/metrica/objects/extlink.html
       */
      var extLink = asyncCallbackFromOptions;

      /**
       * https://yandex.ru/support/metrica/objects/file.html
       */
      var file = asyncCallbackFromOptions;

      /**
       * https://yandex.ru/support/metrica/objects/get-client-id.html
       *
       * @param {string} id
       * @param {Function} cb
       */
      var getClientID = function getClientID(id, cb) {
        if (!cb) {
          return;
        }
        setTimeout(cb(null));
      };

      /**
       * https://yandex.ru/support/metrica/objects/hit.html
       */
      var hitFunc = asyncCallbackFromOptions;

      /**
       * https://yandex.ru/support/metrica/objects/notbounce.html
       */
      var notBounce = asyncCallbackFromOptions;

      /**
       * https://yandex.ru/support/metrica/objects/params-method.html
       */
      var params = noopFunc;

      /**
       * https://yandex.ru/support/metrica/objects/reachgoal.html
       *
       * @param {string} id
       * @param {string} target
       * @param {object} params
       * @param {Function} callback
       * @param {any} ctx
       */
      var reachGoal = function reachGoal(id, target, params, callback, ctx) {
        asyncCallbackFromOptions(null, null, {
          callback,
          ctx
        });
      };

      /**
       * https://yandex.ru/support/metrica/objects/set-user-id.html
       */
      var setUserID = noopFunc;

      /**
       * https://yandex.ru/support/metrica/objects/user-params.html
       */
      var userParams = noopFunc;

      // https://github.com/AdguardTeam/Scriptlets/issues/198
      var destruct = noopFunc;
      var api = {
        addFileExtension,
        extLink,
        file,
        getClientID,
        hit: hitFunc,
        notBounce,
        params,
        reachGoal,
        setUserID,
        userParams,
        destruct
      };
      function ym(id, funcName) {
        for (var _len = arguments.length, args = new Array(_len > 2 ? _len - 2 : 0), _key = 2; _key < _len; _key++) {
          args[_key - 2] = arguments[_key];
        }
        return api[funcName] && api[funcName](id, ...args);
      }
      function init(id) {
        // yaCounter object should provide api
        window["yaCounter".concat(id)] = api;
        document.dispatchEvent(new Event("yacounter".concat(id, "inited")));
      }
      if (typeof window.ym === 'undefined') {
        window.ym = ym;
        ym.a = [];
      } else if (window.ym && window.ym.a) {
        // Keep initial counters array intact
        ym.a = window.ym.a;
        window.ym = ym;
        window.ym.a.forEach(function (params) {
          var id = params[0];
          init(id);
        });
      }
      hit(source);
    }
    metrikaYandexTag$1.names = ['metrika-yandex-tag'];
    metrikaYandexTag$1.injections = [hit, noopFunc];

    /**
     * @redirect metrika-yandex-watch
     *
     * @description
     * Mocks the old Yandex Metrika API.
     * https://yandex.ru/support/metrica/objects/_method-reference.html
     *
     * ### Examples
     *
     * ```adblock
     * ||mc.yandex.ru/metrika/watch.js$script,redirect=metrika-yandex-watch
     * ```
     *
     * @added v1.0.10.
     */
    function metrikaYandexWatch$1(source) {
      var cbName = 'yandex_metrika_callbacks';

      /**
       * Gets callback and its context from options and call it in async way
       *
       * @param {object} options Yandex Metrika API options
       */
      var asyncCallbackFromOptions = function asyncCallbackFromOptions() {
        var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
        var callback = options.callback;
        var ctx = options.ctx;
        if (typeof callback === 'function') {
          callback = ctx !== undefined ? callback.bind(ctx) : callback;
          setTimeout(function () {
            return callback();
          });
        }
      };
      function Metrika() {} // constructor
      Metrika.counters = noopArray;
      // Methods without options
      Metrika.prototype.addFileExtension = noopFunc;
      Metrika.prototype.getClientID = noopFunc;
      Metrika.prototype.setUserID = noopFunc;
      Metrika.prototype.userParams = noopFunc;
      Metrika.prototype.params = noopFunc;
      Metrika.prototype.counters = noopArray;

      // Methods with options
      // The order of arguments should be kept in according to API
      Metrika.prototype.extLink = function (url, options) {
        asyncCallbackFromOptions(options);
      };
      Metrika.prototype.file = function (url, options) {
        asyncCallbackFromOptions(options);
      };
      Metrika.prototype.hit = function (url, options) {
        asyncCallbackFromOptions(options);
      };
      Metrika.prototype.reachGoal = function (target, params, cb, ctx) {
        asyncCallbackFromOptions({
          callback: cb,
          ctx
        });
      };
      Metrika.prototype.notBounce = asyncCallbackFromOptions;
      if (window.Ya) {
        window.Ya.Metrika = Metrika;
      } else {
        window.Ya = {
          Metrika
        };
      }
      if (window[cbName] && Array.isArray(window[cbName])) {
        window[cbName].forEach(function (func) {
          if (typeof func === 'function') {
            func();
          }
        });
      }
      hit(source);
    }
    metrikaYandexWatch$1.names = ['metrika-yandex-watch'];
    metrikaYandexWatch$1.injections = [hit, noopFunc, noopArray];

    /* eslint-disable func-names */

    /**
     * @redirect naver-wcslog
     *
     * @description
     * Mocks wcslog.js of Naver Analytics.
     *
     * ### Examples
     *
     * ```adblock
     * ||wcs.naver.net/wcslog.js$script,redirect=naver-wcslog
     * ```
     *
     * @added v1.6.2.
     */

    function NaverWcslog$1(source) {
      window.wcs_add = {};
      window.wcs_do = noopFunc;
      window.wcs = {
        inflow: noopFunc
      };
      hit(source);
    }
    NaverWcslog$1.names = ['naver-wcslog'];
    NaverWcslog$1.injections = [hit, noopFunc];

    /* eslint-disable func-names */

    /**
     * @redirect pardot-1.0
     *
     * @description
     * Mocks the pd.js file of Salesforce.
     * https://pi.pardot.com/pd.js
     * https://developer.salesforce.com/docs/marketing/pardot/overview
     *
     * ### Examples
     *
     * ```adblock
     * ||pi.pardot.com/pd.js$script,redirect=pardot
     * ||pacedg.com.au/pd.js$redirect=pardot
     * ```
     *
     * @added v1.6.55.
     */

    function Pardot$1(source) {
      window.piVersion = '1.0.2';
      window.piScriptNum = 0;
      window.piScriptObj = [];
      window.checkNamespace = noopFunc;
      window.getPardotUrl = noopStr;
      window.piGetParameter = noopNull;
      window.piSetCookie = noopFunc;
      window.piGetCookie = noopStr;
      function piTracker() {
        window.pi = {
          tracker: {
            visitor_id: '',
            visitor_id_sign: '',
            pi_opt_in: '',
            campaign_id: ''
          }
        };
        window.piScriptNum += 1;
      }
      window.piResponse = noopFunc;
      window.piTracker = piTracker;
      piTracker();
      hit(source);
    }
    Pardot$1.names = ['pardot-1.0'];
    Pardot$1.injections = [hit, noopFunc, noopStr, noopNull];

    /* eslint-disable func-names */

    /**
     * @redirect prebid
     *
     * @description
     * Mocks the prebid.js header bidding suit.
     * https://docs.prebid.org/
     *
     * ### Examples
     *
     * ```adblock
     * ||example.org/bd/hb/prebid.js$script,redirect=prebid
     * ```
     *
     * @added v1.6.2.
     */

    function Prebid$1(source) {
      var pushFunction = function pushFunction(arg) {
        if (typeof arg === 'function') {
          try {
            arg.call();
          } catch (ex) {
            /* empty */
          }
        }
      };
      var pbjsWrapper = {
        addAdUnits() {},
        adServers: {
          dfp: {
            // https://docs.prebid.org/dev-docs/publisher-api-reference/adServers.dfp.buildVideoUrl.html
            // returns ad URL
            buildVideoUrl: noopStr
          }
        },
        adUnits: [],
        aliasBidder() {},
        cmd: [],
        enableAnalytics() {},
        getHighestCpmBids: noopArray,
        libLoaded: true,
        que: [],
        requestBids(arg) {
          if (arg instanceof Object && arg.bidsBackHandler) {
            try {
              arg.bidsBackHandler.call(); // https://docs.prebid.org/dev-docs/publisher-api-reference/requestBids.html
            } catch (ex) {
              /* empty */
            }
          }
        },
        removeAdUnit() {},
        setBidderConfig() {},
        setConfig() {},
        setTargetingForGPTAsync() {}
      };
      pbjsWrapper.cmd.push = pushFunction;
      pbjsWrapper.que.push = pushFunction;
      window.pbjs = pbjsWrapper;
      hit(source);
    }
    Prebid$1.names = ['prebid'];
    Prebid$1.injections = [hit, noopFunc, noopStr, noopArray];

    /**
     * @redirect scorecardresearch-beacon
     *
     * @description
     * Mocks Scorecard Research API.
     *
     * Related UBO redirect resource:
     * https://github.com/gorhill/uBlock/blob/master/src/web_accessible_resources/scorecardresearch_beacon.js
     *
     * ### Examples
     *
     * ```adblock
     * ||sb.scorecardresearch.com/beacon.js$script,redirect=scorecardresearch-beacon
     * ```
     *
     * @added v1.0.10.
     */
    function ScoreCardResearchBeacon$1(source) {
      window.COMSCORE = {
        purge() {
          // eslint-disable-next-line no-underscore-dangle
          window._comscore = [];
        },
        beacon() {}
      };
      hit(source);
    }
    ScoreCardResearchBeacon$1.names = ['scorecardresearch-beacon', 'ubo-scorecardresearch_beacon.js', 'scorecardresearch_beacon.js'];
    ScoreCardResearchBeacon$1.injections = [hit];

    /**
     * This file must export all scriptlets which should be accessible
     */

    var scriptletListRaw = /*#__PURE__*/Object.freeze({
        __proto__: null,
        AmazonApstag: AmazonApstag$1,
        DidomiLoader: DidomiLoader$1,
        Fingerprintjs2: Fingerprintjs2$1,
        Fingerprintjs3: Fingerprintjs3$1,
        Gemius: Gemius$1,
        GoogleAnalytics: GoogleAnalytics$1,
        GoogleAnalyticsGa: GoogleAnalyticsGa$1,
        GoogleIma3: GoogleIma3$1,
        GoogleSyndicationAdsByGoogle: GoogleSyndicationAdsByGoogle$1,
        GoogleTagServicesGpt: GoogleTagServicesGpt$1,
        Matomo: Matomo$1,
        NaverWcslog: NaverWcslog$1,
        Pardot: Pardot$1,
        Prebid: Prebid$1,
        ScoreCardResearchBeacon: ScoreCardResearchBeacon$1,
        abortCurrentInlineScript: abortCurrentInlineScript$1,
        abortOnPropertyRead: abortOnPropertyRead$1,
        abortOnPropertyWrite: abortOnPropertyWrite$1,
        abortOnStackTrace: abortOnStackTrace$1,
        adjustSetInterval: adjustSetInterval$1,
        adjustSetTimeout: adjustSetTimeout$1,
        callNoThrow: callNoThrow$1,
        debugCurrentInlineScript: debugCurrentInlineScript$1,
        debugOnPropertyRead: debugOnPropertyRead$1,
        debugOnPropertyWrite: debugOnPropertyWrite$1,
        dirString: dirString$1,
        disableNewtabLinks: disableNewtabLinks$1,
        evalDataPrune: evalDataPrune$1,
        forceWindowClose: forceWindowClose$1,
        hideInShadowDom: hideInShadowDom$1,
        hrefSanitizer: hrefSanitizer$1,
        injectCssInShadowDom: injectCssInShadowDom$1,
        jsonPrune: jsonPrune$1,
        jsonPruneFetchResponse: jsonPruneFetchResponse$1,
        jsonPruneXhrResponse: jsonPruneXhrResponse$1,
        log: log$1,
        logAddEventListener: logAddEventListener$1,
        logEval: logEval$1,
        logOnStacktrace: logOnStacktrace$1,
        m3uPrune: m3uPrune$1,
        metrikaYandexTag: metrikaYandexTag$1,
        metrikaYandexWatch: metrikaYandexWatch$1,
        noProtectedAudience: noProtectedAudience$1,
        noTopics: noTopics$1,
        noeval: noeval$1,
        nowebrtc: nowebrtc$1,
        preventAddEventListener: preventAddEventListener$1,
        preventAdfly: preventAdfly$1,
        preventBab: preventBab$2,
        preventElementSrcLoading: preventElementSrcLoading$1,
        preventEvalIf: preventEvalIf$1,
        preventFab: preventFab$1,
        preventFetch: preventFetch$1,
        preventPopadsNet: preventPopadsNet$1,
        preventRefresh: preventRefresh$1,
        preventRequestAnimationFrame: preventRequestAnimationFrame$1,
        preventSetInterval: preventSetInterval$1,
        preventSetTimeout: preventSetTimeout$1,
        preventWindowOpen: preventWindowOpen$1,
        preventXHR: preventXHR$1,
        removeAttr: removeAttr$1,
        removeClass: removeClass$1,
        removeCookie: removeCookie$1,
        removeInShadowDom: removeInShadowDom$1,
        removeNodeText: removeNodeText$1,
        setAttr: setAttr$1,
        setConstant: setConstant$1,
        setCookie: setCookie$1,
        setCookieReload: setCookieReload$1,
        setLocalStorageItem: setLocalStorageItem$1,
        setPopadsDummy: setPopadsDummy$1,
        setSessionStorageItem: setSessionStorageItem$1,
        spoofCSS: spoofCSS$1,
        trustedClickElement: trustedClickElement$1,
        trustedCreateElement: trustedCreateElement$1,
        trustedDispatchEvent: trustedDispatchEvent$1,
        trustedPruneInboundObject: trustedPruneInboundObject$1,
        trustedReplaceFetchResponse: trustedReplaceFetchResponse$1,
        trustedReplaceNodeText: trustedReplaceNodeText$1,
        trustedReplaceOutboundText: trustedReplaceOutboundText$1,
        trustedReplaceXhrResponse: trustedReplaceXhrResponse$1,
        trustedSetAttr: trustedSetAttr$1,
        trustedSetConstant: trustedSetConstant$1,
        trustedSetCookie: trustedSetCookie$1,
        trustedSetCookieReload: trustedSetCookieReload$1,
        trustedSetLocalStorageItem: trustedSetLocalStorageItem$1,
        trustedSetSessionStorageItem: trustedSetSessionStorageItem$1,
        trustedSuppressNativeMethod: trustedSuppressNativeMethod$1,
        xmlPrune: xmlPrune$1
    });

    function _typeof(obj) {
      "@babel/helpers - typeof";

      return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (obj) {
        return typeof obj;
      } : function (obj) {
        return obj && "function" == typeof Symbol && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj;
      }, _typeof(obj);
    }

    function _toPrimitive(input, hint) {
      if (_typeof(input) !== "object" || input === null) return input;
      var prim = input[Symbol.toPrimitive];
      if (prim !== undefined) {
        var res = prim.call(input, hint || "default");
        if (_typeof(res) !== "object") return res;
        throw new TypeError("@@toPrimitive must return a primitive value.");
      }
      return (hint === "string" ? String : Number)(input);
    }

    function _toPropertyKey(arg) {
      var key = _toPrimitive(arg, "string");
      return _typeof(key) === "symbol" ? key : String(key);
    }

    function _defineProperty(obj, key, value) {
      key = _toPropertyKey(key);
      if (key in obj) {
        Object.defineProperty(obj, key, {
          value: value,
          enumerable: true,
          configurable: true,
          writable: true
        });
      } else {
        obj[key] = value;
      }
      return obj;
    }

    function ownKeys$1(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); enumerableOnly && (symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; }
    function _objectSpread$1(target) { for (var i = 1; i < arguments.length; i++) { var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? ownKeys$1(Object(source), !0).forEach(function (key) { _defineProperty(target, key, source[key]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys$1(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } return target; }

    /**
     * Get rule node from string or rule node
     *
     * @param rule Rule in string or rule node format
     * @returns Rule node
     *
     * @throws If the rule is in string format and cannot be parsed
     */
    var getRuleNode = function getRuleNode(rule) {
      return typeof rule === 'string'
      // Note: AGTree does not support legacy script:inject syntax
      ? RuleParser.parse(rule, _objectSpread$1(_objectSpread$1({}, defaultParserOptions), {}, {
        includeRaws: false,
        isLocIncluded: false
      })) : rule;
    };

    /**
     * Get rule text from string or rule node
     *
     * @param rule Rule in string or rule node format
     * @returns Rule text
     */
    var getRuleText = function getRuleText(rule) {
      return typeof rule === 'string' ? rule : RuleParser.generate(rule);
    };

    function _createForOfIteratorHelper(o, allowArrayLike) { var it = typeof Symbol !== "undefined" && o[Symbol.iterator] || o["@@iterator"]; if (!it) { if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") { if (it) o = it; var i = 0; var F = function F() {}; return { s: F, n: function n() { if (i >= o.length) return { done: true }; return { done: false, value: o[i++] }; }, e: function e(_e) { throw _e; }, 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 normalCompletion = true, didErr = false, err; return { s: function s() { it = it.call(o); }, n: function n() { var step = it.next(); normalCompletion = step.done; return step; }, e: function e(_e2) { didErr = true; err = _e2; }, f: function f() { try { if (!normalCompletion && it.return != null) it.return(); } finally { if (didErr) throw err; } } }; }
    function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
    function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; return arr2; }

    /* ************************************************************************
     *
     * Scriptlets
     *
     ************************************************************************** */

    var UBO_JS_SUFFIX = '.js';

    /**
     * Helper function to determine if the rule is a scriptlet rule for the specified syntax
     *
     * @param rule - rule text
     * @param syntax - syntax of the rule
     * @returns true if given rule is scriptlet rule for the specified syntax
     */
    var isScriptletRuleForSyntax = function isScriptletRuleForSyntax(rule, syntax) {
      try {
        var ruleNode = getRuleNode(rule);
        return ruleNode.category === RuleCategory.Cosmetic && ruleNode.type === CosmeticRuleType.ScriptletInjectionRule && ruleNode.syntax === syntax;
      } catch (e) {
        return false;
      }
    };

    /**
     * Checks if the `rule` is AdGuard scriptlet rule
     *
     * @param rule - rule text
     * @returns true if given rule is adg rule
     */
    var isAdgScriptletRule = function isAdgScriptletRule(rule) {
      return isScriptletRuleForSyntax(rule, AdblockSyntax.Adg);
    };

    /**
     * Checks if the `rule` is uBO scriptlet rule
     *
     * @param rule rule text
     * @returns true if given rule is ubo rule
     */
    var isUboScriptletRule = function isUboScriptletRule(rule) {
      return isScriptletRuleForSyntax(rule, AdblockSyntax.Ubo);
    };

    /**
     * Checks if the `rule` is AdBlock Plus snippet
     *
     * @param rule rule text
     * @returns true if given rule is abp rule
     */
    var isAbpSnippetRule = function isAbpSnippetRule(rule) {
      return isScriptletRuleForSyntax(rule, AdblockSyntax.Abp);
    };

    /**
     * Returns array of scriptlet objects.
     * Needed for scriptlet name validation which will check aliases names.
     *
     * @returns Array of all scriptlet objects.
     */
    var getScriptletsObjList = function getScriptletsObjList() {
      return Object.values(scriptletListRaw);
    };

    /**
     * Finds scriptlet by the `name`.
     *
     * @param name Scriptlet name.
     * @param scriptlets Array of all scriptlet objects.
     * @returns {Function} Scriptlet function.
     */
    var getScriptletByName = function getScriptletByName(name, scriptlets) {
      var allScriptletsFns = scriptlets || getScriptletsObjList();
      return allScriptletsFns.find(function (s) {
        return s.names
        // full match name checking
        && (s.names.includes(name)
        // or check ubo alias name without '.js' at the end
        || !name.endsWith(UBO_JS_SUFFIX) && s.names.includes("".concat(name).concat(UBO_JS_SUFFIX)));
      });
    };
    var scriptletObjects = getScriptletsObjList();

    /**
     * Checks whether the scriptlet `name` is valid by checking the scriptlet list object.
     *
     * @param name Scriptlet name.
     * @returns True if scriptlet name is valid.
     */
    var isValidScriptletNameNotCached = function isValidScriptletNameNotCached(name) {
      if (!name) {
        return false;
      }
      return !!getScriptletByName(name, scriptletObjects);
    };

    /**
     * Cache for better performance of scriptlet name validation.
     */
    var scriptletNameValidationCache = new Map();

    /**
     * Checks whether the `name` is valid scriptlet name.
     * Uses cache for better performance.
     *
     * @param name Scriptlet name.
     * @returns True if scriptlet name is a valid one or an empty string,
     * otherwise false.
     */
    var isValidScriptletName = function isValidScriptletName(name) {
      // empty name is used for allowlist scriptlets. e.g.
      // - '#@%#//scriptlet()'
      if (name === '') {
        return true;
      }
      if (!name) {
        return false;
      }
      // if there is no cached validation value
      if (!scriptletNameValidationCache.has(name)) {
        // we should calculate it first
        var isValid = isValidScriptletNameNotCached(name);
        // and save it to the cache then
        scriptletNameValidationCache.set(name, isValid);
        return isValid;
      }
      // otherwise return cached validation result
      return scriptletNameValidationCache.get(name);
    };

    /* ************************************************************************
     *
     * Redirects
     *
     ************************************************************************** */

    /**
     * Redirect resource object, used for extracting redirect resources from the rule.
     */
    /**
     * List of modifiers that can be used for redirects.
     */
    var POSSIBLE_REDIRECT_MODIFIERS = new Set(['redirect', 'redirect-rule', 'rewrite']);

    /**
     * Extracts redirect resources from the `rule`.
     *
     * @param rule Rule text
     * @returns Array of redirect resources
     */
    var getRedirectResourcesFromRule = function getRedirectResourcesFromRule(rule) {
      var result = [];
      try {
        var ruleNode = getRuleNode(rule);
        if (ruleNode.category !== RuleCategory.Network) {
          return result;
        }
        if (ruleNode.type !== NetworkRuleType.NetworkRule) {
          return result;
        }
        var ruleModifiers = ruleNode.modifiers;
        if (!ruleModifiers) {
          return result;
        }
        var _iterator = _createForOfIteratorHelper(ruleModifiers.children),
          _step;
        try {
          for (_iterator.s(); !(_step = _iterator.n()).done;) {
            var el = _step.value;
            // Ignore exception modifiers
            if (el.exception) {
              continue;
            }
            if (POSSIBLE_REDIRECT_MODIFIERS.has(el.name.value)) {
              var _el$value;
              result.push({
                modifier: el.name.value,
                resource: (_el$value = el.value) === null || _el$value === void 0 ? void 0 : _el$value.value,
                exceptionRule: ruleNode.exception
              });
            }
          }
        } catch (err) {
          _iterator.e(err);
        } finally {
          _iterator.f();
        }
        return result;
      } catch (e) {
        return result;
      }
    };

    /**
     * Checks if the `rule` is AdGuard redirect rule.
     * Discards comments and JS rules and checks if the `rule` has 'redirect' modifier.
     *
     * @param rule - rule text
     * @returns true if given rule is adg redirect
     */
    var isAdgRedirectRule = function isAdgRedirectRule(rule) {
      var resources = getRedirectResourcesFromRule(rule);
      if (!resources.length || resources.length > 1) {
        return false;
      }
      var _resources = _slicedToArray$1(resources, 1),
        resource = _resources[0];
      return modifiersCompatibilityTable.exists(resource.modifier, GenericPlatform.AdgAny);
    };

    /**
     * Checks if the specified redirect resource is compatible with AdGuard
     *
     * @param redirectName - Redirect resource name to check
     * @returns - true if the redirect resource is compatible with AdGuard
     */
    var isRedirectResourceCompatibleWithAdg = function isRedirectResourceCompatibleWithAdg(redirectName) {
      return redirectsCompatibilityTable.exists(redirectName, GenericPlatform.AdgAny);
    };

    /**
     * Checks if the `rule` is **valid** AdGuard redirect resource rule
     *
     * @param rule - rule text
     * @returns true if given rule is valid adg redirect
     */
    var isValidAdgRedirectRule = function isValidAdgRedirectRule(rule) {
      var resources = getRedirectResourcesFromRule(rule);
      if (!resources.length || resources.length > 1) {
        return false;
      }
      var _resources2 = _slicedToArray$1(resources, 1),
        resource = _resources2[0];
      if (!resource.resource) {
        return resource.exceptionRule;
      }
      return modifiersCompatibilityTable.exists(resource.modifier, GenericPlatform.AdgAny) && isRedirectResourceCompatibleWithAdg(resource.resource);
    };

    /**
     * Checks if the redirect resource from the `rule` is compatible with the specified platform (`from`)
     * and has a compatible pair for the target platform (`to`)
     *
     * @param rule - rule text
     * @param from - platform to convert from
     * @param to - platform to convert to
     * @returns true if the rule is compatible with the specified platform
     */
    var checkCompatibility = function checkCompatibility(rule, from, to) {
      var resources = getRedirectResourcesFromRule(rule);
      if (!resources.length || resources.length > 1) {
        return false;
      }
      var _resources3 = _slicedToArray$1(resources, 1),
        resource = _resources3[0];
      if (!resource.resource) {
        return resource.exceptionRule;
      }

      // Redirect should exist for the source platform
      if (!redirectsCompatibilityTable.exists(resource.resource, from)) {
        return false;
      }

      // Redirect should have a compatible pair for the target platform (maybe in a different name)
      return !!redirectsCompatibilityTable.getFirst(resource.resource, to);
    };

    /**
     * Checks if the AdGuard redirect `rule` has Ubo analog. Needed for Adg->Ubo conversion
     *
     * @param rule - AdGuard rule text
     * @returns - true if the rule can be converted to Ubo
     */
    var isAdgRedirectCompatibleWithUbo = function isAdgRedirectCompatibleWithUbo(rule) {
      return checkCompatibility(rule, GenericPlatform.AdgAny, GenericPlatform.UboAny);
    };

    /**
     * Checks if the Ubo redirect `rule` has AdGuard analog. Needed for Ubo->Adg conversion
     *
     * @param rule - Ubo rule text
     * @returns - true if the rule can be converted to AdGuard
     */
    var isUboRedirectCompatibleWithAdg = function isUboRedirectCompatibleWithAdg(rule) {
      return checkCompatibility(rule, GenericPlatform.UboAny, GenericPlatform.AdgAny);
    };

    /**
     * Checks if the Abp redirect `rule` has AdGuard analog. Needed for Abp->Adg conversion
     *
     * @param rule - Abp rule text
     * @returns - true if the rule can be converted to AdGuard
     */
    var isAbpRedirectCompatibleWithAdg = function isAbpRedirectCompatibleWithAdg(rule) {
      return checkCompatibility(rule, GenericPlatform.AbpAny, GenericPlatform.AdgAny);
    };
    var validator = {
      isAdgScriptletRule,
      isUboScriptletRule,
      isAbpSnippetRule,
      getScriptletByName,
      isValidScriptletName,
      isAdgRedirectRule,
      isValidAdgRedirectRule,
      isRedirectResourceCompatibleWithAdg,
      isAdgRedirectCompatibleWithUbo,
      isUboRedirectCompatibleWithAdg,
      isAbpRedirectCompatibleWithAdg
    };

    /**
     * Helper type to get methods of RuleConverter that are not excluded
     *
     * @template ExcludedMethods Methods to exclude
     */

    /**
     * Conversion method type
     */

    /**
     * Checks if an array of rules is an array of scriptlet rules
     *
     * @param rules Array of rules
     * @returns True if all rules are scriptlet rules
     */
    var isArrayOfScriptletRules = function isArrayOfScriptletRules(rules) {
      return rules.every(function (rule) {
        return rule.category === RuleCategory.Cosmetic && rule.type === CosmeticRuleType.ScriptletInjectionRule;
      });
    };

    /**
     * Helper function to convert a scriptlet rule to a specific syntax
     *
     * @param rule Scriptlet rule
     * @param method Method to convert the rule
     *
     * @throws If the rule is in string format and cannot be parsed
     */
    var convertScriptletTo = function convertScriptletTo(rule, method) {
      var ruleNode = getRuleNode(rule);
      if (ruleNode.category !== RuleCategory.Cosmetic || ruleNode.type !== CosmeticRuleType.ScriptletInjectionRule) {
        return [getRuleText(ruleNode)];
      }
      var conversionResult = method(ruleNode);
      if (!conversionResult.isConverted) {
        return [getRuleText(ruleNode)];
      }
      return conversionResult.result.map(getRuleText);
    };

    /**
     * Converts string of UBO scriptlet rule to AdGuard scriptlet rule
     *
     * @param rule UBO scriptlet rule
     * @returns array with one AdGuard scriptlet rule
     *
     * @deprecated
     */
    var convertUboScriptletToAdg = function convertUboScriptletToAdg(rule) {
      return convertScriptletTo(rule, RuleConverter.convertToAdg);
    };

    /**
     * Convert string of ABP snippet rule to AdGuard scriptlet rule
     *
     * @param rule ABP snippet rule
     * @returns array of AdGuard scriptlet rules, one or few items depends on Abp-rule
     */
    var convertAbpSnippetToAdg = function convertAbpSnippetToAdg(rule) {
      return convertScriptletTo(rule, RuleConverter.convertToAdg);
    };

    /**
     * Converts any scriptlet rule into AdGuard syntax rule.
     * Comments and non-scriptlet rules are returned without changes.
     *
     * @param rule Rule.
     *
     * @returns Array of AdGuard scriptlet rules: one array item for ADG and UBO or few items for ABP.
     * For the ADG `rule` validates its syntax, and returns an empty array if it is invalid.
     */
    var convertScriptletToAdg = function convertScriptletToAdg(rule) {
      try {
        return convertScriptletTo(rule, RuleConverter.convertToAdg);
      } catch (e) {
        return [];
      }
    };

    /**
     * Converts AdGuard scriptlet rule to UBO syntax.
     *
     * @param rule AdGuard scriptlet rule
     * @returns UBO scriptlet rule
     * or undefined if `rule` is not valid AdGuard scriptlet rule.
     */
    var convertAdgScriptletToUbo = function convertAdgScriptletToUbo(rule) {
      try {
        return convertScriptletTo(rule, RuleConverter.convertToUbo)[0];
      } catch (e) {
        return undefined;
      }
    };

    /**
     * 1. For ADG scriptlet checks whether the scriptlet syntax and name are valid.
     * 2. For UBO and ABP scriptlet first checks their compatibility with ADG
     * by converting them into ADG syntax, and after that checks the name.
     *
     * ADG or UBO rules are "single-scriptlet", but ABP rule may contain more than one snippet
     * so if at least one of them is not valid — whole `ruleText` rule is not valid too.
     *
     * @param rule Any scriptlet rule — ADG or UBO or ABP.
     *
     * @returns True if scriptlet name is valid in rule.
     */
    var isValidScriptletRule = function isValidScriptletRule(rule) {
      var ruleNodes;
      try {
        ruleNodes = RuleConverter.convertToAdg(getRuleNode(rule)).result;
      } catch (e) {
        return false;
      }
      if (!isArrayOfScriptletRules(ruleNodes)) {
        return false;
      }

      // checking if each of parsed scriptlets is valid
      // if at least one of them is not valid - whole `ruleText` is not valid too
      var isValid = ruleNodes.every(function (ruleNode) {
        var _ruleNode$body$childr, _ruleNode$body$childr2;
        var name = (_ruleNode$body$childr = ruleNode.body.children[0]) === null || _ruleNode$body$childr === void 0 ? void 0 : (_ruleNode$body$childr2 = _ruleNode$body$childr.children[0]) === null || _ruleNode$body$childr2 === void 0 ? void 0 : _ruleNode$body$childr2.value;
        if (!name) {
          return ruleNode.exception;
        }
        var unquotedName = QuoteUtils.removeQuotes(name);
        if (!unquotedName) {
          return false;
        }
        return validator.isValidScriptletName(unquotedName);
      });
      return isValid;
    };

    /**
     * Converts Ubo redirect rule to Adg one
     *
     * @param rule ubo redirect rule
     * @returns  converted adg rule
     */
    var convertUboRedirectToAdg = function convertUboRedirectToAdg(rule) {
      return RuleConverter.convertToAdg(getRuleNode(rule)).result.map(getRuleText)[0];
    };

    /**
     * Converts Abp redirect rule to Adg one
     *
     * @param rule abp redirect rule
     * @returns converted adg rule
     */
    var convertAbpRedirectToAdg = function convertAbpRedirectToAdg(rule) {
      var node = getRuleNode(rule);
      if (node.category !== RuleCategory.Network) {
        return rule;
      }
      var conversionResult = RuleConverter.convertToAdg(node);
      return getRuleText(conversionResult.result[0]);
    };

    /**
     * Converts redirect rule to AdGuard one
     *
     * @param {string} rule redirect rule
     * @returns converted adg rule
     */
    var convertRedirectToAdg = function convertRedirectToAdg(rule) {
      var node = getRuleNode(rule);
      if (node.category !== RuleCategory.Network) {
        return;
      }

      // convert to ADG
      var conversionResult = RuleConverter.convertToAdg(node);

      // eslint-disable-next-line consistent-return
      return getRuleText(conversionResult.result[0]);
    };

    /**
     * Converts Adg redirect rule to Ubo one
     * 1. Checks if there is Ubo analog for Adg rule
     * 2. Parses the rule and checks if there are any source type modifiers which are required by Ubo
     *    and if there are no one we add it manually to the end.
     *    Source types are chosen according to redirect name
     *    e.g. ||ad.com^$redirect=<name>,important  ->>  ||ad.com^$redirect=<name>,important,script
     * 3. Replaces Adg redirect name by Ubo analog
     *
     * Note: if adg redirect uses UBO's priority syntax, it will be lost on conversion, e.g:
     * ||example.com$redirect=noopjs:99 => ||example.com$redirect=noop.js
     *
     * @param rule adg rule
     * @returns converted ubo rule
     * @throws on incompatible rule
     */
    var convertAdgRedirectToUbo = function convertAdgRedirectToUbo(rule) {
      var node = getRuleNode(rule);
      if (node.category !== RuleCategory.Network) {
        throw new Error('Rule is not a network rule');
      }

      // convert to UBO
      var conversionResult = RuleConverter.convertToUbo(node);
      return getRuleText(conversionResult.result[0]);
    };

    /**
     * Converts a redirect name to ADG compatible one, if possible
     *
     * @param name Redirect name to convert
     * @returns Converted ADG compatible redirect name or `undefined` if the redirect isn't supported
     */
    var convertRedirectNameToAdg = function convertRedirectNameToAdg(name) {
      var _redirectsCompatibili;
      return (_redirectsCompatibili = redirectsCompatibilityTable.getFirst(name, GenericPlatform.AdgAny)) === null || _redirectsCompatibili === void 0 ? void 0 : _redirectsCompatibili.name;
    };

    /**
     * @redirect prevent-bab
     *
     * @description
     * Prevents BlockAdblock script from detecting an ad blocker.
     *
     * Mostly it is used as `scriptlet`.
     * See [scriptlet description](../wiki/about-scriptlets.md#prevent-bab).
     *
     * Related UBO redirect resource:
     * https://github.com/gorhill/uBlock/blob/master/src/web_accessible_resources/nobab.js
     *
     * ### Examples
     *
     * ```adblock
     * /blockadblock.$script,redirect=prevent-bab
     * ```
     *
     * @added v1.3.19.
     */
    var preventBab$1 = preventBab$2;
    preventBab$1.names = ['prevent-bab',
    // list of prevent-bab redirect aliases
    'nobab.js', 'ubo-nobab.js', 'bab-defuser.js', 'ubo-bab-defuser.js', 'ubo-nobab', 'ubo-bab-defuser'];

    /**
     * @redirect ati-smarttag
     *
     * @description
     * Mocks AT Internat SmartTag.
     * https://developers.atinternet-solutions.com/as2-tagging-en/javascript-en/getting-started-javascript-en/tracker-initialisation-javascript-en/
     *
     * ### Examples
     *
     * ```adblock
     * ||example.com/assets/scripts/smarttag.js$script,redirect=ati-smarttag
     * ```
     *
     * @added v1.5.0.
     */
    function ATInternetSmartTag(source) {
      var setNoopFuncWrapper = {
        set: noopFunc
      };
      var sendNoopFuncWrapper = {
        send: noopFunc
      };
      var ecommerceWrapper = {
        displayCart: {
          products: setNoopFuncWrapper,
          cart: setNoopFuncWrapper
        },
        updateCart: {
          cart: setNoopFuncWrapper
        },
        displayProduct: {
          products: setNoopFuncWrapper
        },
        displayPageProduct: {
          products: setNoopFuncWrapper
        },
        addProduct: {
          products: setNoopFuncWrapper
        },
        removeProduct: {
          products: setNoopFuncWrapper
        }
      };

      // eslint-disable-next-line new-cap, func-names
      var tag = function tag() {};
      tag.prototype = {
        setConfig: noopFunc,
        setParam: noopFunc,
        dispatch: noopFunc,
        customVars: setNoopFuncWrapper,
        publisher: setNoopFuncWrapper,
        order: setNoopFuncWrapper,
        click: sendNoopFuncWrapper,
        clickListener: sendNoopFuncWrapper,
        internalSearch: {
          set: noopFunc,
          send: noopFunc
        },
        ecommerce: ecommerceWrapper,
        identifiedVisitor: {
          unset: noopFunc
        },
        page: {
          set: noopFunc,
          send: noopFunc
        },
        selfPromotion: {
          add: noopFunc,
          send: noopFunc
        },
        privacy: {
          setVisitorMode: noopFunc,
          getVisitorMode: noopFunc,
          hit: noopFunc
        },
        richMedia: {
          add: noopFunc,
          send: noopFunc,
          remove: noopFunc,
          removeAll: noopFunc
        }
      };
      var smartTagWrapper = {
        Tracker: {
          Tag: tag
        }
      };
      window.ATInternet = smartTagWrapper;
      hit(source);
    }
    ATInternetSmartTag.names = ['ati-smarttag'];
    ATInternetSmartTag.injections = [hit, noopFunc];

    /* eslint-disable consistent-return, no-eval */

    /**
     * @redirect prevent-bab2
     *
     * @description
     * Prevents BlockAdblock script from detecting an ad blocker.
     *
     * Related UBO redirect:
     * https://github.com/gorhill/uBlock/blob/master/src/web_accessible_resources/nobab2.js
     *
     * See [redirect description](../wiki/about-redirects.md#prevent-bab2).
     *
     * ### Examples
     *
     * ```adblock
     * /blockadblock.$script,redirect=prevent-bab2
     * ```
     *
     * @added v1.5.0.
     */
    function preventBab2(source) {
      var script = document.currentScript;
      if (script === null) {
        return;
      }
      var url = script.src;
      if (typeof url !== 'string') {
        return;
      }
      var domainsStr = ['adclixx\\.net', 'adnetasia\\.com', 'adtrackers\\.net', 'bannertrack\\.net'].join('|');
      var matchStr = "^https?://[\\w-]+\\.(".concat(domainsStr, ")/.");
      var domainsRegex = new RegExp(matchStr);
      if (domainsRegex.test(url) === false) {
        return;
      }
      window.nH7eXzOsG = 858;
      hit(source);
    }
    preventBab2.names = ['prevent-bab2',
    // aliases are needed for matching the related scriptlet converted into our syntax
    'nobab2.js'];
    preventBab2.injections = [hit];

    /* eslint-disable func-names */

    /**
     * @redirect prebid-ads
     *
     * @description
     * Sets predefined constants on a page:
     *
     * - `canRunAds`: `true`
     * - `isAdBlockActive`: `false`
     *
     * ### Examples
     *
     * ```adblock
     * ||example.org/assets/js/prebid-ads.js$script,redirect=prebid-ads
     * ```
     *
     * @added v1.6.2.
     */
    function prebidAds(source) {
      window.canRunAds = true;
      window.isAdBlockActive = false;
      hit(source);
    }
    prebidAds.names = ['prebid-ads', 'ubo-prebid-ads.js', 'prebid-ads.js'];
    prebidAds.injections = [hit];

    var redirectsList = /*#__PURE__*/Object.freeze({
        __proto__: null,
        ATInternetSmartTag: ATInternetSmartTag,
        AmazonApstag: AmazonApstag$1,
        DidomiLoader: DidomiLoader$1,
        Fingerprintjs2: Fingerprintjs2$1,
        Fingerprintjs3: Fingerprintjs3$1,
        Gemius: Gemius$1,
        GoogleAnalytics: GoogleAnalytics$1,
        GoogleAnalyticsGa: GoogleAnalyticsGa$1,
        GoogleIma3: GoogleIma3$1,
        GoogleSyndicationAdsByGoogle: GoogleSyndicationAdsByGoogle$1,
        GoogleTagServicesGpt: GoogleTagServicesGpt$1,
        Matomo: Matomo$1,
        NaverWcslog: NaverWcslog$1,
        Pardot: Pardot$1,
        Prebid: Prebid$1,
        ScoreCardResearchBeacon: ScoreCardResearchBeacon$1,
        metrikaYandexTag: metrikaYandexTag$1,
        metrikaYandexWatch: metrikaYandexWatch$1,
        noeval: noeval$1,
        prebidAds: prebidAds,
        preventBab: preventBab$1,
        preventBab2: preventBab2,
        preventFab: preventFab$1,
        preventPopadsNet: preventPopadsNet$1,
        setPopadsDummy: setPopadsDummy$1
    });

    var jsYaml$2 = {};

    var loader$1 = {};

    var common$6 = {};

    function isNothing(subject) {
      return typeof subject === 'undefined' || subject === null;
    }
    function isObject(subject) {
      return typeof subject === 'object' && subject !== null;
    }
    function toArray(sequence) {
      if (Array.isArray(sequence)) return sequence;else if (isNothing(sequence)) return [];
      return [sequence];
    }
    function extend(target, source) {
      var index, length, key, sourceKeys;
      if (source) {
        sourceKeys = Object.keys(source);
        for (index = 0, length = sourceKeys.length; index < length; index += 1) {
          key = sourceKeys[index];
          target[key] = source[key];
        }
      }
      return target;
    }
    function repeat(string, count) {
      var result = '',
        cycle;
      for (cycle = 0; cycle < count; cycle += 1) {
        result += string;
      }
      return result;
    }
    function isNegativeZero(number) {
      return number === 0 && Number.NEGATIVE_INFINITY === 1 / number;
    }
    common$6.isNothing = isNothing;
    common$6.isObject = isObject;
    common$6.toArray = toArray;
    common$6.repeat = repeat;
    common$6.isNegativeZero = isNegativeZero;
    common$6.extend = extend;

    function YAMLException$4(reason, mark) {
      // Super constructor
      Error.call(this);
      this.name = 'YAMLException';
      this.reason = reason;
      this.mark = mark;
      this.message = (this.reason || '(unknown reason)') + (this.mark ? ' ' + this.mark.toString() : '');

      // Include stack trace in error object
      if (Error.captureStackTrace) {
        // Chrome and NodeJS
        Error.captureStackTrace(this, this.constructor);
      } else {
        // FF, IE 10+ and Safari 6+. Fallback for others
        this.stack = new Error().stack || '';
      }
    }

    // Inherit from Error
    YAMLException$4.prototype = Object.create(Error.prototype);
    YAMLException$4.prototype.constructor = YAMLException$4;
    YAMLException$4.prototype.toString = function toString(compact) {
      var result = this.name + ': ';
      result += this.reason || '(unknown reason)';
      if (!compact && this.mark) {
        result += ' ' + this.mark.toString();
      }
      return result;
    };
    var exception = YAMLException$4;

    var common$5 = common$6;
    function Mark$1(name, buffer, position, line, column) {
      this.name = name;
      this.buffer = buffer;
      this.position = position;
      this.line = line;
      this.column = column;
    }
    Mark$1.prototype.getSnippet = function getSnippet(indent, maxLength) {
      var head, start, tail, end, snippet;
      if (!this.buffer) return null;
      indent = indent || 4;
      maxLength = maxLength || 75;
      head = '';
      start = this.position;
      while (start > 0 && "\0\r\n\x85\u2028\u2029".indexOf(this.buffer.charAt(start - 1)) === -1) {
        start -= 1;
        if (this.position - start > maxLength / 2 - 1) {
          head = ' ... ';
          start += 5;
          break;
        }
      }
      tail = '';
      end = this.position;
      while (end < this.buffer.length && "\0\r\n\x85\u2028\u2029".indexOf(this.buffer.charAt(end)) === -1) {
        end += 1;
        if (end - this.position > maxLength / 2 - 1) {
          tail = ' ... ';
          end -= 5;
          break;
        }
      }
      snippet = this.buffer.slice(start, end);
      return common$5.repeat(' ', indent) + head + snippet + tail + '\n' + common$5.repeat(' ', indent + this.position - start + head.length) + '^';
    };
    Mark$1.prototype.toString = function toString(compact) {
      var snippet,
        where = '';
      if (this.name) {
        where += 'in "' + this.name + '" ';
      }
      where += 'at line ' + (this.line + 1) + ', column ' + (this.column + 1);
      if (!compact) {
        snippet = this.getSnippet();
        if (snippet) {
          where += ':\n' + snippet;
        }
      }
      return where;
    };
    var mark = Mark$1;

    var YAMLException$3 = exception;
    var TYPE_CONSTRUCTOR_OPTIONS = ['kind', 'resolve', 'construct', 'instanceOf', 'predicate', 'represent', 'defaultStyle', 'styleAliases'];
    var YAML_NODE_KINDS = ['scalar', 'sequence', 'mapping'];
    function compileStyleAliases(map) {
      var result = {};
      if (map !== null) {
        Object.keys(map).forEach(function (style) {
          map[style].forEach(function (alias) {
            result[String(alias)] = style;
          });
        });
      }
      return result;
    }
    function Type$h(tag, options) {
      options = options || {};
      Object.keys(options).forEach(function (name) {
        if (TYPE_CONSTRUCTOR_OPTIONS.indexOf(name) === -1) {
          throw new YAMLException$3('Unknown option "' + name + '" is met in definition of "' + tag + '" YAML type.');
        }
      });

      // TODO: Add tag format check.
      this.tag = tag;
      this.kind = options['kind'] || null;
      this.resolve = options['resolve'] || function () {
        return true;
      };
      this.construct = options['construct'] || function (data) {
        return data;
      };
      this.instanceOf = options['instanceOf'] || null;
      this.predicate = options['predicate'] || null;
      this.represent = options['represent'] || null;
      this.defaultStyle = options['defaultStyle'] || null;
      this.styleAliases = compileStyleAliases(options['styleAliases'] || null);
      if (YAML_NODE_KINDS.indexOf(this.kind) === -1) {
        throw new YAMLException$3('Unknown kind "' + this.kind + '" is specified for "' + tag + '" YAML type.');
      }
    }
    var type = Type$h;

    /*eslint-disable max-len*/

    var common$4 = common$6;
    var YAMLException$2 = exception;
    var Type$g = type;
    function compileList(schema, name, result) {
      var exclude = [];
      schema.include.forEach(function (includedSchema) {
        result = compileList(includedSchema, name, result);
      });
      schema[name].forEach(function (currentType) {
        result.forEach(function (previousType, previousIndex) {
          if (previousType.tag === currentType.tag && previousType.kind === currentType.kind) {
            exclude.push(previousIndex);
          }
        });
        result.push(currentType);
      });
      return result.filter(function (type, index) {
        return exclude.indexOf(index) === -1;
      });
    }
    function compileMap( /* lists... */
    ) {
      var result = {
          scalar: {},
          sequence: {},
          mapping: {},
          fallback: {}
        },
        index,
        length;
      function collectType(type) {
        result[type.kind][type.tag] = result['fallback'][type.tag] = type;
      }
      for (index = 0, length = arguments.length; index < length; index += 1) {
        arguments[index].forEach(collectType);
      }
      return result;
    }
    function Schema$5(definition) {
      this.include = definition.include || [];
      this.implicit = definition.implicit || [];
      this.explicit = definition.explicit || [];
      this.implicit.forEach(function (type) {
        if (type.loadKind && type.loadKind !== 'scalar') {
          throw new YAMLException$2('There is a non-scalar type in the implicit list of a schema. Implicit resolving of such types is not supported.');
        }
      });
      this.compiledImplicit = compileList(this, 'implicit', []);
      this.compiledExplicit = compileList(this, 'explicit', []);
      this.compiledTypeMap = compileMap(this.compiledImplicit, this.compiledExplicit);
    }
    Schema$5.DEFAULT = null;
    Schema$5.create = function createSchema() {
      var schemas, types;
      switch (arguments.length) {
        case 1:
          schemas = Schema$5.DEFAULT;
          types = arguments[0];
          break;
        case 2:
          schemas = arguments[0];
          types = arguments[1];
          break;
        default:
          throw new YAMLException$2('Wrong number of arguments for Schema.create function');
      }
      schemas = common$4.toArray(schemas);
      types = common$4.toArray(types);
      if (!schemas.every(function (schema) {
        return schema instanceof Schema$5;
      })) {
        throw new YAMLException$2('Specified list of super schemas (or a single Schema object) contains a non-Schema object.');
      }
      if (!types.every(function (type) {
        return type instanceof Type$g;
      })) {
        throw new YAMLException$2('Specified list of YAML types (or a single Type object) contains a non-Type object.');
      }
      return new Schema$5({
        include: schemas,
        explicit: types
      });
    };
    var schema = Schema$5;

    var Type$f = type;
    var str = new Type$f('tag:yaml.org,2002:str', {
      kind: 'scalar',
      construct: function construct(data) {
        return data !== null ? data : '';
      }
    });

    var Type$e = type;
    var seq = new Type$e('tag:yaml.org,2002:seq', {
      kind: 'sequence',
      construct: function construct(data) {
        return data !== null ? data : [];
      }
    });

    var Type$d = type;
    var map = new Type$d('tag:yaml.org,2002:map', {
      kind: 'mapping',
      construct: function construct(data) {
        return data !== null ? data : {};
      }
    });

    var Schema$4 = schema;
    var failsafe = new Schema$4({
      explicit: [str, seq, map]
    });

    var Type$c = type;
    function resolveYamlNull(data) {
      if (data === null) return true;
      var max = data.length;
      return max === 1 && data === '~' || max === 4 && (data === 'null' || data === 'Null' || data === 'NULL');
    }
    function constructYamlNull() {
      return null;
    }
    function isNull(object) {
      return object === null;
    }
    var _null = new Type$c('tag:yaml.org,2002:null', {
      kind: 'scalar',
      resolve: resolveYamlNull,
      construct: constructYamlNull,
      predicate: isNull,
      represent: {
        canonical: function canonical() {
          return '~';
        },
        lowercase: function lowercase() {
          return 'null';
        },
        uppercase: function uppercase() {
          return 'NULL';
        },
        camelcase: function camelcase() {
          return 'Null';
        }
      },
      defaultStyle: 'lowercase'
    });

    var Type$b = type;
    function resolveYamlBoolean(data) {
      if (data === null) return false;
      var max = data.length;
      return max === 4 && (data === 'true' || data === 'True' || data === 'TRUE') || max === 5 && (data === 'false' || data === 'False' || data === 'FALSE');
    }
    function constructYamlBoolean(data) {
      return data === 'true' || data === 'True' || data === 'TRUE';
    }
    function isBoolean(object) {
      return Object.prototype.toString.call(object) === '[object Boolean]';
    }
    var bool = new Type$b('tag:yaml.org,2002:bool', {
      kind: 'scalar',
      resolve: resolveYamlBoolean,
      construct: constructYamlBoolean,
      predicate: isBoolean,
      represent: {
        lowercase: function lowercase(object) {
          return object ? 'true' : 'false';
        },
        uppercase: function uppercase(object) {
          return object ? 'TRUE' : 'FALSE';
        },
        camelcase: function camelcase(object) {
          return object ? 'True' : 'False';
        }
      },
      defaultStyle: 'lowercase'
    });

    var common$3 = common$6;
    var Type$a = type;
    function isHexCode(c) {
      return 0x30 /* 0 */ <= c && c <= 0x39 /* 9 */ || 0x41 /* A */ <= c && c <= 0x46 /* F */ || 0x61 /* a */ <= c && c <= 0x66 /* f */;
    }

    function isOctCode(c) {
      return 0x30 /* 0 */ <= c && c <= 0x37 /* 7 */;
    }

    function isDecCode(c) {
      return 0x30 /* 0 */ <= c && c <= 0x39 /* 9 */;
    }

    function resolveYamlInteger(data) {
      if (data === null) return false;
      var max = data.length,
        index = 0,
        hasDigits = false,
        ch;
      if (!max) return false;
      ch = data[index];

      // sign
      if (ch === '-' || ch === '+') {
        ch = data[++index];
      }
      if (ch === '0') {
        // 0
        if (index + 1 === max) return true;
        ch = data[++index];

        // base 2, base 8, base 16

        if (ch === 'b') {
          // base 2
          index++;
          for (; index < max; index++) {
            ch = data[index];
            if (ch === '_') continue;
            if (ch !== '0' && ch !== '1') return false;
            hasDigits = true;
          }
          return hasDigits && ch !== '_';
        }
        if (ch === 'x') {
          // base 16
          index++;
          for (; index < max; index++) {
            ch = data[index];
            if (ch === '_') continue;
            if (!isHexCode(data.charCodeAt(index))) return false;
            hasDigits = true;
          }
          return hasDigits && ch !== '_';
        }

        // base 8
        for (; index < max; index++) {
          ch = data[index];
          if (ch === '_') continue;
          if (!isOctCode(data.charCodeAt(index))) return false;
          hasDigits = true;
        }
        return hasDigits && ch !== '_';
      }

      // base 10 (except 0) or base 60

      // value should not start with `_`;
      if (ch === '_') return false;
      for (; index < max; index++) {
        ch = data[index];
        if (ch === '_') continue;
        if (ch === ':') break;
        if (!isDecCode(data.charCodeAt(index))) {
          return false;
        }
        hasDigits = true;
      }

      // Should have digits and should not end with `_`
      if (!hasDigits || ch === '_') return false;

      // if !base60 - done;
      if (ch !== ':') return true;

      // base60 almost not used, no needs to optimize
      return /^(:[0-5]?[0-9])+$/.test(data.slice(index));
    }
    function constructYamlInteger(data) {
      var value = data,
        sign = 1,
        ch,
        base,
        digits = [];
      if (value.indexOf('_') !== -1) {
        value = value.replace(/_/g, '');
      }
      ch = value[0];
      if (ch === '-' || ch === '+') {
        if (ch === '-') sign = -1;
        value = value.slice(1);
        ch = value[0];
      }
      if (value === '0') return 0;
      if (ch === '0') {
        if (value[1] === 'b') return sign * parseInt(value.slice(2), 2);
        if (value[1] === 'x') return sign * parseInt(value, 16);
        return sign * parseInt(value, 8);
      }
      if (value.indexOf(':') !== -1) {
        value.split(':').forEach(function (v) {
          digits.unshift(parseInt(v, 10));
        });
        value = 0;
        base = 1;
        digits.forEach(function (d) {
          value += d * base;
          base *= 60;
        });
        return sign * value;
      }
      return sign * parseInt(value, 10);
    }
    function isInteger(object) {
      return Object.prototype.toString.call(object) === '[object Number]' && object % 1 === 0 && !common$3.isNegativeZero(object);
    }
    var int = new Type$a('tag:yaml.org,2002:int', {
      kind: 'scalar',
      resolve: resolveYamlInteger,
      construct: constructYamlInteger,
      predicate: isInteger,
      represent: {
        binary: function binary(obj) {
          return obj >= 0 ? '0b' + obj.toString(2) : '-0b' + obj.toString(2).slice(1);
        },
        octal: function octal(obj) {
          return obj >= 0 ? '0' + obj.toString(8) : '-0' + obj.toString(8).slice(1);
        },
        decimal: function decimal(obj) {
          return obj.toString(10);
        },
        /* eslint-disable max-len */
        hexadecimal: function hexadecimal(obj) {
          return obj >= 0 ? '0x' + obj.toString(16).toUpperCase() : '-0x' + obj.toString(16).toUpperCase().slice(1);
        }
      },
      defaultStyle: 'decimal',
      styleAliases: {
        binary: [2, 'bin'],
        octal: [8, 'oct'],
        decimal: [10, 'dec'],
        hexadecimal: [16, 'hex']
      }
    });

    var common$2 = common$6;
    var Type$9 = type;
    var YAML_FLOAT_PATTERN = new RegExp(
    // 2.5e4, 2.5 and integers
    '^(?:[-+]?(?:0|[1-9][0-9_]*)(?:\\.[0-9_]*)?(?:[eE][-+]?[0-9]+)?' +
    // .2e4, .2
    // special case, seems not from spec
    '|\\.[0-9_]+(?:[eE][-+]?[0-9]+)?' +
    // 20:59
    '|[-+]?[0-9][0-9_]*(?::[0-5]?[0-9])+\\.[0-9_]*' +
    // .inf
    '|[-+]?\\.(?:inf|Inf|INF)' +
    // .nan
    '|\\.(?:nan|NaN|NAN))$');
    function resolveYamlFloat(data) {
      if (data === null) return false;
      if (!YAML_FLOAT_PATTERN.test(data) ||
      // Quick hack to not allow integers end with `_`
      // Probably should update regexp & check speed
      data[data.length - 1] === '_') {
        return false;
      }
      return true;
    }
    function constructYamlFloat(data) {
      var value, sign, base, digits;
      value = data.replace(/_/g, '').toLowerCase();
      sign = value[0] === '-' ? -1 : 1;
      digits = [];
      if ('+-'.indexOf(value[0]) >= 0) {
        value = value.slice(1);
      }
      if (value === '.inf') {
        return sign === 1 ? Number.POSITIVE_INFINITY : Number.NEGATIVE_INFINITY;
      } else if (value === '.nan') {
        return NaN;
      } else if (value.indexOf(':') >= 0) {
        value.split(':').forEach(function (v) {
          digits.unshift(parseFloat(v, 10));
        });
        value = 0.0;
        base = 1;
        digits.forEach(function (d) {
          value += d * base;
          base *= 60;
        });
        return sign * value;
      }
      return sign * parseFloat(value, 10);
    }
    var SCIENTIFIC_WITHOUT_DOT = /^[-+]?[0-9]+e/;
    function representYamlFloat(object, style) {
      var res;
      if (isNaN(object)) {
        switch (style) {
          case 'lowercase':
            return '.nan';
          case 'uppercase':
            return '.NAN';
          case 'camelcase':
            return '.NaN';
        }
      } else if (Number.POSITIVE_INFINITY === object) {
        switch (style) {
          case 'lowercase':
            return '.inf';
          case 'uppercase':
            return '.INF';
          case 'camelcase':
            return '.Inf';
        }
      } else if (Number.NEGATIVE_INFINITY === object) {
        switch (style) {
          case 'lowercase':
            return '-.inf';
          case 'uppercase':
            return '-.INF';
          case 'camelcase':
            return '-.Inf';
        }
      } else if (common$2.isNegativeZero(object)) {
        return '-0.0';
      }
      res = object.toString(10);

      // JS stringifier can build scientific format without dots: 5e-100,
      // while YAML requres dot: 5.e-100. Fix it with simple hack

      return SCIENTIFIC_WITHOUT_DOT.test(res) ? res.replace('e', '.e') : res;
    }
    function isFloat(object) {
      return Object.prototype.toString.call(object) === '[object Number]' && (object % 1 !== 0 || common$2.isNegativeZero(object));
    }
    var float = new Type$9('tag:yaml.org,2002:float', {
      kind: 'scalar',
      resolve: resolveYamlFloat,
      construct: constructYamlFloat,
      predicate: isFloat,
      represent: representYamlFloat,
      defaultStyle: 'lowercase'
    });

    var Schema$3 = schema;
    var json = new Schema$3({
      include: [failsafe],
      implicit: [_null, bool, int, float]
    });

    var Schema$2 = schema;
    var core = new Schema$2({
      include: [json]
    });

    var Type$8 = type;
    var YAML_DATE_REGEXP = new RegExp('^([0-9][0-9][0-9][0-9])' +
    // [1] year
    '-([0-9][0-9])' +
    // [2] month
    '-([0-9][0-9])$'); // [3] day

    var YAML_TIMESTAMP_REGEXP = new RegExp('^([0-9][0-9][0-9][0-9])' +
    // [1] year
    '-([0-9][0-9]?)' +
    // [2] month
    '-([0-9][0-9]?)' +
    // [3] day
    '(?:[Tt]|[ \\t]+)' +
    // ...
    '([0-9][0-9]?)' +
    // [4] hour
    ':([0-9][0-9])' +
    // [5] minute
    ':([0-9][0-9])' +
    // [6] second
    '(?:\\.([0-9]*))?' +
    // [7] fraction
    '(?:[ \\t]*(Z|([-+])([0-9][0-9]?)' +
    // [8] tz [9] tz_sign [10] tz_hour
    '(?::([0-9][0-9]))?))?$'); // [11] tz_minute

    function resolveYamlTimestamp(data) {
      if (data === null) return false;
      if (YAML_DATE_REGEXP.exec(data) !== null) return true;
      if (YAML_TIMESTAMP_REGEXP.exec(data) !== null) return true;
      return false;
    }
    function constructYamlTimestamp(data) {
      var match,
        year,
        month,
        day,
        hour,
        minute,
        second,
        fraction = 0,
        delta = null,
        tz_hour,
        tz_minute,
        date;
      match = YAML_DATE_REGEXP.exec(data);
      if (match === null) match = YAML_TIMESTAMP_REGEXP.exec(data);
      if (match === null) throw new Error('Date resolve error');

      // match: [1] year [2] month [3] day

      year = +match[1];
      month = +match[2] - 1; // JS month starts with 0
      day = +match[3];
      if (!match[4]) {
        // no hour
        return new Date(Date.UTC(year, month, day));
      }

      // match: [4] hour [5] minute [6] second [7] fraction

      hour = +match[4];
      minute = +match[5];
      second = +match[6];
      if (match[7]) {
        fraction = match[7].slice(0, 3);
        while (fraction.length < 3) {
          // milli-seconds
          fraction += '0';
        }
        fraction = +fraction;
      }

      // match: [8] tz [9] tz_sign [10] tz_hour [11] tz_minute

      if (match[9]) {
        tz_hour = +match[10];
        tz_minute = +(match[11] || 0);
        delta = (tz_hour * 60 + tz_minute) * 60000; // delta in mili-seconds
        if (match[9] === '-') delta = -delta;
      }
      date = new Date(Date.UTC(year, month, day, hour, minute, second, fraction));
      if (delta) date.setTime(date.getTime() - delta);
      return date;
    }
    function representYamlTimestamp(object /*, style*/) {
      return object.toISOString();
    }
    var timestamp = new Type$8('tag:yaml.org,2002:timestamp', {
      kind: 'scalar',
      resolve: resolveYamlTimestamp,
      construct: constructYamlTimestamp,
      instanceOf: Date,
      represent: representYamlTimestamp
    });

    var Type$7 = type;
    function resolveYamlMerge(data) {
      return data === '<<' || data === null;
    }
    var merge = new Type$7('tag:yaml.org,2002:merge', {
      kind: 'scalar',
      resolve: resolveYamlMerge
    });

    function commonjsRequire(path) {
    	throw new Error('Could not dynamically require "' + path + '". Please configure the dynamicRequireTargets or/and ignoreDynamicRequires option of @rollup/plugin-commonjs appropriately for this require call to work.');
    }

    /*eslint-disable no-bitwise*/

    var NodeBuffer;
    try {
      // A trick for browserified version, to not include `Buffer` shim
      var _require$1 = commonjsRequire;
      NodeBuffer = _require$1('buffer').Buffer;
    } catch (__) {}
    var Type$6 = type;

    // [ 64, 65, 66 ] -> [ padding, CR, LF ]
    var BASE64_MAP = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=\n\r';
    function resolveYamlBinary(data) {
      if (data === null) return false;
      var code,
        idx,
        bitlen = 0,
        max = data.length,
        map = BASE64_MAP;

      // Convert one by one.
      for (idx = 0; idx < max; idx++) {
        code = map.indexOf(data.charAt(idx));

        // Skip CR/LF
        if (code > 64) continue;

        // Fail on illegal characters
        if (code < 0) return false;
        bitlen += 6;
      }

      // If there are any bits left, source was corrupted
      return bitlen % 8 === 0;
    }
    function constructYamlBinary(data) {
      var idx,
        tailbits,
        input = data.replace(/[\r\n=]/g, ''),
        // remove CR/LF & padding to simplify scan
        max = input.length,
        map = BASE64_MAP,
        bits = 0,
        result = [];

      // Collect by 6*4 bits (3 bytes)

      for (idx = 0; idx < max; idx++) {
        if (idx % 4 === 0 && idx) {
          result.push(bits >> 16 & 0xFF);
          result.push(bits >> 8 & 0xFF);
          result.push(bits & 0xFF);
        }
        bits = bits << 6 | map.indexOf(input.charAt(idx));
      }

      // Dump tail

      tailbits = max % 4 * 6;
      if (tailbits === 0) {
        result.push(bits >> 16 & 0xFF);
        result.push(bits >> 8 & 0xFF);
        result.push(bits & 0xFF);
      } else if (tailbits === 18) {
        result.push(bits >> 10 & 0xFF);
        result.push(bits >> 2 & 0xFF);
      } else if (tailbits === 12) {
        result.push(bits >> 4 & 0xFF);
      }

      // Wrap into Buffer for NodeJS and leave Array for browser
      if (NodeBuffer) {
        // Support node 6.+ Buffer API when available
        return NodeBuffer.from ? NodeBuffer.from(result) : new NodeBuffer(result);
      }
      return result;
    }
    function representYamlBinary(object /*, style*/) {
      var result = '',
        bits = 0,
        idx,
        tail,
        max = object.length,
        map = BASE64_MAP;

      // Convert every three bytes to 4 ASCII characters.

      for (idx = 0; idx < max; idx++) {
        if (idx % 3 === 0 && idx) {
          result += map[bits >> 18 & 0x3F];
          result += map[bits >> 12 & 0x3F];
          result += map[bits >> 6 & 0x3F];
          result += map[bits & 0x3F];
        }
        bits = (bits << 8) + object[idx];
      }

      // Dump tail

      tail = max % 3;
      if (tail === 0) {
        result += map[bits >> 18 & 0x3F];
        result += map[bits >> 12 & 0x3F];
        result += map[bits >> 6 & 0x3F];
        result += map[bits & 0x3F];
      } else if (tail === 2) {
        result += map[bits >> 10 & 0x3F];
        result += map[bits >> 4 & 0x3F];
        result += map[bits << 2 & 0x3F];
        result += map[64];
      } else if (tail === 1) {
        result += map[bits >> 2 & 0x3F];
        result += map[bits << 4 & 0x3F];
        result += map[64];
        result += map[64];
      }
      return result;
    }
    function isBinary(object) {
      return NodeBuffer && NodeBuffer.isBuffer(object);
    }
    var binary = new Type$6('tag:yaml.org,2002:binary', {
      kind: 'scalar',
      resolve: resolveYamlBinary,
      construct: constructYamlBinary,
      predicate: isBinary,
      represent: representYamlBinary
    });

    var Type$5 = type;
    var _hasOwnProperty$3 = Object.prototype.hasOwnProperty;
    var _toString$2 = Object.prototype.toString;
    function resolveYamlOmap(data) {
      if (data === null) return true;
      var objectKeys = [],
        index,
        length,
        pair,
        pairKey,
        pairHasKey,
        object = data;
      for (index = 0, length = object.length; index < length; index += 1) {
        pair = object[index];
        pairHasKey = false;
        if (_toString$2.call(pair) !== '[object Object]') return false;
        for (pairKey in pair) {
          if (_hasOwnProperty$3.call(pair, pairKey)) {
            if (!pairHasKey) pairHasKey = true;else return false;
          }
        }
        if (!pairHasKey) return false;
        if (objectKeys.indexOf(pairKey) === -1) objectKeys.push(pairKey);else return false;
      }
      return true;
    }
    function constructYamlOmap(data) {
      return data !== null ? data : [];
    }
    var omap = new Type$5('tag:yaml.org,2002:omap', {
      kind: 'sequence',
      resolve: resolveYamlOmap,
      construct: constructYamlOmap
    });

    var Type$4 = type;
    var _toString$1 = Object.prototype.toString;
    function resolveYamlPairs(data) {
      if (data === null) return true;
      var index,
        length,
        pair,
        keys,
        result,
        object = data;
      result = new Array(object.length);
      for (index = 0, length = object.length; index < length; index += 1) {
        pair = object[index];
        if (_toString$1.call(pair) !== '[object Object]') return false;
        keys = Object.keys(pair);
        if (keys.length !== 1) return false;
        result[index] = [keys[0], pair[keys[0]]];
      }
      return true;
    }
    function constructYamlPairs(data) {
      if (data === null) return [];
      var index,
        length,
        pair,
        keys,
        result,
        object = data;
      result = new Array(object.length);
      for (index = 0, length = object.length; index < length; index += 1) {
        pair = object[index];
        keys = Object.keys(pair);
        result[index] = [keys[0], pair[keys[0]]];
      }
      return result;
    }
    var pairs = new Type$4('tag:yaml.org,2002:pairs', {
      kind: 'sequence',
      resolve: resolveYamlPairs,
      construct: constructYamlPairs
    });

    var Type$3 = type;
    var _hasOwnProperty$2 = Object.prototype.hasOwnProperty;
    function resolveYamlSet(data) {
      if (data === null) return true;
      var key,
        object = data;
      for (key in object) {
        if (_hasOwnProperty$2.call(object, key)) {
          if (object[key] !== null) return false;
        }
      }
      return true;
    }
    function constructYamlSet(data) {
      return data !== null ? data : {};
    }
    var set = new Type$3('tag:yaml.org,2002:set', {
      kind: 'mapping',
      resolve: resolveYamlSet,
      construct: constructYamlSet
    });

    var Schema$1 = schema;
    var default_safe = new Schema$1({
      include: [core],
      implicit: [timestamp, merge],
      explicit: [binary, omap, pairs, set]
    });

    var Type$2 = type;
    function resolveJavascriptUndefined() {
      return true;
    }
    function constructJavascriptUndefined() {
      /*eslint-disable no-undefined*/
      return undefined;
    }
    function representJavascriptUndefined() {
      return '';
    }
    function isUndefined(object) {
      return typeof object === 'undefined';
    }
    var _undefined = new Type$2('tag:yaml.org,2002:js/undefined', {
      kind: 'scalar',
      resolve: resolveJavascriptUndefined,
      construct: constructJavascriptUndefined,
      predicate: isUndefined,
      represent: representJavascriptUndefined
    });

    var Type$1 = type;
    function resolveJavascriptRegExp(data) {
      if (data === null) return false;
      if (data.length === 0) return false;
      var regexp = data,
        tail = /\/([gim]*)$/.exec(data),
        modifiers = '';

      // if regexp starts with '/' it can have modifiers and must be properly closed
      // `/foo/gim` - modifiers tail can be maximum 3 chars
      if (regexp[0] === '/') {
        if (tail) modifiers = tail[1];
        if (modifiers.length > 3) return false;
        // if expression starts with /, is should be properly terminated
        if (regexp[regexp.length - modifiers.length - 1] !== '/') return false;
      }
      return true;
    }
    function constructJavascriptRegExp(data) {
      var regexp = data,
        tail = /\/([gim]*)$/.exec(data),
        modifiers = '';

      // `/foo/gim` - tail can be maximum 4 chars
      if (regexp[0] === '/') {
        if (tail) modifiers = tail[1];
        regexp = regexp.slice(1, regexp.length - modifiers.length - 1);
      }
      return new RegExp(regexp, modifiers);
    }
    function representJavascriptRegExp(object /*, style*/) {
      var result = '/' + object.source + '/';
      if (object.global) result += 'g';
      if (object.multiline) result += 'm';
      if (object.ignoreCase) result += 'i';
      return result;
    }
    function isRegExp(object) {
      return Object.prototype.toString.call(object) === '[object RegExp]';
    }
    var regexp = new Type$1('tag:yaml.org,2002:js/regexp', {
      kind: 'scalar',
      resolve: resolveJavascriptRegExp,
      construct: constructJavascriptRegExp,
      predicate: isRegExp,
      represent: representJavascriptRegExp
    });

    var esprima;

    // Browserified version does not have esprima
    //
    // 1. For node.js just require module as deps
    // 2. For browser try to require mudule via external AMD system.
    //    If not found - try to fallback to window.esprima. If not
    //    found too - then fail to parse.
    //
    try {
      // workaround to exclude package from browserify list.
      var _require = commonjsRequire;
      esprima = _require('esprima');
    } catch (_) {
      /* eslint-disable no-redeclare */
      /* global window */
      if (typeof window !== 'undefined') esprima = window.esprima;
    }
    var Type = type;
    function resolveJavascriptFunction(data) {
      if (data === null) return false;
      try {
        var source = '(' + data + ')',
          ast = esprima.parse(source, {
            range: true
          });
        if (ast.type !== 'Program' || ast.body.length !== 1 || ast.body[0].type !== 'ExpressionStatement' || ast.body[0].expression.type !== 'ArrowFunctionExpression' && ast.body[0].expression.type !== 'FunctionExpression') {
          return false;
        }
        return true;
      } catch (err) {
        return false;
      }
    }
    function constructJavascriptFunction(data) {
      /*jslint evil:true*/

      var source = '(' + data + ')',
        ast = esprima.parse(source, {
          range: true
        }),
        params = [],
        body;
      if (ast.type !== 'Program' || ast.body.length !== 1 || ast.body[0].type !== 'ExpressionStatement' || ast.body[0].expression.type !== 'ArrowFunctionExpression' && ast.body[0].expression.type !== 'FunctionExpression') {
        throw new Error('Failed to resolve function');
      }
      ast.body[0].expression.params.forEach(function (param) {
        params.push(param.name);
      });
      body = ast.body[0].expression.body.range;

      // Esprima's ranges include the first '{' and the last '}' characters on
      // function expressions. So cut them out.
      if (ast.body[0].expression.body.type === 'BlockStatement') {
        /*eslint-disable no-new-func*/
        return new Function(params, source.slice(body[0] + 1, body[1] - 1));
      }
      // ES6 arrow functions can omit the BlockStatement. In that case, just return
      // the body.
      /*eslint-disable no-new-func*/
      return new Function(params, 'return ' + source.slice(body[0], body[1]));
    }
    function representJavascriptFunction(object /*, style*/) {
      return object.toString();
    }
    function isFunction(object) {
      return Object.prototype.toString.call(object) === '[object Function]';
    }
    var _function = new Type('tag:yaml.org,2002:js/function', {
      kind: 'scalar',
      resolve: resolveJavascriptFunction,
      construct: constructJavascriptFunction,
      predicate: isFunction,
      represent: representJavascriptFunction
    });

    var Schema = schema;
    var default_full = Schema.DEFAULT = new Schema({
      include: [default_safe],
      explicit: [_undefined, regexp, _function]
    });

    /*eslint-disable max-len,no-use-before-define*/

    var common$1 = common$6;
    var YAMLException$1 = exception;
    var Mark = mark;
    var DEFAULT_SAFE_SCHEMA$1 = default_safe;
    var DEFAULT_FULL_SCHEMA$1 = default_full;
    var _hasOwnProperty$1 = Object.prototype.hasOwnProperty;
    var CONTEXT_FLOW_IN = 1;
    var CONTEXT_FLOW_OUT = 2;
    var CONTEXT_BLOCK_IN = 3;
    var CONTEXT_BLOCK_OUT = 4;
    var CHOMPING_CLIP = 1;
    var CHOMPING_STRIP = 2;
    var CHOMPING_KEEP = 3;
    var PATTERN_NON_PRINTABLE = /[\x00-\x08\x0B\x0C\x0E-\x1F\x7F-\x84\x86-\x9F\uFFFE\uFFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF]/;
    var PATTERN_NON_ASCII_LINE_BREAKS = /[\x85\u2028\u2029]/;
    var PATTERN_FLOW_INDICATORS = /[,\[\]\{\}]/;
    var PATTERN_TAG_HANDLE = /^(?:!|!!|![a-z\-]+!)$/i;
    var PATTERN_TAG_URI = /^(?:!|[^,\[\]\{\}])(?:%[0-9a-f]{2}|[0-9a-z\-#;\/\?:@&=\+\$,_\.!~\*'\(\)\[\]])*$/i;
    function _class(obj) {
      return Object.prototype.toString.call(obj);
    }
    function is_EOL(c) {
      return c === 0x0A /* LF */ || c === 0x0D /* CR */;
    }

    function is_WHITE_SPACE(c) {
      return c === 0x09 /* Tab */ || c === 0x20 /* Space */;
    }

    function is_WS_OR_EOL(c) {
      return c === 0x09 /* Tab */ || c === 0x20 /* Space */ || c === 0x0A /* LF */ || c === 0x0D /* CR */;
    }

    function is_FLOW_INDICATOR(c) {
      return c === 0x2C /* , */ || c === 0x5B /* [ */ || c === 0x5D /* ] */ || c === 0x7B /* { */ || c === 0x7D /* } */;
    }

    function fromHexCode(c) {
      var lc;
      if (0x30 /* 0 */ <= c && c <= 0x39 /* 9 */) {
        return c - 0x30;
      }

      /*eslint-disable no-bitwise*/
      lc = c | 0x20;
      if (0x61 /* a */ <= lc && lc <= 0x66 /* f */) {
        return lc - 0x61 + 10;
      }
      return -1;
    }
    function escapedHexLen(c) {
      if (c === 0x78 /* x */) {
        return 2;
      }
      if (c === 0x75 /* u */) {
        return 4;
      }
      if (c === 0x55 /* U */) {
        return 8;
      }
      return 0;
    }
    function fromDecimalCode(c) {
      if (0x30 /* 0 */ <= c && c <= 0x39 /* 9 */) {
        return c - 0x30;
      }
      return -1;
    }
    function simpleEscapeSequence(c) {
      /* eslint-disable indent */
      return c === 0x30 /* 0 */ ? '\x00' : c === 0x61 /* a */ ? '\x07' : c === 0x62 /* b */ ? '\x08' : c === 0x74 /* t */ ? '\x09' : c === 0x09 /* Tab */ ? '\x09' : c === 0x6E /* n */ ? '\x0A' : c === 0x76 /* v */ ? '\x0B' : c === 0x66 /* f */ ? '\x0C' : c === 0x72 /* r */ ? '\x0D' : c === 0x65 /* e */ ? '\x1B' : c === 0x20 /* Space */ ? ' ' : c === 0x22 /* " */ ? '\x22' : c === 0x2F /* / */ ? '/' : c === 0x5C /* \ */ ? '\x5C' : c === 0x4E /* N */ ? '\x85' : c === 0x5F /* _ */ ? '\xA0' : c === 0x4C /* L */ ? "\u2028" : c === 0x50 /* P */ ? "\u2029" : '';
    }
    function charFromCodepoint(c) {
      if (c <= 0xFFFF) {
        return String.fromCharCode(c);
      }
      // Encode UTF-16 surrogate pair
      // https://en.wikipedia.org/wiki/UTF-16#Code_points_U.2B010000_to_U.2B10FFFF
      return String.fromCharCode((c - 0x010000 >> 10) + 0xD800, (c - 0x010000 & 0x03FF) + 0xDC00);
    }
    var simpleEscapeCheck = new Array(256); // integer, for fast access
    var simpleEscapeMap = new Array(256);
    for (var i = 0; i < 256; i++) {
      simpleEscapeCheck[i] = simpleEscapeSequence(i) ? 1 : 0;
      simpleEscapeMap[i] = simpleEscapeSequence(i);
    }
    function State$1(input, options) {
      this.input = input;
      this.filename = options['filename'] || null;
      this.schema = options['schema'] || DEFAULT_FULL_SCHEMA$1;
      this.onWarning = options['onWarning'] || null;
      this.legacy = options['legacy'] || false;
      this.json = options['json'] || false;
      this.listener = options['listener'] || null;
      this.implicitTypes = this.schema.compiledImplicit;
      this.typeMap = this.schema.compiledTypeMap;
      this.length = input.length;
      this.position = 0;
      this.line = 0;
      this.lineStart = 0;
      this.lineIndent = 0;
      this.documents = [];

      /*
      this.version;
      this.checkLineBreaks;
      this.tagMap;
      this.anchorMap;
      this.tag;
      this.anchor;
      this.kind;
      this.result;*/
    }

    function generateError(state, message) {
      return new YAMLException$1(message, new Mark(state.filename, state.input, state.position, state.line, state.position - state.lineStart));
    }
    function throwError(state, message) {
      throw generateError(state, message);
    }
    function throwWarning(state, message) {
      if (state.onWarning) {
        state.onWarning.call(null, generateError(state, message));
      }
    }
    var directiveHandlers = {
      YAML: function handleYamlDirective(state, name, args) {
        var match, major, minor;
        if (state.version !== null) {
          throwError(state, 'duplication of %YAML directive');
        }
        if (args.length !== 1) {
          throwError(state, 'YAML directive accepts exactly one argument');
        }
        match = /^([0-9]+)\.([0-9]+)$/.exec(args[0]);
        if (match === null) {
          throwError(state, 'ill-formed argument of the YAML directive');
        }
        major = parseInt(match[1], 10);
        minor = parseInt(match[2], 10);
        if (major !== 1) {
          throwError(state, 'unacceptable YAML version of the document');
        }
        state.version = args[0];
        state.checkLineBreaks = minor < 2;
        if (minor !== 1 && minor !== 2) {
          throwWarning(state, 'unsupported YAML version of the document');
        }
      },
      TAG: function handleTagDirective(state, name, args) {
        var handle, prefix;
        if (args.length !== 2) {
          throwError(state, 'TAG directive accepts exactly two arguments');
        }
        handle = args[0];
        prefix = args[1];
        if (!PATTERN_TAG_HANDLE.test(handle)) {
          throwError(state, 'ill-formed tag handle (first argument) of the TAG directive');
        }
        if (_hasOwnProperty$1.call(state.tagMap, handle)) {
          throwError(state, 'there is a previously declared suffix for "' + handle + '" tag handle');
        }
        if (!PATTERN_TAG_URI.test(prefix)) {
          throwError(state, 'ill-formed tag prefix (second argument) of the TAG directive');
        }
        state.tagMap[handle] = prefix;
      }
    };
    function captureSegment(state, start, end, checkJson) {
      var _position, _length, _character, _result;
      if (start < end) {
        _result = state.input.slice(start, end);
        if (checkJson) {
          for (_position = 0, _length = _result.length; _position < _length; _position += 1) {
            _character = _result.charCodeAt(_position);
            if (!(_character === 0x09 || 0x20 <= _character && _character <= 0x10FFFF)) {
              throwError(state, 'expected valid JSON character');
            }
          }
        } else if (PATTERN_NON_PRINTABLE.test(_result)) {
          throwError(state, 'the stream contains non-printable characters');
        }
        state.result += _result;
      }
    }
    function mergeMappings(state, destination, source, overridableKeys) {
      var sourceKeys, key, index, quantity;
      if (!common$1.isObject(source)) {
        throwError(state, 'cannot merge mappings; the provided source object is unacceptable');
      }
      sourceKeys = Object.keys(source);
      for (index = 0, quantity = sourceKeys.length; index < quantity; index += 1) {
        key = sourceKeys[index];
        if (!_hasOwnProperty$1.call(destination, key)) {
          destination[key] = source[key];
          overridableKeys[key] = true;
        }
      }
    }
    function storeMappingPair(state, _result, overridableKeys, keyTag, keyNode, valueNode, startLine, startPos) {
      var index, quantity;

      // The output is a plain object here, so keys can only be strings.
      // We need to convert keyNode to a string, but doing so can hang the process
      // (deeply nested arrays that explode exponentially using aliases).
      if (Array.isArray(keyNode)) {
        keyNode = Array.prototype.slice.call(keyNode);
        for (index = 0, quantity = keyNode.length; index < quantity; index += 1) {
          if (Array.isArray(keyNode[index])) {
            throwError(state, 'nested arrays are not supported inside keys');
          }
          if (typeof keyNode === 'object' && _class(keyNode[index]) === '[object Object]') {
            keyNode[index] = '[object Object]';
          }
        }
      }

      // Avoid code execution in load() via toString property
      // (still use its own toString for arrays, timestamps,
      // and whatever user schema extensions happen to have @@toStringTag)
      if (typeof keyNode === 'object' && _class(keyNode) === '[object Object]') {
        keyNode = '[object Object]';
      }
      keyNode = String(keyNode);
      if (_result === null) {
        _result = {};
      }
      if (keyTag === 'tag:yaml.org,2002:merge') {
        if (Array.isArray(valueNode)) {
          for (index = 0, quantity = valueNode.length; index < quantity; index += 1) {
            mergeMappings(state, _result, valueNode[index], overridableKeys);
          }
        } else {
          mergeMappings(state, _result, valueNode, overridableKeys);
        }
      } else {
        if (!state.json && !_hasOwnProperty$1.call(overridableKeys, keyNode) && _hasOwnProperty$1.call(_result, keyNode)) {
          state.line = startLine || state.line;
          state.position = startPos || state.position;
          throwError(state, 'duplicated mapping key');
        }
        _result[keyNode] = valueNode;
        delete overridableKeys[keyNode];
      }
      return _result;
    }
    function readLineBreak(state) {
      var ch;
      ch = state.input.charCodeAt(state.position);
      if (ch === 0x0A /* LF */) {
        state.position++;
      } else if (ch === 0x0D /* CR */) {
        state.position++;
        if (state.input.charCodeAt(state.position) === 0x0A /* LF */) {
          state.position++;
        }
      } else {
        throwError(state, 'a line break is expected');
      }
      state.line += 1;
      state.lineStart = state.position;
    }
    function skipSeparationSpace(state, allowComments, checkIndent) {
      var lineBreaks = 0,
        ch = state.input.charCodeAt(state.position);
      while (ch !== 0) {
        while (is_WHITE_SPACE(ch)) {
          ch = state.input.charCodeAt(++state.position);
        }
        if (allowComments && ch === 0x23 /* # */) {
          do {
            ch = state.input.charCodeAt(++state.position);
          } while (ch !== 0x0A /* LF */ && ch !== 0x0D /* CR */ && ch !== 0);
        }
        if (is_EOL(ch)) {
          readLineBreak(state);
          ch = state.input.charCodeAt(state.position);
          lineBreaks++;
          state.lineIndent = 0;
          while (ch === 0x20 /* Space */) {
            state.lineIndent++;
            ch = state.input.charCodeAt(++state.position);
          }
        } else {
          break;
        }
      }
      if (checkIndent !== -1 && lineBreaks !== 0 && state.lineIndent < checkIndent) {
        throwWarning(state, 'deficient indentation');
      }
      return lineBreaks;
    }
    function testDocumentSeparator(state) {
      var _position = state.position,
        ch;
      ch = state.input.charCodeAt(_position);

      // Condition state.position === state.lineStart is tested
      // in parent on each call, for efficiency. No needs to test here again.
      if ((ch === 0x2D /* - */ || ch === 0x2E /* . */) && ch === state.input.charCodeAt(_position + 1) && ch === state.input.charCodeAt(_position + 2)) {
        _position += 3;
        ch = state.input.charCodeAt(_position);
        if (ch === 0 || is_WS_OR_EOL(ch)) {
          return true;
        }
      }
      return false;
    }
    function writeFoldedLines(state, count) {
      if (count === 1) {
        state.result += ' ';
      } else if (count > 1) {
        state.result += common$1.repeat('\n', count - 1);
      }
    }
    function readPlainScalar(state, nodeIndent, withinFlowCollection) {
      var preceding,
        following,
        captureStart,
        captureEnd,
        hasPendingContent,
        _line,
        _lineStart,
        _lineIndent,
        _kind = state.kind,
        _result = state.result,
        ch;
      ch = state.input.charCodeAt(state.position);
      if (is_WS_OR_EOL(ch) || is_FLOW_INDICATOR(ch) || ch === 0x23 /* # */ || ch === 0x26 /* & */ || ch === 0x2A /* * */ || ch === 0x21 /* ! */ || ch === 0x7C /* | */ || ch === 0x3E /* > */ || ch === 0x27 /* ' */ || ch === 0x22 /* " */ || ch === 0x25 /* % */ || ch === 0x40 /* @ */ || ch === 0x60 /* ` */) {
        return false;
      }
      if (ch === 0x3F /* ? */ || ch === 0x2D /* - */) {
        following = state.input.charCodeAt(state.position + 1);
        if (is_WS_OR_EOL(following) || withinFlowCollection && is_FLOW_INDICATOR(following)) {
          return false;
        }
      }
      state.kind = 'scalar';
      state.result = '';
      captureStart = captureEnd = state.position;
      hasPendingContent = false;
      while (ch !== 0) {
        if (ch === 0x3A /* : */) {
          following = state.input.charCodeAt(state.position + 1);
          if (is_WS_OR_EOL(following) || withinFlowCollection && is_FLOW_INDICATOR(following)) {
            break;
          }
        } else if (ch === 0x23 /* # */) {
          preceding = state.input.charCodeAt(state.position - 1);
          if (is_WS_OR_EOL(preceding)) {
            break;
          }
        } else if (state.position === state.lineStart && testDocumentSeparator(state) || withinFlowCollection && is_FLOW_INDICATOR(ch)) {
          break;
        } else if (is_EOL(ch)) {
          _line = state.line;
          _lineStart = state.lineStart;
          _lineIndent = state.lineIndent;
          skipSeparationSpace(state, false, -1);
          if (state.lineIndent >= nodeIndent) {
            hasPendingContent = true;
            ch = state.input.charCodeAt(state.position);
            continue;
          } else {
            state.position = captureEnd;
            state.line = _line;
            state.lineStart = _lineStart;
            state.lineIndent = _lineIndent;
            break;
          }
        }
        if (hasPendingContent) {
          captureSegment(state, captureStart, captureEnd, false);
          writeFoldedLines(state, state.line - _line);
          captureStart = captureEnd = state.position;
          hasPendingContent = false;
        }
        if (!is_WHITE_SPACE(ch)) {
          captureEnd = state.position + 1;
        }
        ch = state.input.charCodeAt(++state.position);
      }
      captureSegment(state, captureStart, captureEnd, false);
      if (state.result) {
        return true;
      }
      state.kind = _kind;
      state.result = _result;
      return false;
    }
    function readSingleQuotedScalar(state, nodeIndent) {
      var ch, captureStart, captureEnd;
      ch = state.input.charCodeAt(state.position);
      if (ch !== 0x27 /* ' */) {
        return false;
      }
      state.kind = 'scalar';
      state.result = '';
      state.position++;
      captureStart = captureEnd = state.position;
      while ((ch = state.input.charCodeAt(state.position)) !== 0) {
        if (ch === 0x27 /* ' */) {
          captureSegment(state, captureStart, state.position, true);
          ch = state.input.charCodeAt(++state.position);
          if (ch === 0x27 /* ' */) {
            captureStart = state.position;
            state.position++;
            captureEnd = state.position;
          } else {
            return true;
          }
        } else if (is_EOL(ch)) {
          captureSegment(state, captureStart, captureEnd, true);
          writeFoldedLines(state, skipSeparationSpace(state, false, nodeIndent));
          captureStart = captureEnd = state.position;
        } else if (state.position === state.lineStart && testDocumentSeparator(state)) {
          throwError(state, 'unexpected end of the document within a single quoted scalar');
        } else {
          state.position++;
          captureEnd = state.position;
        }
      }
      throwError(state, 'unexpected end of the stream within a single quoted scalar');
    }
    function readDoubleQuotedScalar(state, nodeIndent) {
      var captureStart, captureEnd, hexLength, hexResult, tmp, ch;
      ch = state.input.charCodeAt(state.position);
      if (ch !== 0x22 /* " */) {
        return false;
      }
      state.kind = 'scalar';
      state.result = '';
      state.position++;
      captureStart = captureEnd = state.position;
      while ((ch = state.input.charCodeAt(state.position)) !== 0) {
        if (ch === 0x22 /* " */) {
          captureSegment(state, captureStart, state.position, true);
          state.position++;
          return true;
        } else if (ch === 0x5C /* \ */) {
          captureSegment(state, captureStart, state.position, true);
          ch = state.input.charCodeAt(++state.position);
          if (is_EOL(ch)) {
            skipSeparationSpace(state, false, nodeIndent);

            // TODO: rework to inline fn with no type cast?
          } else if (ch < 256 && simpleEscapeCheck[ch]) {
            state.result += simpleEscapeMap[ch];
            state.position++;
          } else if ((tmp = escapedHexLen(ch)) > 0) {
            hexLength = tmp;
            hexResult = 0;
            for (; hexLength > 0; hexLength--) {
              ch = state.input.charCodeAt(++state.position);
              if ((tmp = fromHexCode(ch)) >= 0) {
                hexResult = (hexResult << 4) + tmp;
              } else {
                throwError(state, 'expected hexadecimal character');
              }
            }
            state.result += charFromCodepoint(hexResult);
            state.position++;
          } else {
            throwError(state, 'unknown escape sequence');
          }
          captureStart = captureEnd = state.position;
        } else if (is_EOL(ch)) {
          captureSegment(state, captureStart, captureEnd, true);
          writeFoldedLines(state, skipSeparationSpace(state, false, nodeIndent));
          captureStart = captureEnd = state.position;
        } else if (state.position === state.lineStart && testDocumentSeparator(state)) {
          throwError(state, 'unexpected end of the document within a double quoted scalar');
        } else {
          state.position++;
          captureEnd = state.position;
        }
      }
      throwError(state, 'unexpected end of the stream within a double quoted scalar');
    }
    function readFlowCollection(state, nodeIndent) {
      var readNext = true,
        _line,
        _tag = state.tag,
        _result,
        _anchor = state.anchor,
        following,
        terminator,
        isPair,
        isExplicitPair,
        isMapping,
        overridableKeys = {},
        keyNode,
        keyTag,
        valueNode,
        ch;
      ch = state.input.charCodeAt(state.position);
      if (ch === 0x5B /* [ */) {
        terminator = 0x5D; /* ] */
        isMapping = false;
        _result = [];
      } else if (ch === 0x7B /* { */) {
        terminator = 0x7D; /* } */
        isMapping = true;
        _result = {};
      } else {
        return false;
      }
      if (state.anchor !== null) {
        state.anchorMap[state.anchor] = _result;
      }
      ch = state.input.charCodeAt(++state.position);
      while (ch !== 0) {
        skipSeparationSpace(state, true, nodeIndent);
        ch = state.input.charCodeAt(state.position);
        if (ch === terminator) {
          state.position++;
          state.tag = _tag;
          state.anchor = _anchor;
          state.kind = isMapping ? 'mapping' : 'sequence';
          state.result = _result;
          return true;
        } else if (!readNext) {
          throwError(state, 'missed comma between flow collection entries');
        }
        keyTag = keyNode = valueNode = null;
        isPair = isExplicitPair = false;
        if (ch === 0x3F /* ? */) {
          following = state.input.charCodeAt(state.position + 1);
          if (is_WS_OR_EOL(following)) {
            isPair = isExplicitPair = true;
            state.position++;
            skipSeparationSpace(state, true, nodeIndent);
          }
        }
        _line = state.line;
        composeNode(state, nodeIndent, CONTEXT_FLOW_IN, false, true);
        keyTag = state.tag;
        keyNode = state.result;
        skipSeparationSpace(state, true, nodeIndent);
        ch = state.input.charCodeAt(state.position);
        if ((isExplicitPair || state.line === _line) && ch === 0x3A /* : */) {
          isPair = true;
          ch = state.input.charCodeAt(++state.position);
          skipSeparationSpace(state, true, nodeIndent);
          composeNode(state, nodeIndent, CONTEXT_FLOW_IN, false, true);
          valueNode = state.result;
        }
        if (isMapping) {
          storeMappingPair(state, _result, overridableKeys, keyTag, keyNode, valueNode);
        } else if (isPair) {
          _result.push(storeMappingPair(state, null, overridableKeys, keyTag, keyNode, valueNode));
        } else {
          _result.push(keyNode);
        }
        skipSeparationSpace(state, true, nodeIndent);
        ch = state.input.charCodeAt(state.position);
        if (ch === 0x2C /* , */) {
          readNext = true;
          ch = state.input.charCodeAt(++state.position);
        } else {
          readNext = false;
        }
      }
      throwError(state, 'unexpected end of the stream within a flow collection');
    }
    function readBlockScalar(state, nodeIndent) {
      var captureStart,
        folding,
        chomping = CHOMPING_CLIP,
        didReadContent = false,
        detectedIndent = false,
        textIndent = nodeIndent,
        emptyLines = 0,
        atMoreIndented = false,
        tmp,
        ch;
      ch = state.input.charCodeAt(state.position);
      if (ch === 0x7C /* | */) {
        folding = false;
      } else if (ch === 0x3E /* > */) {
        folding = true;
      } else {
        return false;
      }
      state.kind = 'scalar';
      state.result = '';
      while (ch !== 0) {
        ch = state.input.charCodeAt(++state.position);
        if (ch === 0x2B /* + */ || ch === 0x2D /* - */) {
          if (CHOMPING_CLIP === chomping) {
            chomping = ch === 0x2B /* + */ ? CHOMPING_KEEP : CHOMPING_STRIP;
          } else {
            throwError(state, 'repeat of a chomping mode identifier');
          }
        } else if ((tmp = fromDecimalCode(ch)) >= 0) {
          if (tmp === 0) {
            throwError(state, 'bad explicit indentation width of a block scalar; it cannot be less than one');
          } else if (!detectedIndent) {
            textIndent = nodeIndent + tmp - 1;
            detectedIndent = true;
          } else {
            throwError(state, 'repeat of an indentation width identifier');
          }
        } else {
          break;
        }
      }
      if (is_WHITE_SPACE(ch)) {
        do {
          ch = state.input.charCodeAt(++state.position);
        } while (is_WHITE_SPACE(ch));
        if (ch === 0x23 /* # */) {
          do {
            ch = state.input.charCodeAt(++state.position);
          } while (!is_EOL(ch) && ch !== 0);
        }
      }
      while (ch !== 0) {
        readLineBreak(state);
        state.lineIndent = 0;
        ch = state.input.charCodeAt(state.position);
        while ((!detectedIndent || state.lineIndent < textIndent) && ch === 0x20 /* Space */) {
          state.lineIndent++;
          ch = state.input.charCodeAt(++state.position);
        }
        if (!detectedIndent && state.lineIndent > textIndent) {
          textIndent = state.lineIndent;
        }
        if (is_EOL(ch)) {
          emptyLines++;
          continue;
        }

        // End of the scalar.
        if (state.lineIndent < textIndent) {
          // Perform the chomping.
          if (chomping === CHOMPING_KEEP) {
            state.result += common$1.repeat('\n', didReadContent ? 1 + emptyLines : emptyLines);
          } else if (chomping === CHOMPING_CLIP) {
            if (didReadContent) {
              // i.e. only if the scalar is not empty.
              state.result += '\n';
            }
          }

          // Break this `while` cycle and go to the funciton's epilogue.
          break;
        }

        // Folded style: use fancy rules to handle line breaks.
        if (folding) {
          // Lines starting with white space characters (more-indented lines) are not folded.
          if (is_WHITE_SPACE(ch)) {
            atMoreIndented = true;
            // except for the first content line (cf. Example 8.1)
            state.result += common$1.repeat('\n', didReadContent ? 1 + emptyLines : emptyLines);

            // End of more-indented block.
          } else if (atMoreIndented) {
            atMoreIndented = false;
            state.result += common$1.repeat('\n', emptyLines + 1);

            // Just one line break - perceive as the same line.
          } else if (emptyLines === 0) {
            if (didReadContent) {
              // i.e. only if we have already read some scalar content.
              state.result += ' ';
            }

            // Several line breaks - perceive as different lines.
          } else {
            state.result += common$1.repeat('\n', emptyLines);
          }

          // Literal style: just add exact number of line breaks between content lines.
        } else {
          // Keep all line breaks except the header line break.
          state.result += common$1.repeat('\n', didReadContent ? 1 + emptyLines : emptyLines);
        }
        didReadContent = true;
        detectedIndent = true;
        emptyLines = 0;
        captureStart = state.position;
        while (!is_EOL(ch) && ch !== 0) {
          ch = state.input.charCodeAt(++state.position);
        }
        captureSegment(state, captureStart, state.position, false);
      }
      return true;
    }
    function readBlockSequence(state, nodeIndent) {
      var _line,
        _tag = state.tag,
        _anchor = state.anchor,
        _result = [],
        following,
        detected = false,
        ch;
      if (state.anchor !== null) {
        state.anchorMap[state.anchor] = _result;
      }
      ch = state.input.charCodeAt(state.position);
      while (ch !== 0) {
        if (ch !== 0x2D /* - */) {
          break;
        }
        following = state.input.charCodeAt(state.position + 1);
        if (!is_WS_OR_EOL(following)) {
          break;
        }
        detected = true;
        state.position++;
        if (skipSeparationSpace(state, true, -1)) {
          if (state.lineIndent <= nodeIndent) {
            _result.push(null);
            ch = state.input.charCodeAt(state.position);
            continue;
          }
        }
        _line = state.line;
        composeNode(state, nodeIndent, CONTEXT_BLOCK_IN, false, true);
        _result.push(state.result);
        skipSeparationSpace(state, true, -1);
        ch = state.input.charCodeAt(state.position);
        if ((state.line === _line || state.lineIndent > nodeIndent) && ch !== 0) {
          throwError(state, 'bad indentation of a sequence entry');
        } else if (state.lineIndent < nodeIndent) {
          break;
        }
      }
      if (detected) {
        state.tag = _tag;
        state.anchor = _anchor;
        state.kind = 'sequence';
        state.result = _result;
        return true;
      }
      return false;
    }
    function readBlockMapping(state, nodeIndent, flowIndent) {
      var following,
        allowCompact,
        _line,
        _pos,
        _tag = state.tag,
        _anchor = state.anchor,
        _result = {},
        overridableKeys = {},
        keyTag = null,
        keyNode = null,
        valueNode = null,
        atExplicitKey = false,
        detected = false,
        ch;
      if (state.anchor !== null) {
        state.anchorMap[state.anchor] = _result;
      }
      ch = state.input.charCodeAt(state.position);
      while (ch !== 0) {
        following = state.input.charCodeAt(state.position + 1);
        _line = state.line; // Save the current line.
        _pos = state.position;

        //
        // Explicit notation case. There are two separate blocks:
        // first for the key (denoted by "?") and second for the value (denoted by ":")
        //
        if ((ch === 0x3F /* ? */ || ch === 0x3A /* : */) && is_WS_OR_EOL(following)) {
          if (ch === 0x3F /* ? */) {
            if (atExplicitKey) {
              storeMappingPair(state, _result, overridableKeys, keyTag, keyNode, null);
              keyTag = keyNode = valueNode = null;
            }
            detected = true;
            atExplicitKey = true;
            allowCompact = true;
          } else if (atExplicitKey) {
            // i.e. 0x3A/* : */ === character after the explicit key.
            atExplicitKey = false;
            allowCompact = true;
          } else {
            throwError(state, 'incomplete explicit mapping pair; a key node is missed; or followed by a non-tabulated empty line');
          }
          state.position += 1;
          ch = following;

          //
          // Implicit notation case. Flow-style node as the key first, then ":", and the value.
          //
        } else if (composeNode(state, flowIndent, CONTEXT_FLOW_OUT, false, true)) {
          if (state.line === _line) {
            ch = state.input.charCodeAt(state.position);
            while (is_WHITE_SPACE(ch)) {
              ch = state.input.charCodeAt(++state.position);
            }
            if (ch === 0x3A /* : */) {
              ch = state.input.charCodeAt(++state.position);
              if (!is_WS_OR_EOL(ch)) {
                throwError(state, 'a whitespace character is expected after the key-value separator within a block mapping');
              }
              if (atExplicitKey) {
                storeMappingPair(state, _result, overridableKeys, keyTag, keyNode, null);
                keyTag = keyNode = valueNode = null;
              }
              detected = true;
              atExplicitKey = false;
              allowCompact = false;
              keyTag = state.tag;
              keyNode = state.result;
            } else if (detected) {
              throwError(state, 'can not read an implicit mapping pair; a colon is missed');
            } else {
              state.tag = _tag;
              state.anchor = _anchor;
              return true; // Keep the result of `composeNode`.
            }
          } else if (detected) {
            throwError(state, 'can not read a block mapping entry; a multiline key may not be an implicit key');
          } else {
            state.tag = _tag;
            state.anchor = _anchor;
            return true; // Keep the result of `composeNode`.
          }
        } else {
          break; // Reading is done. Go to the epilogue.
        }

        //
        // Common reading code for both explicit and implicit notations.
        //
        if (state.line === _line || state.lineIndent > nodeIndent) {
          if (composeNode(state, nodeIndent, CONTEXT_BLOCK_OUT, true, allowCompact)) {
            if (atExplicitKey) {
              keyNode = state.result;
            } else {
              valueNode = state.result;
            }
          }
          if (!atExplicitKey) {
            storeMappingPair(state, _result, overridableKeys, keyTag, keyNode, valueNode, _line, _pos);
            keyTag = keyNode = valueNode = null;
          }
          skipSeparationSpace(state, true, -1);
          ch = state.input.charCodeAt(state.position);
        }
        if (state.lineIndent > nodeIndent && ch !== 0) {
          throwError(state, 'bad indentation of a mapping entry');
        } else if (state.lineIndent < nodeIndent) {
          break;
        }
      }

      //
      // Epilogue.
      //

      // Special case: last mapping's node contains only the key in explicit notation.
      if (atExplicitKey) {
        storeMappingPair(state, _result, overridableKeys, keyTag, keyNode, null);
      }

      // Expose the resulting mapping.
      if (detected) {
        state.tag = _tag;
        state.anchor = _anchor;
        state.kind = 'mapping';
        state.result = _result;
      }
      return detected;
    }
    function readTagProperty(state) {
      var _position,
        isVerbatim = false,
        isNamed = false,
        tagHandle,
        tagName,
        ch;
      ch = state.input.charCodeAt(state.position);
      if (ch !== 0x21 /* ! */) return false;
      if (state.tag !== null) {
        throwError(state, 'duplication of a tag property');
      }
      ch = state.input.charCodeAt(++state.position);
      if (ch === 0x3C /* < */) {
        isVerbatim = true;
        ch = state.input.charCodeAt(++state.position);
      } else if (ch === 0x21 /* ! */) {
        isNamed = true;
        tagHandle = '!!';
        ch = state.input.charCodeAt(++state.position);
      } else {
        tagHandle = '!';
      }
      _position = state.position;
      if (isVerbatim) {
        do {
          ch = state.input.charCodeAt(++state.position);
        } while (ch !== 0 && ch !== 0x3E /* > */);

        if (state.position < state.length) {
          tagName = state.input.slice(_position, state.position);
          ch = state.input.charCodeAt(++state.position);
        } else {
          throwError(state, 'unexpected end of the stream within a verbatim tag');
        }
      } else {
        while (ch !== 0 && !is_WS_OR_EOL(ch)) {
          if (ch === 0x21 /* ! */) {
            if (!isNamed) {
              tagHandle = state.input.slice(_position - 1, state.position + 1);
              if (!PATTERN_TAG_HANDLE.test(tagHandle)) {
                throwError(state, 'named tag handle cannot contain such characters');
              }
              isNamed = true;
              _position = state.position + 1;
            } else {
              throwError(state, 'tag suffix cannot contain exclamation marks');
            }
          }
          ch = state.input.charCodeAt(++state.position);
        }
        tagName = state.input.slice(_position, state.position);
        if (PATTERN_FLOW_INDICATORS.test(tagName)) {
          throwError(state, 'tag suffix cannot contain flow indicator characters');
        }
      }
      if (tagName && !PATTERN_TAG_URI.test(tagName)) {
        throwError(state, 'tag name cannot contain such characters: ' + tagName);
      }
      if (isVerbatim) {
        state.tag = tagName;
      } else if (_hasOwnProperty$1.call(state.tagMap, tagHandle)) {
        state.tag = state.tagMap[tagHandle] + tagName;
      } else if (tagHandle === '!') {
        state.tag = '!' + tagName;
      } else if (tagHandle === '!!') {
        state.tag = 'tag:yaml.org,2002:' + tagName;
      } else {
        throwError(state, 'undeclared tag handle "' + tagHandle + '"');
      }
      return true;
    }
    function readAnchorProperty(state) {
      var _position, ch;
      ch = state.input.charCodeAt(state.position);
      if (ch !== 0x26 /* & */) return false;
      if (state.anchor !== null) {
        throwError(state, 'duplication of an anchor property');
      }
      ch = state.input.charCodeAt(++state.position);
      _position = state.position;
      while (ch !== 0 && !is_WS_OR_EOL(ch) && !is_FLOW_INDICATOR(ch)) {
        ch = state.input.charCodeAt(++state.position);
      }
      if (state.position === _position) {
        throwError(state, 'name of an anchor node must contain at least one character');
      }
      state.anchor = state.input.slice(_position, state.position);
      return true;
    }
    function readAlias(state) {
      var _position, alias, ch;
      ch = state.input.charCodeAt(state.position);
      if (ch !== 0x2A /* * */) return false;
      ch = state.input.charCodeAt(++state.position);
      _position = state.position;
      while (ch !== 0 && !is_WS_OR_EOL(ch) && !is_FLOW_INDICATOR(ch)) {
        ch = state.input.charCodeAt(++state.position);
      }
      if (state.position === _position) {
        throwError(state, 'name of an alias node must contain at least one character');
      }
      alias = state.input.slice(_position, state.position);
      if (!_hasOwnProperty$1.call(state.anchorMap, alias)) {
        throwError(state, 'unidentified alias "' + alias + '"');
      }
      state.result = state.anchorMap[alias];
      skipSeparationSpace(state, true, -1);
      return true;
    }
    function composeNode(state, parentIndent, nodeContext, allowToSeek, allowCompact) {
      var allowBlockStyles,
        allowBlockScalars,
        allowBlockCollections,
        indentStatus = 1,
        // 1: this>parent, 0: this=parent, -1: this<parent
        atNewLine = false,
        hasContent = false,
        typeIndex,
        typeQuantity,
        type,
        flowIndent,
        blockIndent;
      if (state.listener !== null) {
        state.listener('open', state);
      }
      state.tag = null;
      state.anchor = null;
      state.kind = null;
      state.result = null;
      allowBlockStyles = allowBlockScalars = allowBlockCollections = CONTEXT_BLOCK_OUT === nodeContext || CONTEXT_BLOCK_IN === nodeContext;
      if (allowToSeek) {
        if (skipSeparationSpace(state, true, -1)) {
          atNewLine = true;
          if (state.lineIndent > parentIndent) {
            indentStatus = 1;
          } else if (state.lineIndent === parentIndent) {
            indentStatus = 0;
          } else if (state.lineIndent < parentIndent) {
            indentStatus = -1;
          }
        }
      }
      if (indentStatus === 1) {
        while (readTagProperty(state) || readAnchorProperty(state)) {
          if (skipSeparationSpace(state, true, -1)) {
            atNewLine = true;
            allowBlockCollections = allowBlockStyles;
            if (state.lineIndent > parentIndent) {
              indentStatus = 1;
            } else if (state.lineIndent === parentIndent) {
              indentStatus = 0;
            } else if (state.lineIndent < parentIndent) {
              indentStatus = -1;
            }
          } else {
            allowBlockCollections = false;
          }
        }
      }
      if (allowBlockCollections) {
        allowBlockCollections = atNewLine || allowCompact;
      }
      if (indentStatus === 1 || CONTEXT_BLOCK_OUT === nodeContext) {
        if (CONTEXT_FLOW_IN === nodeContext || CONTEXT_FLOW_OUT === nodeContext) {
          flowIndent = parentIndent;
        } else {
          flowIndent = parentIndent + 1;
        }
        blockIndent = state.position - state.lineStart;
        if (indentStatus === 1) {
          if (allowBlockCollections && (readBlockSequence(state, blockIndent) || readBlockMapping(state, blockIndent, flowIndent)) || readFlowCollection(state, flowIndent)) {
            hasContent = true;
          } else {
            if (allowBlockScalars && readBlockScalar(state, flowIndent) || readSingleQuotedScalar(state, flowIndent) || readDoubleQuotedScalar(state, flowIndent)) {
              hasContent = true;
            } else if (readAlias(state)) {
              hasContent = true;
              if (state.tag !== null || state.anchor !== null) {
                throwError(state, 'alias node should not have any properties');
              }
            } else if (readPlainScalar(state, flowIndent, CONTEXT_FLOW_IN === nodeContext)) {
              hasContent = true;
              if (state.tag === null) {
                state.tag = '?';
              }
            }
            if (state.anchor !== null) {
              state.anchorMap[state.anchor] = state.result;
            }
          }
        } else if (indentStatus === 0) {
          // Special case: block sequences are allowed to have same indentation level as the parent.
          // http://www.yaml.org/spec/1.2/spec.html#id2799784
          hasContent = allowBlockCollections && readBlockSequence(state, blockIndent);
        }
      }
      if (state.tag !== null && state.tag !== '!') {
        if (state.tag === '?') {
          // Implicit resolving is not allowed for non-scalar types, and '?'
          // non-specific tag is only automatically assigned to plain scalars.
          //
          // We only need to check kind conformity in case user explicitly assigns '?'
          // tag, for example like this: "!<?> [0]"
          //
          if (state.result !== null && state.kind !== 'scalar') {
            throwError(state, 'unacceptable node kind for !<?> tag; it should be "scalar", not "' + state.kind + '"');
          }
          for (typeIndex = 0, typeQuantity = state.implicitTypes.length; typeIndex < typeQuantity; typeIndex += 1) {
            type = state.implicitTypes[typeIndex];
            if (type.resolve(state.result)) {
              // `state.result` updated in resolver if matched
              state.result = type.construct(state.result);
              state.tag = type.tag;
              if (state.anchor !== null) {
                state.anchorMap[state.anchor] = state.result;
              }
              break;
            }
          }
        } else if (_hasOwnProperty$1.call(state.typeMap[state.kind || 'fallback'], state.tag)) {
          type = state.typeMap[state.kind || 'fallback'][state.tag];
          if (state.result !== null && type.kind !== state.kind) {
            throwError(state, 'unacceptable node kind for !<' + state.tag + '> tag; it should be "' + type.kind + '", not "' + state.kind + '"');
          }
          if (!type.resolve(state.result)) {
            // `state.result` updated in resolver if matched
            throwError(state, 'cannot resolve a node with !<' + state.tag + '> explicit tag');
          } else {
            state.result = type.construct(state.result);
            if (state.anchor !== null) {
              state.anchorMap[state.anchor] = state.result;
            }
          }
        } else {
          throwError(state, 'unknown tag !<' + state.tag + '>');
        }
      }
      if (state.listener !== null) {
        state.listener('close', state);
      }
      return state.tag !== null || state.anchor !== null || hasContent;
    }
    function readDocument(state) {
      var documentStart = state.position,
        _position,
        directiveName,
        directiveArgs,
        hasDirectives = false,
        ch;
      state.version = null;
      state.checkLineBreaks = state.legacy;
      state.tagMap = {};
      state.anchorMap = {};
      while ((ch = state.input.charCodeAt(state.position)) !== 0) {
        skipSeparationSpace(state, true, -1);
        ch = state.input.charCodeAt(state.position);
        if (state.lineIndent > 0 || ch !== 0x25 /* % */) {
          break;
        }
        hasDirectives = true;
        ch = state.input.charCodeAt(++state.position);
        _position = state.position;
        while (ch !== 0 && !is_WS_OR_EOL(ch)) {
          ch = state.input.charCodeAt(++state.position);
        }
        directiveName = state.input.slice(_position, state.position);
        directiveArgs = [];
        if (directiveName.length < 1) {
          throwError(state, 'directive name must not be less than one character in length');
        }
        while (ch !== 0) {
          while (is_WHITE_SPACE(ch)) {
            ch = state.input.charCodeAt(++state.position);
          }
          if (ch === 0x23 /* # */) {
            do {
              ch = state.input.charCodeAt(++state.position);
            } while (ch !== 0 && !is_EOL(ch));
            break;
          }
          if (is_EOL(ch)) break;
          _position = state.position;
          while (ch !== 0 && !is_WS_OR_EOL(ch)) {
            ch = state.input.charCodeAt(++state.position);
          }
          directiveArgs.push(state.input.slice(_position, state.position));
        }
        if (ch !== 0) readLineBreak(state);
        if (_hasOwnProperty$1.call(directiveHandlers, directiveName)) {
          directiveHandlers[directiveName](state, directiveName, directiveArgs);
        } else {
          throwWarning(state, 'unknown document directive "' + directiveName + '"');
        }
      }
      skipSeparationSpace(state, true, -1);
      if (state.lineIndent === 0 && state.input.charCodeAt(state.position) === 0x2D /* - */ && state.input.charCodeAt(state.position + 1) === 0x2D /* - */ && state.input.charCodeAt(state.position + 2) === 0x2D /* - */) {
        state.position += 3;
        skipSeparationSpace(state, true, -1);
      } else if (hasDirectives) {
        throwError(state, 'directives end mark is expected');
      }
      composeNode(state, state.lineIndent - 1, CONTEXT_BLOCK_OUT, false, true);
      skipSeparationSpace(state, true, -1);
      if (state.checkLineBreaks && PATTERN_NON_ASCII_LINE_BREAKS.test(state.input.slice(documentStart, state.position))) {
        throwWarning(state, 'non-ASCII line breaks are interpreted as content');
      }
      state.documents.push(state.result);
      if (state.position === state.lineStart && testDocumentSeparator(state)) {
        if (state.input.charCodeAt(state.position) === 0x2E /* . */) {
          state.position += 3;
          skipSeparationSpace(state, true, -1);
        }
        return;
      }
      if (state.position < state.length - 1) {
        throwError(state, 'end of the stream or a document separator is expected');
      } else {
        return;
      }
    }
    function loadDocuments(input, options) {
      input = String(input);
      options = options || {};
      if (input.length !== 0) {
        // Add tailing `\n` if not exists
        if (input.charCodeAt(input.length - 1) !== 0x0A /* LF */ && input.charCodeAt(input.length - 1) !== 0x0D /* CR */) {
          input += '\n';
        }

        // Strip BOM
        if (input.charCodeAt(0) === 0xFEFF) {
          input = input.slice(1);
        }
      }
      var state = new State$1(input, options);
      var nullpos = input.indexOf('\0');
      if (nullpos !== -1) {
        state.position = nullpos;
        throwError(state, 'null byte is not allowed in input');
      }

      // Use 0 as string terminator. That significantly simplifies bounds check.
      state.input += '\0';
      while (state.input.charCodeAt(state.position) === 0x20 /* Space */) {
        state.lineIndent += 1;
        state.position += 1;
      }
      while (state.position < state.length - 1) {
        readDocument(state);
      }
      return state.documents;
    }
    function loadAll(input, iterator, options) {
      if (iterator !== null && typeof iterator === 'object' && typeof options === 'undefined') {
        options = iterator;
        iterator = null;
      }
      var documents = loadDocuments(input, options);
      if (typeof iterator !== 'function') {
        return documents;
      }
      for (var index = 0, length = documents.length; index < length; index += 1) {
        iterator(documents[index]);
      }
    }
    function load(input, options) {
      var documents = loadDocuments(input, options);
      if (documents.length === 0) {
        /*eslint-disable no-undefined*/
        return undefined;
      } else if (documents.length === 1) {
        return documents[0];
      }
      throw new YAMLException$1('expected a single document in the stream, but found more');
    }
    function safeLoadAll(input, iterator, options) {
      if (typeof iterator === 'object' && iterator !== null && typeof options === 'undefined') {
        options = iterator;
        iterator = null;
      }
      return loadAll(input, iterator, common$1.extend({
        schema: DEFAULT_SAFE_SCHEMA$1
      }, options));
    }
    function safeLoad(input, options) {
      return load(input, common$1.extend({
        schema: DEFAULT_SAFE_SCHEMA$1
      }, options));
    }
    loader$1.loadAll = loadAll;
    loader$1.load = load;
    loader$1.safeLoadAll = safeLoadAll;
    loader$1.safeLoad = safeLoad;

    var dumper$1 = {};

    /*eslint-disable no-use-before-define*/

    var common = common$6;
    var YAMLException = exception;
    var DEFAULT_FULL_SCHEMA = default_full;
    var DEFAULT_SAFE_SCHEMA = default_safe;
    var _toString = Object.prototype.toString;
    var _hasOwnProperty = Object.prototype.hasOwnProperty;
    var CHAR_TAB = 0x09; /* Tab */
    var CHAR_LINE_FEED = 0x0A; /* LF */
    var CHAR_CARRIAGE_RETURN = 0x0D; /* CR */
    var CHAR_SPACE = 0x20; /* Space */
    var CHAR_EXCLAMATION = 0x21; /* ! */
    var CHAR_DOUBLE_QUOTE = 0x22; /* " */
    var CHAR_SHARP = 0x23; /* # */
    var CHAR_PERCENT = 0x25; /* % */
    var CHAR_AMPERSAND = 0x26; /* & */
    var CHAR_SINGLE_QUOTE = 0x27; /* ' */
    var CHAR_ASTERISK = 0x2A; /* * */
    var CHAR_COMMA = 0x2C; /* , */
    var CHAR_MINUS = 0x2D; /* - */
    var CHAR_COLON = 0x3A; /* : */
    var CHAR_EQUALS = 0x3D; /* = */
    var CHAR_GREATER_THAN = 0x3E; /* > */
    var CHAR_QUESTION = 0x3F; /* ? */
    var CHAR_COMMERCIAL_AT = 0x40; /* @ */
    var CHAR_LEFT_SQUARE_BRACKET = 0x5B; /* [ */
    var CHAR_RIGHT_SQUARE_BRACKET = 0x5D; /* ] */
    var CHAR_GRAVE_ACCENT = 0x60; /* ` */
    var CHAR_LEFT_CURLY_BRACKET = 0x7B; /* { */
    var CHAR_VERTICAL_LINE = 0x7C; /* | */
    var CHAR_RIGHT_CURLY_BRACKET = 0x7D; /* } */

    var ESCAPE_SEQUENCES = {};
    ESCAPE_SEQUENCES[0x00] = '\\0';
    ESCAPE_SEQUENCES[0x07] = '\\a';
    ESCAPE_SEQUENCES[0x08] = '\\b';
    ESCAPE_SEQUENCES[0x09] = '\\t';
    ESCAPE_SEQUENCES[0x0A] = '\\n';
    ESCAPE_SEQUENCES[0x0B] = '\\v';
    ESCAPE_SEQUENCES[0x0C] = '\\f';
    ESCAPE_SEQUENCES[0x0D] = '\\r';
    ESCAPE_SEQUENCES[0x1B] = '\\e';
    ESCAPE_SEQUENCES[0x22] = '\\"';
    ESCAPE_SEQUENCES[0x5C] = '\\\\';
    ESCAPE_SEQUENCES[0x85] = '\\N';
    ESCAPE_SEQUENCES[0xA0] = '\\_';
    ESCAPE_SEQUENCES[0x2028] = '\\L';
    ESCAPE_SEQUENCES[0x2029] = '\\P';
    var DEPRECATED_BOOLEANS_SYNTAX = ['y', 'Y', 'yes', 'Yes', 'YES', 'on', 'On', 'ON', 'n', 'N', 'no', 'No', 'NO', 'off', 'Off', 'OFF'];
    function compileStyleMap(schema, map) {
      var result, keys, index, length, tag, style, type;
      if (map === null) return {};
      result = {};
      keys = Object.keys(map);
      for (index = 0, length = keys.length; index < length; index += 1) {
        tag = keys[index];
        style = String(map[tag]);
        if (tag.slice(0, 2) === '!!') {
          tag = 'tag:yaml.org,2002:' + tag.slice(2);
        }
        type = schema.compiledTypeMap['fallback'][tag];
        if (type && _hasOwnProperty.call(type.styleAliases, style)) {
          style = type.styleAliases[style];
        }
        result[tag] = style;
      }
      return result;
    }
    function encodeHex(character) {
      var string, handle, length;
      string = character.toString(16).toUpperCase();
      if (character <= 0xFF) {
        handle = 'x';
        length = 2;
      } else if (character <= 0xFFFF) {
        handle = 'u';
        length = 4;
      } else if (character <= 0xFFFFFFFF) {
        handle = 'U';
        length = 8;
      } else {
        throw new YAMLException('code point within a string may not be greater than 0xFFFFFFFF');
      }
      return '\\' + handle + common.repeat('0', length - string.length) + string;
    }
    function State(options) {
      this.schema = options['schema'] || DEFAULT_FULL_SCHEMA;
      this.indent = Math.max(1, options['indent'] || 2);
      this.noArrayIndent = options['noArrayIndent'] || false;
      this.skipInvalid = options['skipInvalid'] || false;
      this.flowLevel = common.isNothing(options['flowLevel']) ? -1 : options['flowLevel'];
      this.styleMap = compileStyleMap(this.schema, options['styles'] || null);
      this.sortKeys = options['sortKeys'] || false;
      this.lineWidth = options['lineWidth'] || 80;
      this.noRefs = options['noRefs'] || false;
      this.noCompatMode = options['noCompatMode'] || false;
      this.condenseFlow = options['condenseFlow'] || false;
      this.implicitTypes = this.schema.compiledImplicit;
      this.explicitTypes = this.schema.compiledExplicit;
      this.tag = null;
      this.result = '';
      this.duplicates = [];
      this.usedDuplicates = null;
    }

    // Indents every line in a string. Empty lines (\n only) are not indented.
    function indentString(string, spaces) {
      var ind = common.repeat(' ', spaces),
        position = 0,
        next = -1,
        result = '',
        line,
        length = string.length;
      while (position < length) {
        next = string.indexOf('\n', position);
        if (next === -1) {
          line = string.slice(position);
          position = length;
        } else {
          line = string.slice(position, next + 1);
          position = next + 1;
        }
        if (line.length && line !== '\n') result += ind;
        result += line;
      }
      return result;
    }
    function generateNextLine(state, level) {
      return '\n' + common.repeat(' ', state.indent * level);
    }
    function testImplicitResolving(state, str) {
      var index, length, type;
      for (index = 0, length = state.implicitTypes.length; index < length; index += 1) {
        type = state.implicitTypes[index];
        if (type.resolve(str)) {
          return true;
        }
      }
      return false;
    }

    // [33] s-white ::= s-space | s-tab
    function isWhitespace(c) {
      return c === CHAR_SPACE || c === CHAR_TAB;
    }

    // Returns true if the character can be printed without escaping.
    // From YAML 1.2: "any allowed characters known to be non-printable
    // should also be escaped. [However,] This isn’t mandatory"
    // Derived from nb-char - \t - #x85 - #xA0 - #x2028 - #x2029.
    function isPrintable(c) {
      return 0x00020 <= c && c <= 0x00007E || 0x000A1 <= c && c <= 0x00D7FF && c !== 0x2028 && c !== 0x2029 || 0x0E000 <= c && c <= 0x00FFFD && c !== 0xFEFF /* BOM */ || 0x10000 <= c && c <= 0x10FFFF;
    }

    // [34] ns-char ::= nb-char - s-white
    // [27] nb-char ::= c-printable - b-char - c-byte-order-mark
    // [26] b-char  ::= b-line-feed | b-carriage-return
    // [24] b-line-feed       ::=     #xA    /* LF */
    // [25] b-carriage-return ::=     #xD    /* CR */
    // [3]  c-byte-order-mark ::=     #xFEFF
    function isNsChar(c) {
      return isPrintable(c) && !isWhitespace(c)
      // byte-order-mark
      && c !== 0xFEFF
      // b-char
      && c !== CHAR_CARRIAGE_RETURN && c !== CHAR_LINE_FEED;
    }

    // Simplified test for values allowed after the first character in plain style.
    function isPlainSafe(c, prev) {
      // Uses a subset of nb-char - c-flow-indicator - ":" - "#"
      // where nb-char ::= c-printable - b-char - c-byte-order-mark.
      return isPrintable(c) && c !== 0xFEFF
      // - c-flow-indicator
      && c !== CHAR_COMMA && c !== CHAR_LEFT_SQUARE_BRACKET && c !== CHAR_RIGHT_SQUARE_BRACKET && c !== CHAR_LEFT_CURLY_BRACKET && c !== CHAR_RIGHT_CURLY_BRACKET
      // - ":" - "#"
      // /* An ns-char preceding */ "#"
      && c !== CHAR_COLON && (c !== CHAR_SHARP || prev && isNsChar(prev));
    }

    // Simplified test for values allowed as the first character in plain style.
    function isPlainSafeFirst(c) {
      // Uses a subset of ns-char - c-indicator
      // where ns-char = nb-char - s-white.
      return isPrintable(c) && c !== 0xFEFF && !isWhitespace(c) // - s-white
      // - (c-indicator ::=
      // “-” | “?” | “:” | “,” | “[” | “]” | “{” | “}”
      && c !== CHAR_MINUS && c !== CHAR_QUESTION && c !== CHAR_COLON && c !== CHAR_COMMA && c !== CHAR_LEFT_SQUARE_BRACKET && c !== CHAR_RIGHT_SQUARE_BRACKET && c !== CHAR_LEFT_CURLY_BRACKET && c !== CHAR_RIGHT_CURLY_BRACKET
      // | “#” | “&” | “*” | “!” | “|” | “=” | “>” | “'” | “"”
      && c !== CHAR_SHARP && c !== CHAR_AMPERSAND && c !== CHAR_ASTERISK && c !== CHAR_EXCLAMATION && c !== CHAR_VERTICAL_LINE && c !== CHAR_EQUALS && c !== CHAR_GREATER_THAN && c !== CHAR_SINGLE_QUOTE && c !== CHAR_DOUBLE_QUOTE
      // | “%” | “@” | “`”)
      && c !== CHAR_PERCENT && c !== CHAR_COMMERCIAL_AT && c !== CHAR_GRAVE_ACCENT;
    }

    // Determines whether block indentation indicator is required.
    function needIndentIndicator(string) {
      var leadingSpaceRe = /^\n* /;
      return leadingSpaceRe.test(string);
    }
    var STYLE_PLAIN = 1,
      STYLE_SINGLE = 2,
      STYLE_LITERAL = 3,
      STYLE_FOLDED = 4,
      STYLE_DOUBLE = 5;

    // Determines which scalar styles are possible and returns the preferred style.
    // lineWidth = -1 => no limit.
    // Pre-conditions: str.length > 0.
    // Post-conditions:
    //    STYLE_PLAIN or STYLE_SINGLE => no \n are in the string.
    //    STYLE_LITERAL => no lines are suitable for folding (or lineWidth is -1).
    //    STYLE_FOLDED => a line > lineWidth and can be folded (and lineWidth != -1).
    function chooseScalarStyle(string, singleLineOnly, indentPerLevel, lineWidth, testAmbiguousType) {
      var i;
      var char, prev_char;
      var hasLineBreak = false;
      var hasFoldableLine = false; // only checked if shouldTrackWidth
      var shouldTrackWidth = lineWidth !== -1;
      var previousLineBreak = -1; // count the first line correctly
      var plain = isPlainSafeFirst(string.charCodeAt(0)) && !isWhitespace(string.charCodeAt(string.length - 1));
      if (singleLineOnly) {
        // Case: no block styles.
        // Check for disallowed characters to rule out plain and single.
        for (i = 0; i < string.length; i++) {
          char = string.charCodeAt(i);
          if (!isPrintable(char)) {
            return STYLE_DOUBLE;
          }
          prev_char = i > 0 ? string.charCodeAt(i - 1) : null;
          plain = plain && isPlainSafe(char, prev_char);
        }
      } else {
        // Case: block styles permitted.
        for (i = 0; i < string.length; i++) {
          char = string.charCodeAt(i);
          if (char === CHAR_LINE_FEED) {
            hasLineBreak = true;
            // Check if any line can be folded.
            if (shouldTrackWidth) {
              hasFoldableLine = hasFoldableLine ||
              // Foldable line = too long, and not more-indented.
              i - previousLineBreak - 1 > lineWidth && string[previousLineBreak + 1] !== ' ';
              previousLineBreak = i;
            }
          } else if (!isPrintable(char)) {
            return STYLE_DOUBLE;
          }
          prev_char = i > 0 ? string.charCodeAt(i - 1) : null;
          plain = plain && isPlainSafe(char, prev_char);
        }
        // in case the end is missing a \n
        hasFoldableLine = hasFoldableLine || shouldTrackWidth && i - previousLineBreak - 1 > lineWidth && string[previousLineBreak + 1] !== ' ';
      }
      // Although every style can represent \n without escaping, prefer block styles
      // for multiline, since they're more readable and they don't add empty lines.
      // Also prefer folding a super-long line.
      if (!hasLineBreak && !hasFoldableLine) {
        // Strings interpretable as another type have to be quoted;
        // e.g. the string 'true' vs. the boolean true.
        return plain && !testAmbiguousType(string) ? STYLE_PLAIN : STYLE_SINGLE;
      }
      // Edge case: block indentation indicator can only have one digit.
      if (indentPerLevel > 9 && needIndentIndicator(string)) {
        return STYLE_DOUBLE;
      }
      // At this point we know block styles are valid.
      // Prefer literal style unless we want to fold.
      return hasFoldableLine ? STYLE_FOLDED : STYLE_LITERAL;
    }

    // Note: line breaking/folding is implemented for only the folded style.
    // NB. We drop the last trailing newline (if any) of a returned block scalar
    //  since the dumper adds its own newline. This always works:
    //    • No ending newline => unaffected; already using strip "-" chomping.
    //    • Ending newline    => removed then restored.
    //  Importantly, this keeps the "+" chomp indicator from gaining an extra line.
    function writeScalar(state, string, level, iskey) {
      state.dump = function () {
        if (string.length === 0) {
          return "''";
        }
        if (!state.noCompatMode && DEPRECATED_BOOLEANS_SYNTAX.indexOf(string) !== -1) {
          return "'" + string + "'";
        }
        var indent = state.indent * Math.max(1, level); // no 0-indent scalars
        // As indentation gets deeper, let the width decrease monotonically
        // to the lower bound min(state.lineWidth, 40).
        // Note that this implies
        //  state.lineWidth ≤ 40 + state.indent: width is fixed at the lower bound.
        //  state.lineWidth > 40 + state.indent: width decreases until the lower bound.
        // This behaves better than a constant minimum width which disallows narrower options,
        // or an indent threshold which causes the width to suddenly increase.
        var lineWidth = state.lineWidth === -1 ? -1 : Math.max(Math.min(state.lineWidth, 40), state.lineWidth - indent);

        // Without knowing if keys are implicit/explicit, assume implicit for safety.
        var singleLineOnly = iskey
        // No block styles in flow mode.
        || state.flowLevel > -1 && level >= state.flowLevel;
        function testAmbiguity(string) {
          return testImplicitResolving(state, string);
        }
        switch (chooseScalarStyle(string, singleLineOnly, state.indent, lineWidth, testAmbiguity)) {
          case STYLE_PLAIN:
            return string;
          case STYLE_SINGLE:
            return "'" + string.replace(/'/g, "''") + "'";
          case STYLE_LITERAL:
            return '|' + blockHeader(string, state.indent) + dropEndingNewline(indentString(string, indent));
          case STYLE_FOLDED:
            return '>' + blockHeader(string, state.indent) + dropEndingNewline(indentString(foldString(string, lineWidth), indent));
          case STYLE_DOUBLE:
            return '"' + escapeString(string) + '"';
          default:
            throw new YAMLException('impossible error: invalid scalar style');
        }
      }();
    }

    // Pre-conditions: string is valid for a block scalar, 1 <= indentPerLevel <= 9.
    function blockHeader(string, indentPerLevel) {
      var indentIndicator = needIndentIndicator(string) ? String(indentPerLevel) : '';

      // note the special case: the string '\n' counts as a "trailing" empty line.
      var clip = string[string.length - 1] === '\n';
      var keep = clip && (string[string.length - 2] === '\n' || string === '\n');
      var chomp = keep ? '+' : clip ? '' : '-';
      return indentIndicator + chomp + '\n';
    }

    // (See the note for writeScalar.)
    function dropEndingNewline(string) {
      return string[string.length - 1] === '\n' ? string.slice(0, -1) : string;
    }

    // Note: a long line without a suitable break point will exceed the width limit.
    // Pre-conditions: every char in str isPrintable, str.length > 0, width > 0.
    function foldString(string, width) {
      // In folded style, $k$ consecutive newlines output as $k+1$ newlines—
      // unless they're before or after a more-indented line, or at the very
      // beginning or end, in which case $k$ maps to $k$.
      // Therefore, parse each chunk as newline(s) followed by a content line.
      var lineRe = /(\n+)([^\n]*)/g;

      // first line (possibly an empty line)
      var result = function () {
        var nextLF = string.indexOf('\n');
        nextLF = nextLF !== -1 ? nextLF : string.length;
        lineRe.lastIndex = nextLF;
        return foldLine(string.slice(0, nextLF), width);
      }();
      // If we haven't reached the first content line yet, don't add an extra \n.
      var prevMoreIndented = string[0] === '\n' || string[0] === ' ';
      var moreIndented;

      // rest of the lines
      var match;
      while (match = lineRe.exec(string)) {
        var prefix = match[1],
          line = match[2];
        moreIndented = line[0] === ' ';
        result += prefix + (!prevMoreIndented && !moreIndented && line !== '' ? '\n' : '') + foldLine(line, width);
        prevMoreIndented = moreIndented;
      }
      return result;
    }

    // Greedy line breaking.
    // Picks the longest line under the limit each time,
    // otherwise settles for the shortest line over the limit.
    // NB. More-indented lines *cannot* be folded, as that would add an extra \n.
    function foldLine(line, width) {
      if (line === '' || line[0] === ' ') return line;

      // Since a more-indented line adds a \n, breaks can't be followed by a space.
      var breakRe = / [^ ]/g; // note: the match index will always be <= length-2.
      var match;
      // start is an inclusive index. end, curr, and next are exclusive.
      var start = 0,
        end,
        curr = 0,
        next = 0;
      var result = '';

      // Invariants: 0 <= start <= length-1.
      //   0 <= curr <= next <= max(0, length-2). curr - start <= width.
      // Inside the loop:
      //   A match implies length >= 2, so curr and next are <= length-2.
      while (match = breakRe.exec(line)) {
        next = match.index;
        // maintain invariant: curr - start <= width
        if (next - start > width) {
          end = curr > start ? curr : next; // derive end <= length-2
          result += '\n' + line.slice(start, end);
          // skip the space that was output as \n
          start = end + 1; // derive start <= length-1
        }

        curr = next;
      }

      // By the invariants, start <= length-1, so there is something left over.
      // It is either the whole string or a part starting from non-whitespace.
      result += '\n';
      // Insert a break if the remainder is too long and there is a break available.
      if (line.length - start > width && curr > start) {
        result += line.slice(start, curr) + '\n' + line.slice(curr + 1);
      } else {
        result += line.slice(start);
      }
      return result.slice(1); // drop extra \n joiner
    }

    // Escapes a double-quoted string.
    function escapeString(string) {
      var result = '';
      var char, nextChar;
      var escapeSeq;
      for (var i = 0; i < string.length; i++) {
        char = string.charCodeAt(i);
        // Check for surrogate pairs (reference Unicode 3.0 section "3.7 Surrogates").
        if (char >= 0xD800 && char <= 0xDBFF /* high surrogate */) {
          nextChar = string.charCodeAt(i + 1);
          if (nextChar >= 0xDC00 && nextChar <= 0xDFFF /* low surrogate */) {
            // Combine the surrogate pair and store it escaped.
            result += encodeHex((char - 0xD800) * 0x400 + nextChar - 0xDC00 + 0x10000);
            // Advance index one extra since we already used that char here.
            i++;
            continue;
          }
        }
        escapeSeq = ESCAPE_SEQUENCES[char];
        result += !escapeSeq && isPrintable(char) ? string[i] : escapeSeq || encodeHex(char);
      }
      return result;
    }
    function writeFlowSequence(state, level, object) {
      var _result = '',
        _tag = state.tag,
        index,
        length;
      for (index = 0, length = object.length; index < length; index += 1) {
        // Write only valid elements.
        if (writeNode(state, level, object[index], false, false)) {
          if (index !== 0) _result += ',' + (!state.condenseFlow ? ' ' : '');
          _result += state.dump;
        }
      }
      state.tag = _tag;
      state.dump = '[' + _result + ']';
    }
    function writeBlockSequence(state, level, object, compact) {
      var _result = '',
        _tag = state.tag,
        index,
        length;
      for (index = 0, length = object.length; index < length; index += 1) {
        // Write only valid elements.
        if (writeNode(state, level + 1, object[index], true, true)) {
          if (!compact || index !== 0) {
            _result += generateNextLine(state, level);
          }
          if (state.dump && CHAR_LINE_FEED === state.dump.charCodeAt(0)) {
            _result += '-';
          } else {
            _result += '- ';
          }
          _result += state.dump;
        }
      }
      state.tag = _tag;
      state.dump = _result || '[]'; // Empty sequence if no valid values.
    }

    function writeFlowMapping(state, level, object) {
      var _result = '',
        _tag = state.tag,
        objectKeyList = Object.keys(object),
        index,
        length,
        objectKey,
        objectValue,
        pairBuffer;
      for (index = 0, length = objectKeyList.length; index < length; index += 1) {
        pairBuffer = '';
        if (index !== 0) pairBuffer += ', ';
        if (state.condenseFlow) pairBuffer += '"';
        objectKey = objectKeyList[index];
        objectValue = object[objectKey];
        if (!writeNode(state, level, objectKey, false, false)) {
          continue; // Skip this pair because of invalid key;
        }

        if (state.dump.length > 1024) pairBuffer += '? ';
        pairBuffer += state.dump + (state.condenseFlow ? '"' : '') + ':' + (state.condenseFlow ? '' : ' ');
        if (!writeNode(state, level, objectValue, false, false)) {
          continue; // Skip this pair because of invalid value.
        }

        pairBuffer += state.dump;

        // Both key and value are valid.
        _result += pairBuffer;
      }
      state.tag = _tag;
      state.dump = '{' + _result + '}';
    }
    function writeBlockMapping(state, level, object, compact) {
      var _result = '',
        _tag = state.tag,
        objectKeyList = Object.keys(object),
        index,
        length,
        objectKey,
        objectValue,
        explicitPair,
        pairBuffer;

      // Allow sorting keys so that the output file is deterministic
      if (state.sortKeys === true) {
        // Default sorting
        objectKeyList.sort();
      } else if (typeof state.sortKeys === 'function') {
        // Custom sort function
        objectKeyList.sort(state.sortKeys);
      } else if (state.sortKeys) {
        // Something is wrong
        throw new YAMLException('sortKeys must be a boolean or a function');
      }
      for (index = 0, length = objectKeyList.length; index < length; index += 1) {
        pairBuffer = '';
        if (!compact || index !== 0) {
          pairBuffer += generateNextLine(state, level);
        }
        objectKey = objectKeyList[index];
        objectValue = object[objectKey];
        if (!writeNode(state, level + 1, objectKey, true, true, true)) {
          continue; // Skip this pair because of invalid key.
        }

        explicitPair = state.tag !== null && state.tag !== '?' || state.dump && state.dump.length > 1024;
        if (explicitPair) {
          if (state.dump && CHAR_LINE_FEED === state.dump.charCodeAt(0)) {
            pairBuffer += '?';
          } else {
            pairBuffer += '? ';
          }
        }
        pairBuffer += state.dump;
        if (explicitPair) {
          pairBuffer += generateNextLine(state, level);
        }
        if (!writeNode(state, level + 1, objectValue, true, explicitPair)) {
          continue; // Skip this pair because of invalid value.
        }

        if (state.dump && CHAR_LINE_FEED === state.dump.charCodeAt(0)) {
          pairBuffer += ':';
        } else {
          pairBuffer += ': ';
        }
        pairBuffer += state.dump;

        // Both key and value are valid.
        _result += pairBuffer;
      }
      state.tag = _tag;
      state.dump = _result || '{}'; // Empty mapping if no valid pairs.
    }

    function detectType(state, object, explicit) {
      var _result, typeList, index, length, type, style;
      typeList = explicit ? state.explicitTypes : state.implicitTypes;
      for (index = 0, length = typeList.length; index < length; index += 1) {
        type = typeList[index];
        if ((type.instanceOf || type.predicate) && (!type.instanceOf || typeof object === 'object' && object instanceof type.instanceOf) && (!type.predicate || type.predicate(object))) {
          state.tag = explicit ? type.tag : '?';
          if (type.represent) {
            style = state.styleMap[type.tag] || type.defaultStyle;
            if (_toString.call(type.represent) === '[object Function]') {
              _result = type.represent(object, style);
            } else if (_hasOwnProperty.call(type.represent, style)) {
              _result = type.represent[style](object, style);
            } else {
              throw new YAMLException('!<' + type.tag + '> tag resolver accepts not "' + style + '" style');
            }
            state.dump = _result;
          }
          return true;
        }
      }
      return false;
    }

    // Serializes `object` and writes it to global `result`.
    // Returns true on success, or false on invalid object.
    //
    function writeNode(state, level, object, block, compact, iskey) {
      state.tag = null;
      state.dump = object;
      if (!detectType(state, object, false)) {
        detectType(state, object, true);
      }
      var type = _toString.call(state.dump);
      if (block) {
        block = state.flowLevel < 0 || state.flowLevel > level;
      }
      var objectOrArray = type === '[object Object]' || type === '[object Array]',
        duplicateIndex,
        duplicate;
      if (objectOrArray) {
        duplicateIndex = state.duplicates.indexOf(object);
        duplicate = duplicateIndex !== -1;
      }
      if (state.tag !== null && state.tag !== '?' || duplicate || state.indent !== 2 && level > 0) {
        compact = false;
      }
      if (duplicate && state.usedDuplicates[duplicateIndex]) {
        state.dump = '*ref_' + duplicateIndex;
      } else {
        if (objectOrArray && duplicate && !state.usedDuplicates[duplicateIndex]) {
          state.usedDuplicates[duplicateIndex] = true;
        }
        if (type === '[object Object]') {
          if (block && Object.keys(state.dump).length !== 0) {
            writeBlockMapping(state, level, state.dump, compact);
            if (duplicate) {
              state.dump = '&ref_' + duplicateIndex + state.dump;
            }
          } else {
            writeFlowMapping(state, level, state.dump);
            if (duplicate) {
              state.dump = '&ref_' + duplicateIndex + ' ' + state.dump;
            }
          }
        } else if (type === '[object Array]') {
          var arrayLevel = state.noArrayIndent && level > 0 ? level - 1 : level;
          if (block && state.dump.length !== 0) {
            writeBlockSequence(state, arrayLevel, state.dump, compact);
            if (duplicate) {
              state.dump = '&ref_' + duplicateIndex + state.dump;
            }
          } else {
            writeFlowSequence(state, arrayLevel, state.dump);
            if (duplicate) {
              state.dump = '&ref_' + duplicateIndex + ' ' + state.dump;
            }
          }
        } else if (type === '[object String]') {
          if (state.tag !== '?') {
            writeScalar(state, state.dump, level, iskey);
          }
        } else {
          if (state.skipInvalid) return false;
          throw new YAMLException('unacceptable kind of an object to dump ' + type);
        }
        if (state.tag !== null && state.tag !== '?') {
          state.dump = '!<' + state.tag + '> ' + state.dump;
        }
      }
      return true;
    }
    function getDuplicateReferences(object, state) {
      var objects = [],
        duplicatesIndexes = [],
        index,
        length;
      inspectNode(object, objects, duplicatesIndexes);
      for (index = 0, length = duplicatesIndexes.length; index < length; index += 1) {
        state.duplicates.push(objects[duplicatesIndexes[index]]);
      }
      state.usedDuplicates = new Array(length);
    }
    function inspectNode(object, objects, duplicatesIndexes) {
      var objectKeyList, index, length;
      if (object !== null && typeof object === 'object') {
        index = objects.indexOf(object);
        if (index !== -1) {
          if (duplicatesIndexes.indexOf(index) === -1) {
            duplicatesIndexes.push(index);
          }
        } else {
          objects.push(object);
          if (Array.isArray(object)) {
            for (index = 0, length = object.length; index < length; index += 1) {
              inspectNode(object[index], objects, duplicatesIndexes);
            }
          } else {
            objectKeyList = Object.keys(object);
            for (index = 0, length = objectKeyList.length; index < length; index += 1) {
              inspectNode(object[objectKeyList[index]], objects, duplicatesIndexes);
            }
          }
        }
      }
    }
    function dump(input, options) {
      options = options || {};
      var state = new State(options);
      if (!state.noRefs) getDuplicateReferences(input, state);
      if (writeNode(state, 0, input, true, true)) return state.dump + '\n';
      return '';
    }
    function safeDump(input, options) {
      return dump(input, common.extend({
        schema: DEFAULT_SAFE_SCHEMA
      }, options));
    }
    dumper$1.dump = dump;
    dumper$1.safeDump = safeDump;

    var loader = loader$1;
    var dumper = dumper$1;
    function deprecated(name) {
      return function () {
        throw new Error('Function ' + name + ' is deprecated and cannot be used.');
      };
    }
    jsYaml$2.Type = type;
    jsYaml$2.Schema = schema;
    jsYaml$2.FAILSAFE_SCHEMA = failsafe;
    jsYaml$2.JSON_SCHEMA = json;
    jsYaml$2.CORE_SCHEMA = core;
    jsYaml$2.DEFAULT_SAFE_SCHEMA = default_safe;
    jsYaml$2.DEFAULT_FULL_SCHEMA = default_full;
    jsYaml$2.load = loader.load;
    jsYaml$2.loadAll = loader.loadAll;
    jsYaml$2.safeLoad = loader.safeLoad;
    jsYaml$2.safeLoadAll = loader.safeLoadAll;
    jsYaml$2.dump = dumper.dump;
    jsYaml$2.safeDump = dumper.safeDump;
    jsYaml$2.YAMLException = exception;

    // Deprecated schema names from JS-YAML 2.0.x
    jsYaml$2.MINIMAL_SCHEMA = failsafe;
    jsYaml$2.SAFE_SCHEMA = default_safe;
    jsYaml$2.DEFAULT_SCHEMA = default_full;

    // Deprecated functions from JS-YAML 1.x.x
    jsYaml$2.scan = deprecated('scan');
    jsYaml$2.parse = deprecated('parse');
    jsYaml$2.compose = deprecated('compose');
    jsYaml$2.addConstructor = deprecated('addConstructor');

    var yaml = jsYaml$2;
    var jsYaml = yaml;
    var jsYaml$1 = /*@__PURE__*/getDefaultExportFromCjs$1(jsYaml);

    function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); enumerableOnly && (symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; }
    function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? ownKeys(Object(source), !0).forEach(function (key) { _defineProperty(target, key, source[key]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } return target; }

    /**
     * Redirect - object used to redirect some requests
     * e.g.
     * {
     *      title: 1x1-transparent.gif
     *      comment: http://probablyprogramming.com/2009/03/15/the-tiniest-gif-ever
     *      contentType: image/gif;base64
     *      content: R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==
     * }
     *
     * @typedef {object} Redirect
     * @property {string} title resource name
     * @property {string} comment resource description
     * @property {string} content encoded resource content
     * @property {string} contentType MIME type
     * @property {boolean} [isBlocking] e.g click2load redirect
     * @property {string} [sha] hash
     */

    class Redirects {
      /**
       * Converts rawYaml into JS object with sources titles used as keys
       *
       * @param {string} rawYaml
       * @returns {Redirect} - return object with titles in the keys and RedirectSources
       * in the values
       */
      constructor(rawYaml) {
        try {
          var arrOfRedirects = jsYaml$1.safeLoad(rawYaml);
          this.redirects = arrOfRedirects.reduce(function (acc, redirect) {
            return _objectSpread(_objectSpread({}, acc), {}, {
              [redirect.title]: redirect
            });
          }, {});
        } catch (e) {
          // eslint-disable-next-line no-console
          console.log("Was unable to load YAML into JS due to: ".concat(e.message));
          throw e;
        }
      }

      /**
       * Returns redirect source object
       *
       * @param {string} title
       * @returns {Redirect|undefined} Found redirect source object, or `undefined` if not found.
       */
      getRedirect(title) {
        var _this = this;
        if (Object.prototype.hasOwnProperty.call(this.redirects, title)) {
          return this.redirects[title];
        }

        // look title among aliases
        var values = Object.keys(this.redirects).map(function (key) {
          return _this.redirects[key];
        });
        return values.find(function (redirect) {
          var aliases = redirect.aliases;
          if (!aliases) {
            return false;
          }
          return aliases.includes(title);
        });
      }

      /**
       * Checks if redirect is blocking like click2load.html
       *
       * @param {string} title Title of the redirect.
       * @returns {boolean} True if redirect is blocking otherwise returns `false` even if redirect name is
       * unknown.
       */
      isBlocking(title) {
        var redirect = this.redirects[title];
        if (redirect) {
          return !!redirect.isBlocking;
        }
        return false;
      }
    }

    var redirectsMap = {
      "1x1-transparent.gif": "1x1-transparent.gif",
      "1x1.gif": "1x1-transparent.gif",
      "1x1-transparent-gif": "1x1-transparent.gif",
      "2x2-transparent.png": "2x2-transparent.png",
      "2x2.png": "2x2-transparent.png",
      "2x2-transparent-png": "2x2-transparent.png",
      "3x2-transparent.png": "3x2-transparent.png",
      "3x2.png": "3x2-transparent.png",
      "3x2-transparent-png": "3x2-transparent.png",
      "32x32-transparent.png": "32x32-transparent.png",
      "32x32.png": "32x32-transparent.png",
      "32x32-transparent-png": "32x32-transparent.png",
      noopframe: "noopframe.html",
      "noop.html": "noopframe.html",
      "blank-html": "noopframe.html",
      noopcss: "noopcss.css",
      "noop.css": "noopcss.css",
      "blank-css": "noopcss.css",
      noopjs: "noopjs.js",
      "noop.js": "noopjs.js",
      "blank-js": "noopjs.js",
      noopjson: "noopjson.json",
      "noop.json": "noopjson.json",
      nooptext: "nooptext.js",
      "noop.txt": "nooptext.js",
      "blank-text": "nooptext.js",
      empty: "nooptext.js",
      "noopvmap-1.0": "noopvmap01.xml",
      "noop-vmap1.xml": "noopvmap01.xml",
      "noop-vmap1.0.xml": "noopvmap01.xml",
      "noopvast-2.0": "noopvast02.xml",
      "noop-vast2.xml": "noopvast02.xml",
      "noopvast-3.0": "noopvast03.xml",
      "noop-vast3.xml": "noopvast03.xml",
      "noopvast-4.0": "noopvast04.xml",
      "noop-vast4.xml": "noopvast04.xml",
      "noopmp3-0.1s": "noopmp3.mp3",
      "blank-mp3": "noopmp3.mp3",
      "noopmp4-1s": "noopmp4.mp4",
      "noop-1s.mp4": "noopmp4.mp4",
      "blank-mp4": "noopmp4.mp4",
      "click2load.html": "click2load.html",
      "ubo-click2load.html": "click2load.html",
      "amazon-apstag": "amazon-apstag.js",
      "ubo-amazon_apstag.js": "amazon-apstag.js",
      "amazon_apstag.js": "amazon-apstag.js",
      "ati-smarttag": "ati-smarttag.js",
      "didomi-loader": "didomi-loader.js",
      fingerprintjs2: "fingerprintjs2.js",
      "ubo-fingerprint2.js": "fingerprintjs2.js",
      "fingerprint2.js": "fingerprintjs2.js",
      fingerprintjs3: "fingerprintjs3.js",
      "ubo-fingerprint3.js": "fingerprintjs3.js",
      "fingerprint3.js": "fingerprintjs3.js",
      gemius: "gemius.js",
      "google-analytics-ga": "google-analytics-ga.js",
      "ubo-google-analytics_ga.js": "google-analytics-ga.js",
      "google-analytics_ga.js": "google-analytics-ga.js",
      "google-analytics": "google-analytics.js",
      "ubo-google-analytics_analytics.js": "google-analytics.js",
      "google-analytics_analytics.js": "google-analytics.js",
      "googletagmanager-gtm": "google-analytics.js",
      "ubo-googletagmanager_gtm.js": "google-analytics.js",
      "googletagmanager_gtm.js": "google-analytics.js",
      "google-ima3": "google-ima3.js",
      "ubo-google-ima.js": "google-ima3.js",
      "google-ima.js": "google-ima3.js",
      "googlesyndication-adsbygoogle": "googlesyndication-adsbygoogle.js",
      "ubo-googlesyndication_adsbygoogle.js": "googlesyndication-adsbygoogle.js",
      "googlesyndication_adsbygoogle.js": "googlesyndication-adsbygoogle.js",
      "googletagservices-gpt": "googletagservices-gpt.js",
      "ubo-googletagservices_gpt.js": "googletagservices-gpt.js",
      "googletagservices_gpt.js": "googletagservices-gpt.js",
      matomo: "matomo.js",
      "metrika-yandex-tag": "metrika-yandex-tag.js",
      "metrika-yandex-watch": "metrika-yandex-watch.js",
      "naver-wcslog": "naver-wcslog.js",
      noeval: "noeval.js",
      "noeval.js": "noeval.js",
      "silent-noeval.js": "noeval.js",
      "ubo-noeval.js": "noeval.js",
      "ubo-silent-noeval.js": "noeval.js",
      "ubo-noeval": "noeval.js",
      "ubo-silent-noeval": "noeval.js",
      "pardot-1.0": "pardot-1.0.js",
      "prebid-ads": "prebid-ads.js",
      "ubo-prebid-ads.js": "prebid-ads.js",
      "prebid-ads.js": "prebid-ads.js",
      prebid: "prebid.js",
      "prevent-bab": "prevent-bab.js",
      "nobab.js": "prevent-bab.js",
      "ubo-nobab.js": "prevent-bab.js",
      "bab-defuser.js": "prevent-bab.js",
      "ubo-bab-defuser.js": "prevent-bab.js",
      "ubo-nobab": "prevent-bab.js",
      "ubo-bab-defuser": "prevent-bab.js",
      "prevent-bab2": "prevent-bab2.js",
      "nobab2.js": "prevent-bab2.js",
      "prevent-fab-3.2.0": "prevent-fab-3.2.0.js",
      "nofab.js": "prevent-fab-3.2.0.js",
      "ubo-nofab.js": "prevent-fab-3.2.0.js",
      "fuckadblock.js-3.2.0": "prevent-fab-3.2.0.js",
      "ubo-fuckadblock.js-3.2.0": "prevent-fab-3.2.0.js",
      "ubo-nofab": "prevent-fab-3.2.0.js",
      "prevent-popads-net": "prevent-popads-net.js",
      "popads.net.js": "prevent-popads-net.js",
      "ubo-popads.net.js": "prevent-popads-net.js",
      "ubo-popads.net": "prevent-popads-net.js",
      "scorecardresearch-beacon": "scorecardresearch-beacon.js",
      "ubo-scorecardresearch_beacon.js": "scorecardresearch-beacon.js",
      "scorecardresearch_beacon.js": "scorecardresearch-beacon.js",
      "set-popads-dummy": "set-popads-dummy.js",
      "popads-dummy.js": "set-popads-dummy.js",
      "ubo-popads-dummy.js": "set-popads-dummy.js",
      "ubo-popads-dummy": "set-popads-dummy.js"
    };

    /**
     * Finds redirect resource by it's name
     *
     * @param {string} name - redirect name
     * @returns {Function}
     */
    var getRedirectByName = function getRedirectByName(name) {
      var redirects = Object.keys(redirectsList).map(function (key) {
        return redirectsList[key];
      });
      return redirects.find(function (r) {
        return r.names && r.names.includes(name);
      });
    };

    /**
     * @typedef {object} Source - redirect properties
     * @property {string} name redirect name
     * @property {Array<string>} args Arguments for redirect function
     * @property {'extension'|'test'} [engine] -
     * Defines the final form of redirect string presentation
     * @property {boolean} [verbose] flag to enable printing to console debug information
     */

    /**
     * Returns redirect code by param
     *
     * @param {Source} source
     * @returns {string} redirect code
     */
    var getRedirectCode = function getRedirectCode(source) {
      var redirect = getRedirectByName(source.name);
      var result = attachDependencies(redirect);
      result = addCall(redirect, result);

      // redirect code for different sources is checked in tests
      // so it should be just a code without any source and props passed
      result = source.engine === 'test' ? wrapInNonameFunc(result) : passSourceAndProps(source, result, true);
      return result;
    };
    var getRedirectFilename = function getRedirectFilename(name) {
      return redirectsMap[name];
    };
    var redirects = {
      Redirects,
      getRedirectFilename,
      getCode: getRedirectCode,
      isAdgRedirectRule: validator.isAdgRedirectRule,
      isValidAdgRedirectRule: validator.isValidAdgRedirectRule,
      isRedirectResourceCompatibleWithAdg: validator.isRedirectResourceCompatibleWithAdg,
      isAdgRedirectCompatibleWithUbo: validator.isAdgRedirectCompatibleWithUbo,
      isUboRedirectCompatibleWithAdg: validator.isUboRedirectCompatibleWithAdg,
      isAbpRedirectCompatibleWithAdg: validator.isAbpRedirectCompatibleWithAdg,
      convertUboRedirectToAdg,
      convertAbpRedirectToAdg,
      convertRedirectToAdg,
      convertRedirectNameToAdg,
      convertAdgRedirectToUbo
    };

    var version = "1.12.1";

    function AmazonApstag(source,args){var flag="done";var uniqueIdentifier=source.uniqueId+source.name+"_"+(Array.isArray(args)?args.join("_"):"");if(source.uniqueId){if(Window.prototype.toString[uniqueIdentifier]===flag){return;}}function AmazonApstag(source){var apstagWrapper={fetchBids(a,b){if(typeof b==="function"){b([]);}},init:noopFunc,setDisplayBids:noopFunc,targetingKeys:noopFunc};window.apstag=apstagWrapper;hit(source);}function hit(source){var ADGUARD_PREFIX="[AdGuard]";if(!source.verbose){return;}try{var trace=console.trace.bind(console);var label="".concat(ADGUARD_PREFIX," ");if(source.engine==="corelibs"){label+=source.ruleText;}else {if(source.domainName){label+="".concat(source.domainName);}if(source.args){label+="#%#//scriptlet('".concat(source.name,"', '").concat(source.args.join("', '"),"')");}else {label+="#%#//scriptlet('".concat(source.name,"')");}}if(trace){trace(label);}}catch(e){}if(typeof window.__debug==="function"){window.__debug(source);}}function noopFunc(){}var updatedArgs=args?[].concat(source).concat(args):[source];try{AmazonApstag.apply(this,updatedArgs);if(source.uniqueId){Object.defineProperty(Window.prototype.toString,uniqueIdentifier,{value:flag,enumerable:false,writable:false,configurable:false});}}catch(e){console.log(e);}}function DidomiLoader(source,args){var flag="done";var uniqueIdentifier=source.uniqueId+source.name+"_"+(Array.isArray(args)?args.join("_"):"");if(source.uniqueId){if(Window.prototype.toString[uniqueIdentifier]===flag){return;}}function DidomiLoader(source){function UserConsentStatusForVendorSubscribe(){}UserConsentStatusForVendorSubscribe.prototype.filter=function(){return new UserConsentStatusForVendorSubscribe();};UserConsentStatusForVendorSubscribe.prototype.subscribe=noopFunc;function UserConsentStatusForVendor(){}UserConsentStatusForVendor.prototype.first=function(){return new UserConsentStatusForVendorSubscribe();};UserConsentStatusForVendor.prototype.filter=function(){return new UserConsentStatusForVendorSubscribe();};UserConsentStatusForVendor.prototype.subscribe=noopFunc;var DidomiWrapper={isConsentRequired:falseFunc,getUserConsentStatusForPurpose:trueFunc,getUserConsentStatus:trueFunc,getUserStatus:noopFunc,getRequiredPurposes:noopArray,getUserConsentStatusForVendor:trueFunc,Purposes:{Cookies:"cookies"},notice:{configure:noopFunc,hide:noopFunc,isVisible:falseFunc,show:noopFunc,showDataProcessing:trueFunc},isUserConsentStatusPartial:falseFunc,on(){return {actions:{},emitter:{},services:{},store:{}};},shouldConsentBeCollected:falseFunc,getUserConsentStatusForAll:noopFunc,getObservableOnUserConsentStatusForVendor(){return new UserConsentStatusForVendor();}};window.Didomi=DidomiWrapper;var didomiStateWrapper={didomiExperimentId:"",didomiExperimentUserGroup:"",didomiGDPRApplies:1,didomiIABConsent:"",didomiPurposesConsent:"",didomiPurposesConsentDenied:"",didomiPurposesConsentUnknown:"",didomiVendorsConsent:"",didomiVendorsConsentDenied:"",didomiVendorsConsentUnknown:"",didomiVendorsRawConsent:"",didomiVendorsRawConsentDenied:"",didomiVendorsRawConsentUnknown:""};window.didomiState=didomiStateWrapper;var tcData={eventStatus:"tcloaded",gdprApplies:false,listenerId:noopFunc,vendor:{consents:[]},purpose:{consents:[]}};var __tcfapiWrapper=function __tcfapiWrapper(command,version,callback){if(typeof callback!=="function"||command==="removeEventListener"){return;}callback(tcData,true);};window.__tcfapi=__tcfapiWrapper;var didomiEventListenersWrapper={stub:true,push:noopFunc};window.didomiEventListeners=didomiEventListenersWrapper;var didomiOnReadyWrapper={stub:true,push(arg){if(typeof arg!=="function"){return;}if(document.readyState!=="complete"){window.addEventListener("load",function(){setTimeout(arg(window.Didomi));});}else {setTimeout(arg(window.Didomi));}}};window.didomiOnReady=window.didomiOnReady||didomiOnReadyWrapper;if(Array.isArray(window.didomiOnReady)){window.didomiOnReady.forEach(function(arg){if(typeof arg==="function"){try{setTimeout(arg(window.Didomi));}catch(e){}}});}hit(source);}function hit(source){var ADGUARD_PREFIX="[AdGuard]";if(!source.verbose){return;}try{var trace=console.trace.bind(console);var label="".concat(ADGUARD_PREFIX," ");if(source.engine==="corelibs"){label+=source.ruleText;}else {if(source.domainName){label+="".concat(source.domainName);}if(source.args){label+="#%#//scriptlet('".concat(source.name,"', '").concat(source.args.join("', '"),"')");}else {label+="#%#//scriptlet('".concat(source.name,"')");}}if(trace){trace(label);}}catch(e){}if(typeof window.__debug==="function"){window.__debug(source);}}function noopFunc(){}function noopArray(){return [];}function trueFunc(){return true;}function falseFunc(){return false;}var updatedArgs=args?[].concat(source).concat(args):[source];try{DidomiLoader.apply(this,updatedArgs);if(source.uniqueId){Object.defineProperty(Window.prototype.toString,uniqueIdentifier,{value:flag,enumerable:false,writable:false,configurable:false});}}catch(e){console.log(e);}}function Fingerprintjs2(source,args){var flag="done";var uniqueIdentifier=source.uniqueId+source.name+"_"+(Array.isArray(args)?args.join("_"):"");if(source.uniqueId){if(Window.prototype.toString[uniqueIdentifier]===flag){return;}}function Fingerprintjs2(source){var browserId="";for(var i=0;i<8;i+=1){browserId+=(Math.random()*65536+4096).toString(16).slice(-4);}var Fingerprint2=function Fingerprint2(){};Fingerprint2.get=function(options,callback){if(!callback){callback=options;}setTimeout(function(){if(callback){callback(browserId,[]);}},1);};Fingerprint2.prototype={get:Fingerprint2.get};window.Fingerprint2=Fingerprint2;hit(source);}function hit(source){var ADGUARD_PREFIX="[AdGuard]";if(!source.verbose){return;}try{var trace=console.trace.bind(console);var label="".concat(ADGUARD_PREFIX," ");if(source.engine==="corelibs"){label+=source.ruleText;}else {if(source.domainName){label+="".concat(source.domainName);}if(source.args){label+="#%#//scriptlet('".concat(source.name,"', '").concat(source.args.join("', '"),"')");}else {label+="#%#//scriptlet('".concat(source.name,"')");}}if(trace){trace(label);}}catch(e){}if(typeof window.__debug==="function"){window.__debug(source);}}var updatedArgs=args?[].concat(source).concat(args):[source];try{Fingerprintjs2.apply(this,updatedArgs);if(source.uniqueId){Object.defineProperty(Window.prototype.toString,uniqueIdentifier,{value:flag,enumerable:false,writable:false,configurable:false});}}catch(e){console.log(e);}}function Fingerprintjs3(source,args){var flag="done";var uniqueIdentifier=source.uniqueId+source.name+"_"+(Array.isArray(args)?args.join("_"):"");if(source.uniqueId){if(Window.prototype.toString[uniqueIdentifier]===flag){return;}}function Fingerprintjs3(source){var visitorId=function(){var id="";for(var i=0;i<8;i+=1){id+=(Math.random()*65536+4096).toString(16).slice(-4);}return id;}();var FingerprintJS=function FingerprintJS(){};FingerprintJS.prototype={load(){return Promise.resolve(new FingerprintJS());},get(){return Promise.resolve({visitorId:visitorId});},hashComponents:noopStr};window.FingerprintJS=new FingerprintJS();hit(source);}function hit(source){var ADGUARD_PREFIX="[AdGuard]";if(!source.verbose){return;}try{var trace=console.trace.bind(console);var label="".concat(ADGUARD_PREFIX," ");if(source.engine==="corelibs"){label+=source.ruleText;}else {if(source.domainName){label+="".concat(source.domainName);}if(source.args){label+="#%#//scriptlet('".concat(source.name,"', '").concat(source.args.join("', '"),"')");}else {label+="#%#//scriptlet('".concat(source.name,"')");}}if(trace){trace(label);}}catch(e){}if(typeof window.__debug==="function"){window.__debug(source);}}function noopStr(){return "";}var updatedArgs=args?[].concat(source).concat(args):[source];try{Fingerprintjs3.apply(this,updatedArgs);if(source.uniqueId){Object.defineProperty(Window.prototype.toString,uniqueIdentifier,{value:flag,enumerable:false,writable:false,configurable:false});}}catch(e){console.log(e);}}function Gemius(source,args){var flag="done";var uniqueIdentifier=source.uniqueId+source.name+"_"+(Array.isArray(args)?args.join("_"):"");if(source.uniqueId){if(Window.prototype.toString[uniqueIdentifier]===flag){return;}}function Gemius(source){var GemiusPlayer=function GemiusPlayer(){};GemiusPlayer.prototype={setVideoObject:noopFunc,newProgram:noopFunc,programEvent:noopFunc,newAd:noopFunc,adEvent:noopFunc};window.GemiusPlayer=GemiusPlayer;hit(source);}function hit(source){var ADGUARD_PREFIX="[AdGuard]";if(!source.verbose){return;}try{var trace=console.trace.bind(console);var label="".concat(ADGUARD_PREFIX," ");if(source.engine==="corelibs"){label+=source.ruleText;}else {if(source.domainName){label+="".concat(source.domainName);}if(source.args){label+="#%#//scriptlet('".concat(source.name,"', '").concat(source.args.join("', '"),"')");}else {label+="#%#//scriptlet('".concat(source.name,"')");}}if(trace){trace(label);}}catch(e){}if(typeof window.__debug==="function"){window.__debug(source);}}function noopFunc(){}var updatedArgs=args?[].concat(source).concat(args):[source];try{Gemius.apply(this,updatedArgs);if(source.uniqueId){Object.defineProperty(Window.prototype.toString,uniqueIdentifier,{value:flag,enumerable:false,writable:false,configurable:false});}}catch(e){console.log(e);}}function GoogleAnalytics(source,args){var flag="done";var uniqueIdentifier=source.uniqueId+source.name+"_"+(Array.isArray(args)?args.join("_"):"");if(source.uniqueId){if(Window.prototype.toString[uniqueIdentifier]===flag){return;}}function GoogleAnalytics(source){var _window$googleAnalyti;var Tracker=function Tracker(){};var proto=Tracker.prototype;proto.get=noopFunc;proto.set=noopFunc;proto.send=noopFunc;var googleAnalyticsName=window.GoogleAnalyticsObject||"ga";var queue=(_window$googleAnalyti=window[googleAnalyticsName])===null||_window$googleAnalyti===void 0?void 0:_window$googleAnalyti.q;function ga(a){var len=arguments.length;if(len===0){return;}var lastArg=arguments[len-1];var replacer;if(lastArg instanceof Object&&lastArg!==null&&typeof lastArg.hitCallback==="function"){replacer=lastArg.hitCallback;}else if(typeof lastArg==="function"){replacer=function replacer(){lastArg(ga.create());};}try{setTimeout(replacer,1);}catch(ex){}}ga.create=function(){return new Tracker();};ga.getByName=function(){return new Tracker();};ga.getAll=function(){return [new Tracker()];};ga.remove=noopFunc;ga.loaded=true;window[googleAnalyticsName]=ga;if(Array.isArray(queue)){var push=function push(arg){ga(...arg);};queue.push=push;queue.forEach(push);}var _window=window,dataLayer=_window.dataLayer,google_optimize=_window.google_optimize;if(dataLayer instanceof Object===false){return;}if(dataLayer.hide instanceof Object&&typeof dataLayer.hide.end==="function"){dataLayer.hide.end();}var handleCallback=function handleCallback(dataObj,funcName){if(dataObj&&typeof dataObj[funcName]==="function"){setTimeout(dataObj[funcName]);}};if(typeof dataLayer.push==="function"){dataLayer.push=function(data){if(data instanceof Object){handleCallback(data,"eventCallback");for(var key in data){handleCallback(data[key],"event_callback");}if(!data.hasOwnProperty("eventCallback")&&!data.hasOwnProperty("eventCallback")){[].push.call(window.dataLayer,data);}}if(Array.isArray(data)){data.forEach(function(arg){handleCallback(arg,"callback");});}return noopFunc;};}if(google_optimize instanceof Object&&typeof google_optimize.get==="function"){var googleOptimizeWrapper={get:noopFunc};window.google_optimize=googleOptimizeWrapper;}hit(source);}function hit(source){var ADGUARD_PREFIX="[AdGuard]";if(!source.verbose){return;}try{var trace=console.trace.bind(console);var label="".concat(ADGUARD_PREFIX," ");if(source.engine==="corelibs"){label+=source.ruleText;}else {if(source.domainName){label+="".concat(source.domainName);}if(source.args){label+="#%#//scriptlet('".concat(source.name,"', '").concat(source.args.join("', '"),"')");}else {label+="#%#//scriptlet('".concat(source.name,"')");}}if(trace){trace(label);}}catch(e){}if(typeof window.__debug==="function"){window.__debug(source);}}function noopFunc(){}var updatedArgs=args?[].concat(source).concat(args):[source];try{GoogleAnalytics.apply(this,updatedArgs);if(source.uniqueId){Object.defineProperty(Window.prototype.toString,uniqueIdentifier,{value:flag,enumerable:false,writable:false,configurable:false});}}catch(e){console.log(e);}}function GoogleAnalyticsGa(source,args){var flag="done";var uniqueIdentifier=source.uniqueId+source.name+"_"+(Array.isArray(args)?args.join("_"):"");if(source.uniqueId){if(Window.prototype.toString[uniqueIdentifier]===flag){return;}}function GoogleAnalyticsGa(source){function Gaq(){}Gaq.prototype.Na=noopFunc;Gaq.prototype.O=noopFunc;Gaq.prototype.Sa=noopFunc;Gaq.prototype.Ta=noopFunc;Gaq.prototype.Va=noopFunc;Gaq.prototype._createAsyncTracker=noopFunc;Gaq.prototype._getAsyncTracker=noopFunc;Gaq.prototype._getPlugin=noopFunc;Gaq.prototype.push=function(data){if(typeof data==="function"){data();return;}if(Array.isArray(data)===false){return;}if(typeof data[0]==="string"&&/(^|\.)_link$/.test(data[0])&&typeof data[1]==="string"){window.location.assign(data[1]);}if(data[0]==="_set"&&data[1]==="hitCallback"&&typeof data[2]==="function"){data[2]();}};var gaq=new Gaq();var asyncTrackers=window._gaq||[];if(Array.isArray(asyncTrackers)){while(asyncTrackers[0]){gaq.push(asyncTrackers.shift());}}window._gaq=gaq.qf=gaq;function Gat(){}var api=["_addIgnoredOrganic","_addIgnoredRef","_addItem","_addOrganic","_addTrans","_clearIgnoredOrganic","_clearIgnoredRef","_clearOrganic","_cookiePathCopy","_deleteCustomVar","_getName","_setAccount","_getAccount","_getClientInfo","_getDetectFlash","_getDetectTitle","_getLinkerUrl","_getLocalGifPath","_getServiceMode","_getVersion","_getVisitorCustomVar","_initData","_link","_linkByPost","_setAllowAnchor","_setAllowHash","_setAllowLinker","_setCampContentKey","_setCampMediumKey","_setCampNameKey","_setCampNOKey","_setCampSourceKey","_setCampTermKey","_setCampaignCookieTimeout","_setCampaignTrack","_setClientInfo","_setCookiePath","_setCookiePersistence","_setCookieTimeout","_setCustomVar","_setDetectFlash","_setDetectTitle","_setDomainName","_setLocalGifPath","_setLocalRemoteServerMode","_setLocalServerMode","_setReferrerOverride","_setRemoteServerMode","_setSampleRate","_setSessionTimeout","_setSiteSpeedSampleRate","_setSessionCookieTimeout","_setVar","_setVisitorCookieTimeout","_trackEvent","_trackPageLoadTime","_trackPageview","_trackSocial","_trackTiming","_trackTrans","_visitCode"];var tracker=api.reduce(function(res,funcName){res[funcName]=noopFunc;return res;},{});tracker._getLinkerUrl=function(a){return a;};tracker._link=function(url){if(typeof url!=="string"){return;}try{window.location.assign(url);}catch(e){logMessage(source,e);}};Gat.prototype._anonymizeIP=noopFunc;Gat.prototype._createTracker=noopFunc;Gat.prototype._forceSSL=noopFunc;Gat.prototype._getPlugin=noopFunc;Gat.prototype._getTracker=function(){return tracker;};Gat.prototype._getTrackerByName=function(){return tracker;};Gat.prototype._getTrackers=noopFunc;Gat.prototype.aa=noopFunc;Gat.prototype.ab=noopFunc;Gat.prototype.hb=noopFunc;Gat.prototype.la=noopFunc;Gat.prototype.oa=noopFunc;Gat.prototype.pa=noopFunc;Gat.prototype.u=noopFunc;var gat=new Gat();window._gat=gat;hit(source);}function hit(source){var ADGUARD_PREFIX="[AdGuard]";if(!source.verbose){return;}try{var trace=console.trace.bind(console);var label="".concat(ADGUARD_PREFIX," ");if(source.engine==="corelibs"){label+=source.ruleText;}else {if(source.domainName){label+="".concat(source.domainName);}if(source.args){label+="#%#//scriptlet('".concat(source.name,"', '").concat(source.args.join("', '"),"')");}else {label+="#%#//scriptlet('".concat(source.name,"')");}}if(trace){trace(label);}}catch(e){}if(typeof window.__debug==="function"){window.__debug(source);}}function noopFunc(){}function logMessage(source,message){var forced=arguments.length>2&&arguments[2]!==undefined?arguments[2]:false;var convertMessageToString=arguments.length>3&&arguments[3]!==undefined?arguments[3]:true;var name=source.name,verbose=source.verbose;if(!forced&&!verbose){return;}var nativeConsole=console.log;if(!convertMessageToString){nativeConsole("".concat(name,":"),message);return;}nativeConsole("".concat(name,": ").concat(message));}var updatedArgs=args?[].concat(source).concat(args):[source];try{GoogleAnalyticsGa.apply(this,updatedArgs);if(source.uniqueId){Object.defineProperty(Window.prototype.toString,uniqueIdentifier,{value:flag,enumerable:false,writable:false,configurable:false});}}catch(e){console.log(e);}}function GoogleIma3(source,args){var flag="done";var uniqueIdentifier=source.uniqueId+source.name+"_"+(Array.isArray(args)?args.join("_"):"");if(source.uniqueId){if(Window.prototype.toString[uniqueIdentifier]===flag){return;}}function GoogleIma3(source){var _window$google$ima;var VERSION="3.453.0";var ima={};var AdDisplayContainer=function AdDisplayContainer(containerElement){var divElement=document.createElement("div");divElement.style.setProperty("display","none","important");divElement.style.setProperty("visibility","collapse","important");if(containerElement){containerElement.appendChild(divElement);}};AdDisplayContainer.prototype.destroy=noopFunc;AdDisplayContainer.prototype.initialize=noopFunc;var ImaSdkSettings=function ImaSdkSettings(){};ImaSdkSettings.CompanionBackfillMode={ALWAYS:"always",ON_MASTER_AD:"on_master_ad"};ImaSdkSettings.VpaidMode={DISABLED:0,ENABLED:1,INSECURE:2};ImaSdkSettings.prototype={c:true,f:{},i:false,l:"",p:"",r:0,t:"",v:"",getCompanionBackfill:noopFunc,getDisableCustomPlaybackForIOS10Plus(){return this.i;},getDisabledFlashAds:function getDisabledFlashAds(){return true;},getFeatureFlags(){return this.f;},getLocale(){return this.l;},getNumRedirects(){return this.r;},getPlayerType(){return this.t;},getPlayerVersion(){return this.v;},getPpid(){return this.p;},getVpaidMode(){return this.C;},isCookiesEnabled(){return this.c;},isVpaidAdapter(){return this.M;},setCompanionBackfill:noopFunc,setAutoPlayAdBreaks(a){this.K=a;},setCookiesEnabled(c){this.c=!!c;},setDisableCustomPlaybackForIOS10Plus(i){this.i=!!i;},setDisableFlashAds:noopFunc,setFeatureFlags(f){this.f=!!f;},setIsVpaidAdapter(a){this.M=a;},setLocale(l){this.l=!!l;},setNumRedirects(r){this.r=!!r;},setPageCorrelator(a){this.R=a;},setPlayerType(t){this.t=!!t;},setPlayerVersion(v){this.v=!!v;},setPpid(p){this.p=!!p;},setVpaidMode(a){this.C=a;},setSessionId:noopFunc,setStreamCorrelator:noopFunc,setVpaidAllowed:noopFunc,CompanionBackfillMode:{ALWAYS:"always",ON_MASTER_AD:"on_master_ad"},VpaidMode:{DISABLED:0,ENABLED:1,INSECURE:2}};var EventHandler=function EventHandler(){this.listeners=new Map();this._dispatch=function(e){var listeners=this.listeners.get(e.type);listeners=listeners?listeners.values():[];for(var _i=0,_Array$from=Array.from(listeners);_i<_Array$from.length;_i++){var listener=_Array$from[_i];try{listener(e);}catch(r){logMessage(source,r);}}};this.addEventListener=function(types,callback,options,context){if(!Array.isArray(types)){types=[types];}for(var i=0;i<types.length;i+=1){var type=types[i];if(!this.listeners.has(type)){this.listeners.set(type,new Map());}this.listeners.get(type).set(callback,callback.bind(context||this));}};this.removeEventListener=function(types,callback){if(!Array.isArray(types)){types=[types];}for(var i=0;i<types.length;i+=1){var _this$listeners$get;var type=types[i];(_this$listeners$get=this.listeners.get(type))===null||_this$listeners$get===void 0?void 0:_this$listeners$get.delete(callback);}};};var AdsManager=new EventHandler();AdsManager.volume=1;AdsManager.collapse=noopFunc;AdsManager.configureAdsManager=noopFunc;AdsManager.destroy=noopFunc;AdsManager.discardAdBreak=noopFunc;AdsManager.expand=noopFunc;AdsManager.focus=noopFunc;AdsManager.getAdSkippableState=function(){return false;};AdsManager.getCuePoints=function(){return [0];};AdsManager.getCurrentAd=function(){return currentAd;};AdsManager.getCurrentAdCuePoints=function(){return [];};AdsManager.getRemainingTime=function(){return 0;};AdsManager.getVolume=function(){return this.volume;};AdsManager.init=noopFunc;AdsManager.isCustomClickTrackingUsed=function(){return false;};AdsManager.isCustomPlaybackUsed=function(){return false;};AdsManager.pause=noopFunc;AdsManager.requestNextAdBreak=noopFunc;AdsManager.resize=noopFunc;AdsManager.resume=noopFunc;AdsManager.setVolume=function(v){this.volume=v;};AdsManager.skip=noopFunc;AdsManager.start=function(){for(var _i2=0,_arr=[AdEvent.Type.ALL_ADS_COMPLETED,AdEvent.Type.CONTENT_RESUME_REQUESTED];_i2<_arr.length;_i2++){var type=_arr[_i2];try{this._dispatch(new ima.AdEvent(type));}catch(e){logMessage(source,e);}}};AdsManager.stop=noopFunc;AdsManager.updateAdsRenderingSettings=noopFunc;var manager=Object.create(AdsManager);var AdsManagerLoadedEvent=function AdsManagerLoadedEvent(type,adsRequest,userRequestContext){this.type=type;this.adsRequest=adsRequest;this.userRequestContext=userRequestContext;};AdsManagerLoadedEvent.prototype={getAdsManager:function getAdsManager(){return manager;},getUserRequestContext(){if(this.userRequestContext){return this.userRequestContext;}return {};}};AdsManagerLoadedEvent.Type={ADS_MANAGER_LOADED:"adsManagerLoaded"};var AdsLoader=EventHandler;AdsLoader.prototype.settings=new ImaSdkSettings();AdsLoader.prototype.contentComplete=noopFunc;AdsLoader.prototype.destroy=noopFunc;AdsLoader.prototype.getSettings=function(){return this.settings;};AdsLoader.prototype.getVersion=function(){return VERSION;};AdsLoader.prototype.requestAds=function(adsRequest,userRequestContext){var _this=this;requestAnimationFrame(function(){var ADS_MANAGER_LOADED=AdsManagerLoadedEvent.Type.ADS_MANAGER_LOADED;var event=new ima.AdsManagerLoadedEvent(ADS_MANAGER_LOADED,adsRequest,userRequestContext);_this._dispatch(event);});var e=new ima.AdError("adPlayError",1205,1205,"The browser prevented playback initiated without user interaction.",adsRequest,userRequestContext);requestAnimationFrame(function(){_this._dispatch(new ima.AdErrorEvent(e));});};var AdsRenderingSettings=noopFunc;var AdsRequest=function AdsRequest(){};AdsRequest.prototype={setAdWillAutoPlay:noopFunc,setAdWillPlayMuted:noopFunc,setContinuousPlayback:noopFunc};var AdPodInfo=function AdPodInfo(){};AdPodInfo.prototype={getAdPosition:function getAdPosition(){return 1;},getIsBumper:function getIsBumper(){return false;},getMaxDuration:function getMaxDuration(){return -1;},getPodIndex:function getPodIndex(){return 1;},getTimeOffset:function getTimeOffset(){return 0;},getTotalAds:function getTotalAds(){return 1;}};var UniversalAdIdInfo=function UniversalAdIdInfo(){};UniversalAdIdInfo.prototype.getAdIdRegistry=function(){return "";};UniversalAdIdInfo.prototype.getAdIsValue=function(){return "";};var Ad=function Ad(){};Ad.prototype={pi:new AdPodInfo(),getAdId:function getAdId(){return "";},getAdPodInfo(){return this.pi;},getAdSystem:function getAdSystem(){return "";},getAdvertiserName:function getAdvertiserName(){return "";},getApiFramework:function getApiFramework(){return null;},getCompanionAds:function getCompanionAds(){return [];},getContentType:function getContentType(){return "";},getCreativeAdId:function getCreativeAdId(){return "";},getDealId:function getDealId(){return "";},getDescription:function getDescription(){return "";},getDuration:function getDuration(){return 8.5;},getHeight:function getHeight(){return 0;},getMediaUrl:function getMediaUrl(){return null;},getMinSuggestedDuration:function getMinSuggestedDuration(){return -2;},getSkipTimeOffset:function getSkipTimeOffset(){return -1;},getSurveyUrl:function getSurveyUrl(){return null;},getTitle:function getTitle(){return "";},getTraffickingParametersString:function getTraffickingParametersString(){return "";},getUiElements:function getUiElements(){return [""];},getUniversalAdIdRegistry:function getUniversalAdIdRegistry(){return "unknown";},getUniversalAdIds:function getUniversalAdIds(){return [new UniversalAdIdInfo()];},getUniversalAdIdValue:function getUniversalAdIdValue(){return "unknown";},getVastMediaBitrate:function getVastMediaBitrate(){return 0;},getVastMediaHeight:function getVastMediaHeight(){return 0;},getVastMediaWidth:function getVastMediaWidth(){return 0;},getWidth:function getWidth(){return 0;},getWrapperAdIds:function getWrapperAdIds(){return [""];},getWrapperAdSystems:function getWrapperAdSystems(){return [""];},getWrapperCreativeIds:function getWrapperCreativeIds(){return [""];},isLinear:function isLinear(){return true;},isSkippable(){return true;}};var CompanionAd=function CompanionAd(){};CompanionAd.prototype={getAdSlotId:function getAdSlotId(){return "";},getContent:function getContent(){return "";},getContentType:function getContentType(){return "";},getHeight:function getHeight(){return 1;},getWidth:function getWidth(){return 1;}};var AdError=function AdError(type,code,vast,message,adsRequest,userRequestContext){this.errorCode=code;this.message=message;this.type=type;this.adsRequest=adsRequest;this.userRequestContext=userRequestContext;this.getErrorCode=function(){return this.errorCode;};this.getInnerError=function(){return null;};this.getMessage=function(){return this.message;};this.getType=function(){return this.type;};this.getVastErrorCode=function(){return this.vastErrorCode;};this.toString=function(){return "AdError ".concat(this.errorCode,": ").concat(this.message);};};AdError.ErrorCode={};AdError.Type={};var isEngadget=function isEngadget(){try{for(var _i3=0,_Object$values=Object.values(window.vidible._getContexts());_i3<_Object$values.length;_i3++){var _ctx$getPlayer,_ctx$getPlayer$div;var ctx=_Object$values[_i3];if((_ctx$getPlayer=ctx.getPlayer())!==null&&_ctx$getPlayer!==void 0&&(_ctx$getPlayer$div=_ctx$getPlayer.div)!==null&&_ctx$getPlayer$div!==void 0&&_ctx$getPlayer$div.innerHTML.includes("www.engadget.com")){return true;}}}catch(e){}return false;};var currentAd=isEngadget()?undefined:new Ad();var AdEvent=function AdEvent(type){this.type=type;};AdEvent.prototype={getAd:function getAd(){return currentAd;},getAdData:function getAdData(){}};AdEvent.Type={AD_BREAK_READY:"adBreakReady",AD_BUFFERING:"adBuffering",AD_CAN_PLAY:"adCanPlay",AD_METADATA:"adMetadata",AD_PROGRESS:"adProgress",ALL_ADS_COMPLETED:"allAdsCompleted",CLICK:"click",COMPLETE:"complete",CONTENT_PAUSE_REQUESTED:"contentPauseRequested",CONTENT_RESUME_REQUESTED:"contentResumeRequested",DURATION_CHANGE:"durationChange",EXPANDED_CHANGED:"expandedChanged",FIRST_QUARTILE:"firstQuartile",IMPRESSION:"impression",INTERACTION:"interaction",LINEAR_CHANGE:"linearChange",LINEAR_CHANGED:"linearChanged",LOADED:"loaded",LOG:"log",MIDPOINT:"midpoint",PAUSED:"pause",RESUMED:"resume",SKIPPABLE_STATE_CHANGED:"skippableStateChanged",SKIPPED:"skip",STARTED:"start",THIRD_QUARTILE:"thirdQuartile",USER_CLOSE:"userClose",VIDEO_CLICKED:"videoClicked",VIDEO_ICON_CLICKED:"videoIconClicked",VIEWABLE_IMPRESSION:"viewable_impression",VOLUME_CHANGED:"volumeChange",VOLUME_MUTED:"mute"};var AdErrorEvent=function AdErrorEvent(error){this.error=error;this.type="adError";this.getError=function(){return this.error;};this.getUserRequestContext=function(){var _this$error;if((_this$error=this.error)!==null&&_this$error!==void 0&&_this$error.userRequestContext){return this.error.userRequestContext;}return {};};};AdErrorEvent.Type={AD_ERROR:"adError"};var CustomContentLoadedEvent=function CustomContentLoadedEvent(){};CustomContentLoadedEvent.Type={CUSTOM_CONTENT_LOADED:"deprecated-event"};var CompanionAdSelectionSettings=function CompanionAdSelectionSettings(){};CompanionAdSelectionSettings.CreativeType={ALL:"All",FLASH:"Flash",IMAGE:"Image"};CompanionAdSelectionSettings.ResourceType={ALL:"All",HTML:"Html",IFRAME:"IFrame",STATIC:"Static"};CompanionAdSelectionSettings.SizeCriteria={IGNORE:"IgnoreSize",SELECT_EXACT_MATCH:"SelectExactMatch",SELECT_NEAR_MATCH:"SelectNearMatch"};var AdCuePoints=function AdCuePoints(){};AdCuePoints.prototype={getCuePoints:function getCuePoints(){return [];},getAdIdRegistry:function getAdIdRegistry(){return "";},getAdIdValue:function getAdIdValue(){return "";}};var AdProgressData=noopFunc;Object.assign(ima,{AdCuePoints:AdCuePoints,AdDisplayContainer:AdDisplayContainer,AdError:AdError,AdErrorEvent:AdErrorEvent,AdEvent:AdEvent,AdPodInfo:AdPodInfo,AdProgressData:AdProgressData,AdsLoader:AdsLoader,AdsManager:manager,AdsManagerLoadedEvent:AdsManagerLoadedEvent,AdsRenderingSettings:AdsRenderingSettings,AdsRequest:AdsRequest,CompanionAd:CompanionAd,CompanionAdSelectionSettings:CompanionAdSelectionSettings,CustomContentLoadedEvent:CustomContentLoadedEvent,gptProxyInstance:{},ImaSdkSettings:ImaSdkSettings,OmidAccessMode:{DOMAIN:"domain",FULL:"full",LIMITED:"limited"},OmidVerificationVendor:{1:"OTHER",2:"MOAT",3:"DOUBLEVERIFY",4:"INTEGRAL_AD_SCIENCE",5:"PIXELATE",6:"NIELSEN",7:"COMSCORE",8:"MEETRICS",9:"GOOGLE",OTHER:1,MOAT:2,DOUBLEVERIFY:3,INTEGRAL_AD_SCIENCE:4,PIXELATE:5,NIELSEN:6,COMSCORE:7,MEETRICS:8,GOOGLE:9},settings:new ImaSdkSettings(),UiElements:{AD_ATTRIBUTION:"adAttribution",COUNTDOWN:"countdown"},UniversalAdIdInfo:UniversalAdIdInfo,VERSION:VERSION,ViewMode:{FULLSCREEN:"fullscreen",NORMAL:"normal"}});if(!window.google){window.google={};}if((_window$google$ima=window.google.ima)!==null&&_window$google$ima!==void 0&&_window$google$ima.dai){ima.dai=window.google.ima.dai;}window.google.ima=ima;hit(source);}function hit(source){var ADGUARD_PREFIX="[AdGuard]";if(!source.verbose){return;}try{var trace=console.trace.bind(console);var label="".concat(ADGUARD_PREFIX," ");if(source.engine==="corelibs"){label+=source.ruleText;}else {if(source.domainName){label+="".concat(source.domainName);}if(source.args){label+="#%#//scriptlet('".concat(source.name,"', '").concat(source.args.join("', '"),"')");}else {label+="#%#//scriptlet('".concat(source.name,"')");}}if(trace){trace(label);}}catch(e){}if(typeof window.__debug==="function"){window.__debug(source);}}function noopFunc(){}function logMessage(source,message){var forced=arguments.length>2&&arguments[2]!==undefined?arguments[2]:false;var convertMessageToString=arguments.length>3&&arguments[3]!==undefined?arguments[3]:true;var name=source.name,verbose=source.verbose;if(!forced&&!verbose){return;}var nativeConsole=console.log;if(!convertMessageToString){nativeConsole("".concat(name,":"),message);return;}nativeConsole("".concat(name,": ").concat(message));}var updatedArgs=args?[].concat(source).concat(args):[source];try{GoogleIma3.apply(this,updatedArgs);if(source.uniqueId){Object.defineProperty(Window.prototype.toString,uniqueIdentifier,{value:flag,enumerable:false,writable:false,configurable:false});}}catch(e){console.log(e);}}function GoogleSyndicationAdsByGoogle(source,args){var flag="done";var uniqueIdentifier=source.uniqueId+source.name+"_"+(Array.isArray(args)?args.join("_"):"");if(source.uniqueId){if(Window.prototype.toString[uniqueIdentifier]===flag){return;}}function GoogleSyndicationAdsByGoogle(source){window.adsbygoogle={loaded:true,push(arg){if(typeof this.length==="undefined"){this.length=0;this.length+=1;}if(arg!==null&&arg instanceof Object&&arg.constructor.name==="Object"){for(var _i=0,_Object$keys=Object.keys(arg);_i<_Object$keys.length;_i++){var key=_Object$keys[_i];if(typeof arg[key]==="function"){try{arg[key].call(this,{});}catch(_unused){}}}}}};var adElems=document.querySelectorAll(".adsbygoogle");var css="height:1px!important;max-height:1px!important;max-width:1px!important;width:1px!important;";var statusAttrName="data-adsbygoogle-status";var ASWIFT_IFRAME_MARKER="aswift_";var GOOGLE_ADS_IFRAME_MARKER="google_ads_iframe_";var executed=false;for(var i=0;i<adElems.length;i+=1){var adElemChildNodes=adElems[i].childNodes;var childNodesQuantity=adElemChildNodes.length;var areIframesDefined=false;if(childNodesQuantity>0){areIframesDefined=childNodesQuantity===2&&adElemChildNodes[0].nodeName.toLowerCase()==="iframe"&&adElemChildNodes[0].id.includes(ASWIFT_IFRAME_MARKER)&&adElemChildNodes[1].nodeName.toLowerCase()==="iframe"&&adElemChildNodes[1].id.includes(GOOGLE_ADS_IFRAME_MARKER);}if(!areIframesDefined){adElems[i].setAttribute(statusAttrName,"done");var aswiftIframe=document.createElement("iframe");aswiftIframe.id="".concat(ASWIFT_IFRAME_MARKER).concat(i);aswiftIframe.style=css;adElems[i].appendChild(aswiftIframe);var innerAswiftIframe=document.createElement("iframe");aswiftIframe.contentWindow.document.body.appendChild(innerAswiftIframe);var googleadsIframe=document.createElement("iframe");googleadsIframe.id="".concat(GOOGLE_ADS_IFRAME_MARKER).concat(i);googleadsIframe.style=css;adElems[i].appendChild(googleadsIframe);var innerGoogleadsIframe=document.createElement("iframe");googleadsIframe.contentWindow.document.body.appendChild(innerGoogleadsIframe);executed=true;}}if(executed){hit(source);}}function hit(source){var ADGUARD_PREFIX="[AdGuard]";if(!source.verbose){return;}try{var trace=console.trace.bind(console);var label="".concat(ADGUARD_PREFIX," ");if(source.engine==="corelibs"){label+=source.ruleText;}else {if(source.domainName){label+="".concat(source.domainName);}if(source.args){label+="#%#//scriptlet('".concat(source.name,"', '").concat(source.args.join("', '"),"')");}else {label+="#%#//scriptlet('".concat(source.name,"')");}}if(trace){trace(label);}}catch(e){}if(typeof window.__debug==="function"){window.__debug(source);}}var updatedArgs=args?[].concat(source).concat(args):[source];try{GoogleSyndicationAdsByGoogle.apply(this,updatedArgs);if(source.uniqueId){Object.defineProperty(Window.prototype.toString,uniqueIdentifier,{value:flag,enumerable:false,writable:false,configurable:false});}}catch(e){console.log(e);}}function GoogleTagServicesGpt(source,args){var flag="done";var uniqueIdentifier=source.uniqueId+source.name+"_"+(Array.isArray(args)?args.join("_"):"");if(source.uniqueId){if(Window.prototype.toString[uniqueIdentifier]===flag){return;}}function GoogleTagServicesGpt(source){var slots=new Map();var slotsById=new Map();var slotsPerPath=new Map();var slotCreatives=new Map();var eventCallbacks=new Map();var gTargeting=new Map();var addEventListener=function addEventListener(name,listener){if(!eventCallbacks.has(name)){eventCallbacks.set(name,new Set());}eventCallbacks.get(name).add(listener);return this;};var removeEventListener=function removeEventListener(name,listener){if(eventCallbacks.has(name)){return eventCallbacks.get(name).delete(listener);}return false;};var fireSlotEvent=function fireSlotEvent(name,slot){return new Promise(function(resolve){requestAnimationFrame(function(){var size=[0,0];var callbacksSet=eventCallbacks.get(name)||[];var callbackArray=Array.from(callbacksSet);for(var i=0;i<callbackArray.length;i+=1){callbackArray[i]({isEmpty:true,size:size,slot:slot});}resolve();});});};var emptySlotElement=function emptySlotElement(slot){var node=document.getElementById(slot.getSlotElementId());while(node!==null&&node!==void 0&&node.lastChild){node.lastChild.remove();}};var recreateIframeForSlot=function recreateIframeForSlot(slot){var _document$getElementB;var eid="google_ads_iframe_".concat(slot.getId());(_document$getElementB=document.getElementById(eid))===null||_document$getElementB===void 0?void 0:_document$getElementB.remove();var node=document.getElementById(slot.getSlotElementId());if(node){var f=document.createElement("iframe");f.id=eid;f.srcdoc="<body></body>";f.style="position:absolute; width:0; height:0; left:0; right:0; z-index:-1; border:0";f.setAttribute("width",0);f.setAttribute("height",0);f.setAttribute("data-load-complete",true);f.setAttribute("data-google-container-id",true);f.setAttribute("sandbox","");node.appendChild(f);}};var displaySlot=function displaySlot(slot){if(!slot){return;}var id=slot.getSlotElementId();if(!document.getElementById(id)){return;}var parent=document.getElementById(id);if(parent){parent.appendChild(document.createElement("div"));}emptySlotElement(slot);recreateIframeForSlot(slot);fireSlotEvent("slotRenderEnded",slot);fireSlotEvent("slotRequested",slot);fireSlotEvent("slotResponseReceived",slot);fireSlotEvent("slotOnload",slot);fireSlotEvent("impressionViewable",slot);};var companionAdsService={addEventListener:addEventListener,removeEventListener:removeEventListener,enableSyncLoading:noopFunc,setRefreshUnfilledSlots:noopFunc,getSlots:noopArray};var contentService={addEventListener:addEventListener,removeEventListener:removeEventListener,setContent:noopFunc};function PassbackSlot(){}PassbackSlot.prototype.display=noopFunc;PassbackSlot.prototype.get=noopNull;PassbackSlot.prototype.set=noopThis;PassbackSlot.prototype.setClickUrl=noopThis;PassbackSlot.prototype.setTagForChildDirectedTreatment=noopThis;PassbackSlot.prototype.setTargeting=noopThis;PassbackSlot.prototype.updateTargetingFromMap=noopThis;function SizeMappingBuilder(){}SizeMappingBuilder.prototype.addSize=noopThis;SizeMappingBuilder.prototype.build=noopNull;var getTargetingValue=function getTargetingValue(v){if(typeof v==="string"){return [v];}try{return Array.prototype.flat.call(v);}catch(_unused){}return [];};var updateTargeting=function updateTargeting(targeting,map){if(typeof map==="object"){for(var key in map){if(Object.prototype.hasOwnProperty.call(map,key)){targeting.set(key,getTargetingValue(map[key]));}}}};var defineSlot=function defineSlot(adUnitPath,creatives,optDiv){if(slotsById.has(optDiv)){var _document$getElementB2;(_document$getElementB2=document.getElementById(optDiv))===null||_document$getElementB2===void 0?void 0:_document$getElementB2.remove();return slotsById.get(optDiv);}var attributes=new Map();var targeting=new Map();var exclusions=new Set();var response={advertiserId:undefined,campaignId:undefined,creativeId:undefined,creativeTemplateId:undefined,lineItemId:undefined};var sizes=[{getHeight:function getHeight(){return 2;},getWidth:function getWidth(){return 2;}}];var num=(slotsPerPath.get(adUnitPath)||0)+1;slotsPerPath.set(adUnitPath,num);var id="".concat(adUnitPath,"_").concat(num);var clickUrl="";var collapseEmptyDiv=null;var services=new Set();var slot={addService(e){services.add(e);return slot;},clearCategoryExclusions:noopThis,clearTargeting(k){if(k===undefined){targeting.clear();}else {targeting.delete(k);}},defineSizeMapping(mapping){slotCreatives.set(optDiv,mapping);return this;},get:function get(k){return attributes.get(k);},getAdUnitPath:function getAdUnitPath(){return adUnitPath;},getAttributeKeys:function getAttributeKeys(){return Array.from(attributes.keys());},getCategoryExclusions:function getCategoryExclusions(){return Array.from(exclusions);},getClickUrl:function getClickUrl(){return clickUrl;},getCollapseEmptyDiv:function getCollapseEmptyDiv(){return collapseEmptyDiv;},getContentUrl:function getContentUrl(){return "";},getDivStartsCollapsed:function getDivStartsCollapsed(){return null;},getDomId:function getDomId(){return optDiv;},getEscapedQemQueryId:function getEscapedQemQueryId(){return "";},getFirstLook:function getFirstLook(){return 0;},getId:function getId(){return id;},getHtml:function getHtml(){return "";},getName:function getName(){return id;},getOutOfPage:function getOutOfPage(){return false;},getResponseInformation:function getResponseInformation(){return response;},getServices:function getServices(){return Array.from(services);},getSizes:function getSizes(){return sizes;},getSlotElementId:function getSlotElementId(){return optDiv;},getSlotId:function getSlotId(){return slot;},getTargeting:function getTargeting(k){return targeting.get(k)||gTargeting.get(k)||[];},getTargetingKeys:function getTargetingKeys(){return Array.from(new Set(Array.of(...gTargeting.keys(),...targeting.keys())));},getTargetingMap:function getTargetingMap(){return Object.assign(Object.fromEntries(gTargeting.entries()),Object.fromEntries(targeting.entries()));},set(k,v){attributes.set(k,v);return slot;},setCategoryExclusion(e){exclusions.add(e);return slot;},setClickUrl(u){clickUrl=u;return slot;},setCollapseEmptyDiv(v){collapseEmptyDiv=!!v;return slot;},setSafeFrameConfig:noopThis,setTagForChildDirectedTreatment:noopThis,setTargeting(k,v){targeting.set(k,getTargetingValue(v));return slot;},toString:function toString(){return id;},updateTargetingFromMap(map){updateTargeting(targeting,map);return slot;}};slots.set(adUnitPath,slot);slotsById.set(optDiv,slot);slotCreatives.set(optDiv,creatives);return slot;};var pubAdsService={addEventListener:addEventListener,removeEventListener:removeEventListener,clear:noopFunc,clearCategoryExclusions:noopThis,clearTagForChildDirectedTreatment:noopThis,clearTargeting(k){if(k===undefined){gTargeting.clear();}else {gTargeting.delete(k);}},collapseEmptyDivs:noopFunc,defineOutOfPagePassback(){return new PassbackSlot();},definePassback(){return new PassbackSlot();},disableInitialLoad:noopFunc,display:noopFunc,enableAsyncRendering:noopFunc,enableLazyLoad:noopFunc,enableSingleRequest:noopFunc,enableSyncRendering:noopFunc,enableVideoAds:noopFunc,get:noopNull,getAttributeKeys:noopArray,getTargeting:noopArray,getTargetingKeys:noopArray,getSlots:noopArray,isInitialLoadDisabled:trueFunc,refresh:noopFunc,set:noopThis,setCategoryExclusion:noopThis,setCentering:noopFunc,setCookieOptions:noopThis,setForceSafeFrame:noopThis,setLocation:noopThis,setPrivacySettings:noopThis,setPublisherProvidedId:noopThis,setRequestNonPersonalizedAds:noopThis,setSafeFrameConfig:noopThis,setTagForChildDirectedTreatment:noopThis,setTargeting:noopThis,setVideoContent:noopThis,updateCorrelator:noopFunc};var _window=window,_window$googletag=_window.googletag,googletag=_window$googletag===void 0?{}:_window$googletag;var _googletag$cmd=googletag.cmd,cmd=_googletag$cmd===void 0?[]:_googletag$cmd;googletag.apiReady=true;googletag.cmd=[];googletag.cmd.push=function(a){try{a();}catch(ex){}return 1;};googletag.companionAds=function(){return companionAdsService;};googletag.content=function(){return contentService;};googletag.defineOutOfPageSlot=defineSlot;googletag.defineSlot=defineSlot;googletag.destroySlots=function(){slots.clear();slotsById.clear();};googletag.disablePublisherConsole=noopFunc;googletag.display=function(arg){var id;if(arg!==null&&arg!==void 0&&arg.getSlotElementId){id=arg.getSlotElementId();}else if(arg!==null&&arg!==void 0&&arg.nodeType){id=arg.id;}else {id=String(arg);}displaySlot(slotsById.get(id));};googletag.enableServices=noopFunc;googletag.getVersion=noopStr;googletag.pubads=function(){return pubAdsService;};googletag.pubadsReady=true;googletag.setAdIframeTitle=noopFunc;googletag.sizeMapping=function(){return new SizeMappingBuilder();};window.googletag=googletag;while(cmd.length!==0){googletag.cmd.push(cmd.shift());}hit(source);}function hit(source){var ADGUARD_PREFIX="[AdGuard]";if(!source.verbose){return;}try{var trace=console.trace.bind(console);var label="".concat(ADGUARD_PREFIX," ");if(source.engine==="corelibs"){label+=source.ruleText;}else {if(source.domainName){label+="".concat(source.domainName);}if(source.args){label+="#%#//scriptlet('".concat(source.name,"', '").concat(source.args.join("', '"),"')");}else {label+="#%#//scriptlet('".concat(source.name,"')");}}if(trace){trace(label);}}catch(e){}if(typeof window.__debug==="function"){window.__debug(source);}}function noopFunc(){}function noopThis(){return this;}function noopNull(){return null;}function noopArray(){return [];}function noopStr(){return "";}function trueFunc(){return true;}var updatedArgs=args?[].concat(source).concat(args):[source];try{GoogleTagServicesGpt.apply(this,updatedArgs);if(source.uniqueId){Object.defineProperty(Window.prototype.toString,uniqueIdentifier,{value:flag,enumerable:false,writable:false,configurable:false});}}catch(e){console.log(e);}}function Matomo(source,args){var flag="done";var uniqueIdentifier=source.uniqueId+source.name+"_"+(Array.isArray(args)?args.join("_"):"");if(source.uniqueId){if(Window.prototype.toString[uniqueIdentifier]===flag){return;}}function Matomo(source){var Tracker=function Tracker(){};Tracker.prototype.setDoNotTrack=noopFunc;Tracker.prototype.setDomains=noopFunc;Tracker.prototype.setCustomDimension=noopFunc;Tracker.prototype.trackPageView=noopFunc;var AsyncTracker=function AsyncTracker(){};AsyncTracker.prototype.addListener=noopFunc;var matomoWrapper={getTracker:Tracker,getAsyncTracker:AsyncTracker};window.Piwik=matomoWrapper;hit(source);}function hit(source){var ADGUARD_PREFIX="[AdGuard]";if(!source.verbose){return;}try{var trace=console.trace.bind(console);var label="".concat(ADGUARD_PREFIX," ");if(source.engine==="corelibs"){label+=source.ruleText;}else {if(source.domainName){label+="".concat(source.domainName);}if(source.args){label+="#%#//scriptlet('".concat(source.name,"', '").concat(source.args.join("', '"),"')");}else {label+="#%#//scriptlet('".concat(source.name,"')");}}if(trace){trace(label);}}catch(e){}if(typeof window.__debug==="function"){window.__debug(source);}}function noopFunc(){}var updatedArgs=args?[].concat(source).concat(args):[source];try{Matomo.apply(this,updatedArgs);if(source.uniqueId){Object.defineProperty(Window.prototype.toString,uniqueIdentifier,{value:flag,enumerable:false,writable:false,configurable:false});}}catch(e){console.log(e);}}function NaverWcslog(source,args){var flag="done";var uniqueIdentifier=source.uniqueId+source.name+"_"+(Array.isArray(args)?args.join("_"):"");if(source.uniqueId){if(Window.prototype.toString[uniqueIdentifier]===flag){return;}}function NaverWcslog(source){window.wcs_add={};window.wcs_do=noopFunc;window.wcs={inflow:noopFunc};hit(source);}function hit(source){var ADGUARD_PREFIX="[AdGuard]";if(!source.verbose){return;}try{var trace=console.trace.bind(console);var label="".concat(ADGUARD_PREFIX," ");if(source.engine==="corelibs"){label+=source.ruleText;}else {if(source.domainName){label+="".concat(source.domainName);}if(source.args){label+="#%#//scriptlet('".concat(source.name,"', '").concat(source.args.join("', '"),"')");}else {label+="#%#//scriptlet('".concat(source.name,"')");}}if(trace){trace(label);}}catch(e){}if(typeof window.__debug==="function"){window.__debug(source);}}function noopFunc(){}var updatedArgs=args?[].concat(source).concat(args):[source];try{NaverWcslog.apply(this,updatedArgs);if(source.uniqueId){Object.defineProperty(Window.prototype.toString,uniqueIdentifier,{value:flag,enumerable:false,writable:false,configurable:false});}}catch(e){console.log(e);}}function Pardot(source,args){var flag="done";var uniqueIdentifier=source.uniqueId+source.name+"_"+(Array.isArray(args)?args.join("_"):"");if(source.uniqueId){if(Window.prototype.toString[uniqueIdentifier]===flag){return;}}function Pardot(source){window.piVersion="1.0.2";window.piScriptNum=0;window.piScriptObj=[];window.checkNamespace=noopFunc;window.getPardotUrl=noopStr;window.piGetParameter=noopNull;window.piSetCookie=noopFunc;window.piGetCookie=noopStr;function piTracker(){window.pi={tracker:{visitor_id:"",visitor_id_sign:"",pi_opt_in:"",campaign_id:""}};window.piScriptNum+=1;}window.piResponse=noopFunc;window.piTracker=piTracker;piTracker();hit(source);}function hit(source){var ADGUARD_PREFIX="[AdGuard]";if(!source.verbose){return;}try{var trace=console.trace.bind(console);var label="".concat(ADGUARD_PREFIX," ");if(source.engine==="corelibs"){label+=source.ruleText;}else {if(source.domainName){label+="".concat(source.domainName);}if(source.args){label+="#%#//scriptlet('".concat(source.name,"', '").concat(source.args.join("', '"),"')");}else {label+="#%#//scriptlet('".concat(source.name,"')");}}if(trace){trace(label);}}catch(e){}if(typeof window.__debug==="function"){window.__debug(source);}}function noopFunc(){}function noopStr(){return "";}function noopNull(){return null;}var updatedArgs=args?[].concat(source).concat(args):[source];try{Pardot.apply(this,updatedArgs);if(source.uniqueId){Object.defineProperty(Window.prototype.toString,uniqueIdentifier,{value:flag,enumerable:false,writable:false,configurable:false});}}catch(e){console.log(e);}}function Prebid(source,args){var flag="done";var uniqueIdentifier=source.uniqueId+source.name+"_"+(Array.isArray(args)?args.join("_"):"");if(source.uniqueId){if(Window.prototype.toString[uniqueIdentifier]===flag){return;}}function Prebid(source){var pushFunction=function pushFunction(arg){if(typeof arg==="function"){try{arg.call();}catch(ex){}}};var pbjsWrapper={addAdUnits(){},adServers:{dfp:{buildVideoUrl:noopStr}},adUnits:[],aliasBidder(){},cmd:[],enableAnalytics(){},getHighestCpmBids:noopArray,libLoaded:true,que:[],requestBids(arg){if(arg instanceof Object&&arg.bidsBackHandler){try{arg.bidsBackHandler.call();}catch(ex){}}},removeAdUnit(){},setBidderConfig(){},setConfig(){},setTargetingForGPTAsync(){}};pbjsWrapper.cmd.push=pushFunction;pbjsWrapper.que.push=pushFunction;window.pbjs=pbjsWrapper;hit(source);}function hit(source){var ADGUARD_PREFIX="[AdGuard]";if(!source.verbose){return;}try{var trace=console.trace.bind(console);var label="".concat(ADGUARD_PREFIX," ");if(source.engine==="corelibs"){label+=source.ruleText;}else {if(source.domainName){label+="".concat(source.domainName);}if(source.args){label+="#%#//scriptlet('".concat(source.name,"', '").concat(source.args.join("', '"),"')");}else {label+="#%#//scriptlet('".concat(source.name,"')");}}if(trace){trace(label);}}catch(e){}if(typeof window.__debug==="function"){window.__debug(source);}}function noopStr(){return "";}function noopArray(){return [];}var updatedArgs=args?[].concat(source).concat(args):[source];try{Prebid.apply(this,updatedArgs);if(source.uniqueId){Object.defineProperty(Window.prototype.toString,uniqueIdentifier,{value:flag,enumerable:false,writable:false,configurable:false});}}catch(e){console.log(e);}}function ScoreCardResearchBeacon(source,args){var flag="done";var uniqueIdentifier=source.uniqueId+source.name+"_"+(Array.isArray(args)?args.join("_"):"");if(source.uniqueId){if(Window.prototype.toString[uniqueIdentifier]===flag){return;}}function ScoreCardResearchBeacon(source){window.COMSCORE={purge(){window._comscore=[];},beacon(){}};hit(source);}function hit(source){var ADGUARD_PREFIX="[AdGuard]";if(!source.verbose){return;}try{var trace=console.trace.bind(console);var label="".concat(ADGUARD_PREFIX," ");if(source.engine==="corelibs"){label+=source.ruleText;}else {if(source.domainName){label+="".concat(source.domainName);}if(source.args){label+="#%#//scriptlet('".concat(source.name,"', '").concat(source.args.join("', '"),"')");}else {label+="#%#//scriptlet('".concat(source.name,"')");}}if(trace){trace(label);}}catch(e){}if(typeof window.__debug==="function"){window.__debug(source);}}var updatedArgs=args?[].concat(source).concat(args):[source];try{ScoreCardResearchBeacon.apply(this,updatedArgs);if(source.uniqueId){Object.defineProperty(Window.prototype.toString,uniqueIdentifier,{value:flag,enumerable:false,writable:false,configurable:false});}}catch(e){console.log(e);}}function abortCurrentInlineScript(source,args){var flag="done";var uniqueIdentifier=source.uniqueId+source.name+"_"+(Array.isArray(args)?args.join("_"):"");if(source.uniqueId){if(Window.prototype.toString[uniqueIdentifier]===flag){return;}}function abortCurrentInlineScript(source,property,search){var searchRegexp=toRegExp(search);var rid=randomId();var SRC_DATA_MARKER="data:text/javascript;base64,";var getCurrentScript=function getCurrentScript(){if("currentScript"in document){return document.currentScript;}var scripts=document.getElementsByTagName("script");return scripts[scripts.length-1];};var ourScript=getCurrentScript();var abort=function abort(){var _scriptEl$src;var scriptEl=getCurrentScript();if(!scriptEl){return;}var content=scriptEl.textContent;try{var textContentGetter=Object.getOwnPropertyDescriptor(Node.prototype,"textContent").get;content=textContentGetter.call(scriptEl);}catch(e){}if(content.length===0&&typeof scriptEl.src!=="undefined"&&(_scriptEl$src=scriptEl.src)!==null&&_scriptEl$src!==void 0&&_scriptEl$src.startsWith(SRC_DATA_MARKER)){var encodedContent=scriptEl.src.slice(SRC_DATA_MARKER.length);content=window.atob(encodedContent);}if(scriptEl instanceof HTMLScriptElement&&content.length>0&&scriptEl!==ourScript&&searchRegexp.test(content)){hit(source);throw new ReferenceError(rid);}};var setChainPropAccess=function setChainPropAccess(owner,property){var chainInfo=getPropertyInChain(owner,property);var base=chainInfo.base;var prop=chainInfo.prop,chain=chainInfo.chain;if(base instanceof Object===false&&base===null){var props=property.split(".");var propIndex=props.indexOf(prop);var baseName=props[propIndex-1];var message="The scriptlet had been executed before the ".concat(baseName," was loaded.");logMessage(source,message);return;}if(chain){var setter=function setter(a){base=a;if(a instanceof Object){setChainPropAccess(a,chain);}};Object.defineProperty(owner,prop,{get:function get(){return base;},set:setter});return;}var currentValue=base[prop];var origDescriptor=Object.getOwnPropertyDescriptor(base,prop);if(origDescriptor instanceof Object===false||origDescriptor.get instanceof Function===false){currentValue=base[prop];origDescriptor=undefined;}var descriptorWrapper=Object.assign(getDescriptorAddon(),{currentValue:currentValue,get(){if(!this.isAbortingSuspended){this.isolateCallback(abort);}if(origDescriptor instanceof Object){return origDescriptor.get.call(base);}return this.currentValue;},set(newValue){if(!this.isAbortingSuspended){this.isolateCallback(abort);}if(origDescriptor instanceof Object){origDescriptor.set.call(base,newValue);}else {this.currentValue=newValue;}}});setPropertyAccess(base,prop,{get(){return descriptorWrapper.get.call(descriptorWrapper);},set(newValue){descriptorWrapper.set.call(descriptorWrapper,newValue);}});};setChainPropAccess(window,property);window.onerror=createOnErrorHandler(rid).bind();}function randomId(){return Math.random().toString(36).slice(2,9);}function setPropertyAccess(object,property,descriptor){var currentDescriptor=Object.getOwnPropertyDescriptor(object,property);if(currentDescriptor&&!currentDescriptor.configurable){return false;}Object.defineProperty(object,property,descriptor);return true;}function getPropertyInChain(base,chain){var pos=chain.indexOf(".");if(pos===-1){return {base:base,prop:chain};}var prop=chain.slice(0,pos);if(base===null){return {base:base,prop:prop,chain:chain};}var nextBase=base[prop];chain=chain.slice(pos+1);if((base instanceof Object||typeof base==="object")&&isEmptyObject(base)){return {base:base,prop:prop,chain:chain};}if(nextBase===null){return {base:base,prop:prop,chain:chain};}if(nextBase!==undefined){return getPropertyInChain(nextBase,chain);}Object.defineProperty(base,prop,{configurable:true});return {base:base,prop:prop,chain:chain};}function toRegExp(rawInput){var input=rawInput||"";var DEFAULT_VALUE=".?";var FORWARD_SLASH="/";if(input===""){return new RegExp(DEFAULT_VALUE);}var delimiterIndex=input.lastIndexOf(FORWARD_SLASH);var flagsPart=input.substring(delimiterIndex+1);var regExpPart=input.substring(0,delimiterIndex+1);var isValidRegExpFlag=function isValidRegExpFlag(flag){if(!flag){return false;}try{new RegExp("",flag);return true;}catch(ex){return false;}};var getRegExpFlags=function getRegExpFlags(regExpStr,flagsStr){if(regExpStr.startsWith(FORWARD_SLASH)&&regExpStr.endsWith(FORWARD_SLASH)&&!regExpStr.endsWith("\\/")&&isValidRegExpFlag(flagsStr)){return flagsStr;}return "";};var flags=getRegExpFlags(regExpPart,flagsPart);if(input.startsWith(FORWARD_SLASH)&&input.endsWith(FORWARD_SLASH)||flags){var regExpInput=flags?regExpPart:input;return new RegExp(regExpInput.slice(1,-1),flags);}var escaped=input.replace(/\\'/g,"'").replace(/\\"/g,'"').replace(/[.*+?^${}()|[\]\\]/g,"\\$&");return new RegExp(escaped);}function createOnErrorHandler(rid){var nativeOnError=window.onerror;return function onError(error){if(typeof error==="string"&&error.includes(rid)){return true;}if(nativeOnError instanceof Function){for(var _len=arguments.length,args=new Array(_len>1?_len-1:0),_key=1;_key<_len;_key++){args[_key-1]=arguments[_key];}return nativeOnError.apply(window,[error,...args]);}return false;};}function hit(source){var ADGUARD_PREFIX="[AdGuard]";if(!source.verbose){return;}try{var trace=console.trace.bind(console);var label="".concat(ADGUARD_PREFIX," ");if(source.engine==="corelibs"){label+=source.ruleText;}else {if(source.domainName){label+="".concat(source.domainName);}if(source.args){label+="#%#//scriptlet('".concat(source.name,"', '").concat(source.args.join("', '"),"')");}else {label+="#%#//scriptlet('".concat(source.name,"')");}}if(trace){trace(label);}}catch(e){}if(typeof window.__debug==="function"){window.__debug(source);}}function logMessage(source,message){var forced=arguments.length>2&&arguments[2]!==undefined?arguments[2]:false;var convertMessageToString=arguments.length>3&&arguments[3]!==undefined?arguments[3]:true;var name=source.name,verbose=source.verbose;if(!forced&&!verbose){return;}var nativeConsole=console.log;if(!convertMessageToString){nativeConsole("".concat(name,":"),message);return;}nativeConsole("".concat(name,": ").concat(message));}function isEmptyObject(obj){return Object.keys(obj).length===0&&!obj.prototype;}function getDescriptorAddon(){return {isAbortingSuspended:false,isolateCallback(cb){this.isAbortingSuspended=true;try{for(var _len=arguments.length,args=new Array(_len>1?_len-1:0),_key=1;_key<_len;_key++){args[_key-1]=arguments[_key];}var result=cb(...args);this.isAbortingSuspended=false;return result;}catch(_unused){var rid=randomId();this.isAbortingSuspended=false;throw new ReferenceError(rid);}}};}var updatedArgs=args?[].concat(source).concat(args):[source];try{abortCurrentInlineScript.apply(this,updatedArgs);if(source.uniqueId){Object.defineProperty(Window.prototype.toString,uniqueIdentifier,{value:flag,enumerable:false,writable:false,configurable:false});}}catch(e){console.log(e);}}function abortOnPropertyRead(source,args){var flag="done";var uniqueIdentifier=source.uniqueId+source.name+"_"+(Array.isArray(args)?args.join("_"):"");if(source.uniqueId){if(Window.prototype.toString[uniqueIdentifier]===flag){return;}}function abortOnPropertyRead(source,property){if(!property){return;}var rid=randomId();var abort=function abort(){hit(source);throw new ReferenceError(rid);};var setChainPropAccess=function setChainPropAccess(owner,property){var chainInfo=getPropertyInChain(owner,property);var base=chainInfo.base;var prop=chainInfo.prop,chain=chainInfo.chain;if(chain){var setter=function setter(a){base=a;if(a instanceof Object){setChainPropAccess(a,chain);}};Object.defineProperty(owner,prop,{get:function get(){return base;},set:setter});return;}setPropertyAccess(base,prop,{get:abort,set:function set(){}});};setChainPropAccess(window,property);window.onerror=createOnErrorHandler(rid).bind();}function randomId(){return Math.random().toString(36).slice(2,9);}function setPropertyAccess(object,property,descriptor){var currentDescriptor=Object.getOwnPropertyDescriptor(object,property);if(currentDescriptor&&!currentDescriptor.configurable){return false;}Object.defineProperty(object,property,descriptor);return true;}function getPropertyInChain(base,chain){var pos=chain.indexOf(".");if(pos===-1){return {base:base,prop:chain};}var prop=chain.slice(0,pos);if(base===null){return {base:base,prop:prop,chain:chain};}var nextBase=base[prop];chain=chain.slice(pos+1);if((base instanceof Object||typeof base==="object")&&isEmptyObject(base)){return {base:base,prop:prop,chain:chain};}if(nextBase===null){return {base:base,prop:prop,chain:chain};}if(nextBase!==undefined){return getPropertyInChain(nextBase,chain);}Object.defineProperty(base,prop,{configurable:true});return {base:base,prop:prop,chain:chain};}function createOnErrorHandler(rid){var nativeOnError=window.onerror;return function onError(error){if(typeof error==="string"&&error.includes(rid)){return true;}if(nativeOnError instanceof Function){for(var _len=arguments.length,args=new Array(_len>1?_len-1:0),_key=1;_key<_len;_key++){args[_key-1]=arguments[_key];}return nativeOnError.apply(window,[error,...args]);}return false;};}function hit(source){var ADGUARD_PREFIX="[AdGuard]";if(!source.verbose){return;}try{var trace=console.trace.bind(console);var label="".concat(ADGUARD_PREFIX," ");if(source.engine==="corelibs"){label+=source.ruleText;}else {if(source.domainName){label+="".concat(source.domainName);}if(source.args){label+="#%#//scriptlet('".concat(source.name,"', '").concat(source.args.join("', '"),"')");}else {label+="#%#//scriptlet('".concat(source.name,"')");}}if(trace){trace(label);}}catch(e){}if(typeof window.__debug==="function"){window.__debug(source);}}function isEmptyObject(obj){return Object.keys(obj).length===0&&!obj.prototype;}var updatedArgs=args?[].concat(source).concat(args):[source];try{abortOnPropertyRead.apply(this,updatedArgs);if(source.uniqueId){Object.defineProperty(Window.prototype.toString,uniqueIdentifier,{value:flag,enumerable:false,writable:false,configurable:false});}}catch(e){console.log(e);}}function abortOnPropertyWrite(source,args){var flag="done";var uniqueIdentifier=source.uniqueId+source.name+"_"+(Array.isArray(args)?args.join("_"):"");if(source.uniqueId){if(Window.prototype.toString[uniqueIdentifier]===flag){return;}}function abortOnPropertyWrite(source,property){if(!property){return;}var rid=randomId();var abort=function abort(){hit(source);throw new ReferenceError(rid);};var setChainPropAccess=function setChainPropAccess(owner,property){var chainInfo=getPropertyInChain(owner,property);var base=chainInfo.base;var prop=chainInfo.prop,chain=chainInfo.chain;if(chain){var setter=function setter(a){base=a;if(a instanceof Object){setChainPropAccess(a,chain);}};Object.defineProperty(owner,prop,{get:function get(){return base;},set:setter});return;}setPropertyAccess(base,prop,{set:abort});};setChainPropAccess(window,property);window.onerror=createOnErrorHandler(rid).bind();}function randomId(){return Math.random().toString(36).slice(2,9);}function setPropertyAccess(object,property,descriptor){var currentDescriptor=Object.getOwnPropertyDescriptor(object,property);if(currentDescriptor&&!currentDescriptor.configurable){return false;}Object.defineProperty(object,property,descriptor);return true;}function getPropertyInChain(base,chain){var pos=chain.indexOf(".");if(pos===-1){return {base:base,prop:chain};}var prop=chain.slice(0,pos);if(base===null){return {base:base,prop:prop,chain:chain};}var nextBase=base[prop];chain=chain.slice(pos+1);if((base instanceof Object||typeof base==="object")&&isEmptyObject(base)){return {base:base,prop:prop,chain:chain};}if(nextBase===null){return {base:base,prop:prop,chain:chain};}if(nextBase!==undefined){return getPropertyInChain(nextBase,chain);}Object.defineProperty(base,prop,{configurable:true});return {base:base,prop:prop,chain:chain};}function createOnErrorHandler(rid){var nativeOnError=window.onerror;return function onError(error){if(typeof error==="string"&&error.includes(rid)){return true;}if(nativeOnError instanceof Function){for(var _len=arguments.length,args=new Array(_len>1?_len-1:0),_key=1;_key<_len;_key++){args[_key-1]=arguments[_key];}return nativeOnError.apply(window,[error,...args]);}return false;};}function hit(source){var ADGUARD_PREFIX="[AdGuard]";if(!source.verbose){return;}try{var trace=console.trace.bind(console);var label="".concat(ADGUARD_PREFIX," ");if(source.engine==="corelibs"){label+=source.ruleText;}else {if(source.domainName){label+="".concat(source.domainName);}if(source.args){label+="#%#//scriptlet('".concat(source.name,"', '").concat(source.args.join("', '"),"')");}else {label+="#%#//scriptlet('".concat(source.name,"')");}}if(trace){trace(label);}}catch(e){}if(typeof window.__debug==="function"){window.__debug(source);}}function isEmptyObject(obj){return Object.keys(obj).length===0&&!obj.prototype;}var updatedArgs=args?[].concat(source).concat(args):[source];try{abortOnPropertyWrite.apply(this,updatedArgs);if(source.uniqueId){Object.defineProperty(Window.prototype.toString,uniqueIdentifier,{value:flag,enumerable:false,writable:false,configurable:false});}}catch(e){console.log(e);}}function abortOnStackTrace(source,args){var flag="done";var uniqueIdentifier=source.uniqueId+source.name+"_"+(Array.isArray(args)?args.join("_"):"");if(source.uniqueId){if(Window.prototype.toString[uniqueIdentifier]===flag){return;}}function abortOnStackTrace(source,property,stack){if(!property||!stack){return;}var rid=randomId();var abort=function abort(){hit(source);throw new ReferenceError(rid);};var setChainPropAccess=function setChainPropAccess(owner,property){var chainInfo=getPropertyInChain(owner,property);var base=chainInfo.base;var prop=chainInfo.prop,chain=chainInfo.chain;if(chain){var setter=function setter(a){base=a;if(a instanceof Object){setChainPropAccess(a,chain);}};Object.defineProperty(owner,prop,{get:function get(){return base;},set:setter});return;}if(!stack.match(/^(inlineScript|injectedScript)$/)&&!isValidStrPattern(stack)){logMessage(source,"Invalid parameter: ".concat(stack));return;}var descriptorWrapper=Object.assign(getDescriptorAddon(),{value:base[prop],get(){if(!this.isAbortingSuspended&&this.isolateCallback(matchStackTrace,stack,new Error().stack)){abort();}return this.value;},set(newValue){if(!this.isAbortingSuspended&&this.isolateCallback(matchStackTrace,stack,new Error().stack)){abort();}this.value=newValue;}});setPropertyAccess(base,prop,{get(){return descriptorWrapper.get.call(descriptorWrapper);},set(newValue){descriptorWrapper.set.call(descriptorWrapper,newValue);}});};setChainPropAccess(window,property);window.onerror=createOnErrorHandler(rid).bind();}function randomId(){return Math.random().toString(36).slice(2,9);}function setPropertyAccess(object,property,descriptor){var currentDescriptor=Object.getOwnPropertyDescriptor(object,property);if(currentDescriptor&&!currentDescriptor.configurable){return false;}Object.defineProperty(object,property,descriptor);return true;}function getPropertyInChain(base,chain){var pos=chain.indexOf(".");if(pos===-1){return {base:base,prop:chain};}var prop=chain.slice(0,pos);if(base===null){return {base:base,prop:prop,chain:chain};}var nextBase=base[prop];chain=chain.slice(pos+1);if((base instanceof Object||typeof base==="object")&&isEmptyObject(base)){return {base:base,prop:prop,chain:chain};}if(nextBase===null){return {base:base,prop:prop,chain:chain};}if(nextBase!==undefined){return getPropertyInChain(nextBase,chain);}Object.defineProperty(base,prop,{configurable:true});return {base:base,prop:prop,chain:chain};}function createOnErrorHandler(rid){var nativeOnError=window.onerror;return function onError(error){if(typeof error==="string"&&error.includes(rid)){return true;}if(nativeOnError instanceof Function){for(var _len=arguments.length,args=new Array(_len>1?_len-1:0),_key=1;_key<_len;_key++){args[_key-1]=arguments[_key];}return nativeOnError.apply(window,[error,...args]);}return false;};}function hit(source){var ADGUARD_PREFIX="[AdGuard]";if(!source.verbose){return;}try{var trace=console.trace.bind(console);var label="".concat(ADGUARD_PREFIX," ");if(source.engine==="corelibs"){label+=source.ruleText;}else {if(source.domainName){label+="".concat(source.domainName);}if(source.args){label+="#%#//scriptlet('".concat(source.name,"', '").concat(source.args.join("', '"),"')");}else {label+="#%#//scriptlet('".concat(source.name,"')");}}if(trace){trace(label);}}catch(e){}if(typeof window.__debug==="function"){window.__debug(source);}}function isValidStrPattern(input){var FORWARD_SLASH="/";var str=escapeRegExp(input);if(input[0]===FORWARD_SLASH&&input[input.length-1]===FORWARD_SLASH){str=input.slice(1,-1);}var isValid;try{isValid=new RegExp(str);isValid=true;}catch(e){isValid=false;}return isValid;}function escapeRegExp(str){return str.replace(/[.*+?^${}()|[\]\\]/g,"\\$&");}function matchStackTrace(stackMatch,stackTrace){if(!stackMatch||stackMatch===""){return true;}var regExpValues=backupRegExpValues();if(shouldAbortInlineOrInjectedScript(stackMatch,stackTrace)){if(regExpValues.length&&regExpValues[0]!==RegExp.$1){restoreRegExpValues(regExpValues);}return true;}var stackRegexp=toRegExp(stackMatch);var refinedStackTrace=stackTrace.split("\n").slice(2).map(function(line){return line.trim();}).join("\n");if(regExpValues.length&&regExpValues[0]!==RegExp.$1){restoreRegExpValues(regExpValues);}return getNativeRegexpTest().call(stackRegexp,refinedStackTrace);}function getDescriptorAddon(){return {isAbortingSuspended:false,isolateCallback(cb){this.isAbortingSuspended=true;try{for(var _len=arguments.length,args=new Array(_len>1?_len-1:0),_key=1;_key<_len;_key++){args[_key-1]=arguments[_key];}var result=cb(...args);this.isAbortingSuspended=false;return result;}catch(_unused){var rid=randomId();this.isAbortingSuspended=false;throw new ReferenceError(rid);}}};}function logMessage(source,message){var forced=arguments.length>2&&arguments[2]!==undefined?arguments[2]:false;var convertMessageToString=arguments.length>3&&arguments[3]!==undefined?arguments[3]:true;var name=source.name,verbose=source.verbose;if(!forced&&!verbose){return;}var nativeConsole=console.log;if(!convertMessageToString){nativeConsole("".concat(name,":"),message);return;}nativeConsole("".concat(name,": ").concat(message));}function toRegExp(rawInput){var input=rawInput||"";var DEFAULT_VALUE=".?";var FORWARD_SLASH="/";if(input===""){return new RegExp(DEFAULT_VALUE);}var delimiterIndex=input.lastIndexOf(FORWARD_SLASH);var flagsPart=input.substring(delimiterIndex+1);var regExpPart=input.substring(0,delimiterIndex+1);var isValidRegExpFlag=function isValidRegExpFlag(flag){if(!flag){return false;}try{new RegExp("",flag);return true;}catch(ex){return false;}};var getRegExpFlags=function getRegExpFlags(regExpStr,flagsStr){if(regExpStr.startsWith(FORWARD_SLASH)&&regExpStr.endsWith(FORWARD_SLASH)&&!regExpStr.endsWith("\\/")&&isValidRegExpFlag(flagsStr)){return flagsStr;}return "";};var flags=getRegExpFlags(regExpPart,flagsPart);if(input.startsWith(FORWARD_SLASH)&&input.endsWith(FORWARD_SLASH)||flags){var regExpInput=flags?regExpPart:input;return new RegExp(regExpInput.slice(1,-1),flags);}var escaped=input.replace(/\\'/g,"'").replace(/\\"/g,'"').replace(/[.*+?^${}()|[\]\\]/g,"\\$&");return new RegExp(escaped);}function isEmptyObject(obj){return Object.keys(obj).length===0&&!obj.prototype;}function getNativeRegexpTest(){var descriptor=Object.getOwnPropertyDescriptor(RegExp.prototype,"test");var nativeRegexTest=descriptor===null||descriptor===void 0?void 0:descriptor.value;if(descriptor&&typeof descriptor.value==="function"){return nativeRegexTest;}throw new Error("RegExp.prototype.test is not a function");}function shouldAbortInlineOrInjectedScript(stackMatch,stackTrace){var INLINE_SCRIPT_STRING="inlineScript";var INJECTED_SCRIPT_STRING="injectedScript";var INJECTED_SCRIPT_MARKER="<anonymous>";var isInlineScript=function isInlineScript(match){return match.includes(INLINE_SCRIPT_STRING);};var isInjectedScript=function isInjectedScript(match){return match.includes(INJECTED_SCRIPT_STRING);};if(!(isInlineScript(stackMatch)||isInjectedScript(stackMatch))){return false;}var documentURL=window.location.href;var pos=documentURL.indexOf("#");if(pos!==-1){documentURL=documentURL.slice(0,pos);}var stackSteps=stackTrace.split("\n").slice(2).map(function(line){return line.trim();});var stackLines=stackSteps.map(function(line){var stack;var getStackTraceValues=/(.*?@)?(\S+)(:\d+)(:\d+)\)?$/.exec(line);if(getStackTraceValues){var _stackURL,_stackURL2;var stackURL=getStackTraceValues[2];var stackLine=getStackTraceValues[3];var stackCol=getStackTraceValues[4];if((_stackURL=stackURL)!==null&&_stackURL!==void 0&&_stackURL.startsWith("(")){stackURL=stackURL.slice(1);}if((_stackURL2=stackURL)!==null&&_stackURL2!==void 0&&_stackURL2.startsWith(INJECTED_SCRIPT_MARKER)){var _stackFunction;stackURL=INJECTED_SCRIPT_STRING;var stackFunction=getStackTraceValues[1]!==undefined?getStackTraceValues[1].slice(0,-1):line.slice(0,getStackTraceValues.index).trim();if((_stackFunction=stackFunction)!==null&&_stackFunction!==void 0&&_stackFunction.startsWith("at")){stackFunction=stackFunction.slice(2).trim();}stack="".concat(stackFunction," ").concat(stackURL).concat(stackLine).concat(stackCol).trim();}else if(stackURL===documentURL){stack="".concat(INLINE_SCRIPT_STRING).concat(stackLine).concat(stackCol).trim();}else {stack="".concat(stackURL).concat(stackLine).concat(stackCol).trim();}}else {stack=line;}return stack;});if(stackLines){for(var index=0;index<stackLines.length;index+=1){if(isInlineScript(stackMatch)&&stackLines[index].startsWith(INLINE_SCRIPT_STRING)&&stackLines[index].match(toRegExp(stackMatch))){return true;}if(isInjectedScript(stackMatch)&&stackLines[index].startsWith(INJECTED_SCRIPT_STRING)&&stackLines[index].match(toRegExp(stackMatch))){return true;}}}return false;}function backupRegExpValues(){try{var arrayOfRegexpValues=[];for(var index=1;index<10;index+=1){var value="$".concat(index);if(!RegExp[value]){break;}arrayOfRegexpValues.push(RegExp[value]);}return arrayOfRegexpValues;}catch(error){return [];}}function restoreRegExpValues(array){if(!array.length){return;}try{var stringPattern="";if(array.length===1){stringPattern="(".concat(array[0],")");}else {stringPattern=array.reduce(function(accumulator,currentValue,currentIndex){if(currentIndex===1){return "(".concat(accumulator,"),(").concat(currentValue,")");}return "".concat(accumulator,",(").concat(currentValue,")");});}var regExpGroup=new RegExp(stringPattern);array.toString().replace(regExpGroup,"");}catch(error){var message="Failed to restore RegExp values: ".concat(error);console.log(message);}}var updatedArgs=args?[].concat(source).concat(args):[source];try{abortOnStackTrace.apply(this,updatedArgs);if(source.uniqueId){Object.defineProperty(Window.prototype.toString,uniqueIdentifier,{value:flag,enumerable:false,writable:false,configurable:false});}}catch(e){console.log(e);}}function adjustSetInterval(source,args){var flag="done";var uniqueIdentifier=source.uniqueId+source.name+"_"+(Array.isArray(args)?args.join("_"):"");if(source.uniqueId){if(Window.prototype.toString[uniqueIdentifier]===flag){return;}}function adjustSetInterval(source,matchCallback,matchDelay,boost){var nativeSetInterval=window.setInterval;var matchRegexp=toRegExp(matchCallback);var intervalWrapper=function intervalWrapper(callback,delay){if(!isValidCallback(callback)){var message="Scriptlet can't be applied because of invalid callback: '".concat(String(callback),"'");logMessage(source,message);}else if(matchRegexp.test(callback.toString())&&isDelayMatched(matchDelay,delay)){delay*=getBoostMultiplier(boost);hit(source);}for(var _len=arguments.length,args=new Array(_len>2?_len-2:0),_key=2;_key<_len;_key++){args[_key-2]=arguments[_key];}return nativeSetInterval.apply(window,[callback,delay,...args]);};window.setInterval=intervalWrapper;}function hit(source){var ADGUARD_PREFIX="[AdGuard]";if(!source.verbose){return;}try{var trace=console.trace.bind(console);var label="".concat(ADGUARD_PREFIX," ");if(source.engine==="corelibs"){label+=source.ruleText;}else {if(source.domainName){label+="".concat(source.domainName);}if(source.args){label+="#%#//scriptlet('".concat(source.name,"', '").concat(source.args.join("', '"),"')");}else {label+="#%#//scriptlet('".concat(source.name,"')");}}if(trace){trace(label);}}catch(e){}if(typeof window.__debug==="function"){window.__debug(source);}}function isValidCallback(callback){return callback instanceof Function||typeof callback==="string";}function toRegExp(rawInput){var input=rawInput||"";var DEFAULT_VALUE=".?";var FORWARD_SLASH="/";if(input===""){return new RegExp(DEFAULT_VALUE);}var delimiterIndex=input.lastIndexOf(FORWARD_SLASH);var flagsPart=input.substring(delimiterIndex+1);var regExpPart=input.substring(0,delimiterIndex+1);var isValidRegExpFlag=function isValidRegExpFlag(flag){if(!flag){return false;}try{new RegExp("",flag);return true;}catch(ex){return false;}};var getRegExpFlags=function getRegExpFlags(regExpStr,flagsStr){if(regExpStr.startsWith(FORWARD_SLASH)&&regExpStr.endsWith(FORWARD_SLASH)&&!regExpStr.endsWith("\\/")&&isValidRegExpFlag(flagsStr)){return flagsStr;}return "";};var flags=getRegExpFlags(regExpPart,flagsPart);if(input.startsWith(FORWARD_SLASH)&&input.endsWith(FORWARD_SLASH)||flags){var regExpInput=flags?regExpPart:input;return new RegExp(regExpInput.slice(1,-1),flags);}var escaped=input.replace(/\\'/g,"'").replace(/\\"/g,'"').replace(/[.*+?^${}()|[\]\\]/g,"\\$&");return new RegExp(escaped);}function getBoostMultiplier(boost){var DEFAULT_MULTIPLIER=.05;var MIN_MULTIPLIER=.001;var MAX_MULTIPLIER=50;var parsedBoost=parseFloat(boost);var boostMultiplier=nativeIsNaN(parsedBoost)||!nativeIsFinite(parsedBoost)?DEFAULT_MULTIPLIER:parsedBoost;if(boostMultiplier<MIN_MULTIPLIER){boostMultiplier=MIN_MULTIPLIER;}if(boostMultiplier>MAX_MULTIPLIER){boostMultiplier=MAX_MULTIPLIER;}return boostMultiplier;}function isDelayMatched(inputDelay,realDelay){return shouldMatchAnyDelay(inputDelay)||realDelay===getMatchDelay(inputDelay);}function logMessage(source,message){var forced=arguments.length>2&&arguments[2]!==undefined?arguments[2]:false;var convertMessageToString=arguments.length>3&&arguments[3]!==undefined?arguments[3]:true;var name=source.name,verbose=source.verbose;if(!forced&&!verbose){return;}var nativeConsole=console.log;if(!convertMessageToString){nativeConsole("".concat(name,":"),message);return;}nativeConsole("".concat(name,": ").concat(message));}function nativeIsNaN(num){var native=Number.isNaN||window.isNaN;return native(num);}function nativeIsFinite(num){var native=Number.isFinite||window.isFinite;return native(num);}function getMatchDelay(delay){var DEFAULT_DELAY=1e3;var parsedDelay=parseInt(delay,10);var delayMatch=nativeIsNaN(parsedDelay)?DEFAULT_DELAY:parsedDelay;return delayMatch;}function shouldMatchAnyDelay(delay){return delay==="*";}var updatedArgs=args?[].concat(source).concat(args):[source];try{adjustSetInterval.apply(this,updatedArgs);if(source.uniqueId){Object.defineProperty(Window.prototype.toString,uniqueIdentifier,{value:flag,enumerable:false,writable:false,configurable:false});}}catch(e){console.log(e);}}function adjustSetTimeout(source,args){var flag="done";var uniqueIdentifier=source.uniqueId+source.name+"_"+(Array.isArray(args)?args.join("_"):"");if(source.uniqueId){if(Window.prototype.toString[uniqueIdentifier]===flag){return;}}function adjustSetTimeout(source,matchCallback,matchDelay,boost){var nativeSetTimeout=window.setTimeout;var matchRegexp=toRegExp(matchCallback);var timeoutWrapper=function timeoutWrapper(callback,delay){if(!isValidCallback(callback)){var message="Scriptlet can't be applied because of invalid callback: '".concat(String(callback),"'");logMessage(source,message);}else if(matchRegexp.test(callback.toString())&&isDelayMatched(matchDelay,delay)){delay*=getBoostMultiplier(boost);hit(source);}for(var _len=arguments.length,args=new Array(_len>2?_len-2:0),_key=2;_key<_len;_key++){args[_key-2]=arguments[_key];}return nativeSetTimeout.apply(window,[callback,delay,...args]);};window.setTimeout=timeoutWrapper;}function hit(source){var ADGUARD_PREFIX="[AdGuard]";if(!source.verbose){return;}try{var trace=console.trace.bind(console);var label="".concat(ADGUARD_PREFIX," ");if(source.engine==="corelibs"){label+=source.ruleText;}else {if(source.domainName){label+="".concat(source.domainName);}if(source.args){label+="#%#//scriptlet('".concat(source.name,"', '").concat(source.args.join("', '"),"')");}else {label+="#%#//scriptlet('".concat(source.name,"')");}}if(trace){trace(label);}}catch(e){}if(typeof window.__debug==="function"){window.__debug(source);}}function isValidCallback(callback){return callback instanceof Function||typeof callback==="string";}function toRegExp(rawInput){var input=rawInput||"";var DEFAULT_VALUE=".?";var FORWARD_SLASH="/";if(input===""){return new RegExp(DEFAULT_VALUE);}var delimiterIndex=input.lastIndexOf(FORWARD_SLASH);var flagsPart=input.substring(delimiterIndex+1);var regExpPart=input.substring(0,delimiterIndex+1);var isValidRegExpFlag=function isValidRegExpFlag(flag){if(!flag){return false;}try{new RegExp("",flag);return true;}catch(ex){return false;}};var getRegExpFlags=function getRegExpFlags(regExpStr,flagsStr){if(regExpStr.startsWith(FORWARD_SLASH)&&regExpStr.endsWith(FORWARD_SLASH)&&!regExpStr.endsWith("\\/")&&isValidRegExpFlag(flagsStr)){return flagsStr;}return "";};var flags=getRegExpFlags(regExpPart,flagsPart);if(input.startsWith(FORWARD_SLASH)&&input.endsWith(FORWARD_SLASH)||flags){var regExpInput=flags?regExpPart:input;return new RegExp(regExpInput.slice(1,-1),flags);}var escaped=input.replace(/\\'/g,"'").replace(/\\"/g,'"').replace(/[.*+?^${}()|[\]\\]/g,"\\$&");return new RegExp(escaped);}function getBoostMultiplier(boost){var DEFAULT_MULTIPLIER=.05;var MIN_MULTIPLIER=.001;var MAX_MULTIPLIER=50;var parsedBoost=parseFloat(boost);var boostMultiplier=nativeIsNaN(parsedBoost)||!nativeIsFinite(parsedBoost)?DEFAULT_MULTIPLIER:parsedBoost;if(boostMultiplier<MIN_MULTIPLIER){boostMultiplier=MIN_MULTIPLIER;}if(boostMultiplier>MAX_MULTIPLIER){boostMultiplier=MAX_MULTIPLIER;}return boostMultiplier;}function isDelayMatched(inputDelay,realDelay){return shouldMatchAnyDelay(inputDelay)||realDelay===getMatchDelay(inputDelay);}function logMessage(source,message){var forced=arguments.length>2&&arguments[2]!==undefined?arguments[2]:false;var convertMessageToString=arguments.length>3&&arguments[3]!==undefined?arguments[3]:true;var name=source.name,verbose=source.verbose;if(!forced&&!verbose){return;}var nativeConsole=console.log;if(!convertMessageToString){nativeConsole("".concat(name,":"),message);return;}nativeConsole("".concat(name,": ").concat(message));}function nativeIsNaN(num){var native=Number.isNaN||window.isNaN;return native(num);}function nativeIsFinite(num){var native=Number.isFinite||window.isFinite;return native(num);}function getMatchDelay(delay){var DEFAULT_DELAY=1e3;var parsedDelay=parseInt(delay,10);var delayMatch=nativeIsNaN(parsedDelay)?DEFAULT_DELAY:parsedDelay;return delayMatch;}function shouldMatchAnyDelay(delay){return delay==="*";}var updatedArgs=args?[].concat(source).concat(args):[source];try{adjustSetTimeout.apply(this,updatedArgs);if(source.uniqueId){Object.defineProperty(Window.prototype.toString,uniqueIdentifier,{value:flag,enumerable:false,writable:false,configurable:false});}}catch(e){console.log(e);}}function callNoThrow(source,args){var flag="done";var uniqueIdentifier=source.uniqueId+source.name+"_"+(Array.isArray(args)?args.join("_"):"");if(source.uniqueId){if(Window.prototype.toString[uniqueIdentifier]===flag){return;}}function callNoThrow(source,functionName){if(!functionName){return;}var _getPropertyInChain=getPropertyInChain(window,functionName),base=_getPropertyInChain.base,prop=_getPropertyInChain.prop;if(!base||!prop||typeof base[prop]!=="function"){var message="".concat(functionName," is not a function");logMessage(source,message);return;}var objectWrapper=function objectWrapper(){var result;try{result=Reflect.apply(...arguments);}catch(e){var _message="Error calling ".concat(functionName,": ").concat(e.message);logMessage(source,_message);}hit(source);return result;};var objectHandler={apply:objectWrapper};base[prop]=new Proxy(base[prop],objectHandler);}function hit(source){var ADGUARD_PREFIX="[AdGuard]";if(!source.verbose){return;}try{var trace=console.trace.bind(console);var label="".concat(ADGUARD_PREFIX," ");if(source.engine==="corelibs"){label+=source.ruleText;}else {if(source.domainName){label+="".concat(source.domainName);}if(source.args){label+="#%#//scriptlet('".concat(source.name,"', '").concat(source.args.join("', '"),"')");}else {label+="#%#//scriptlet('".concat(source.name,"')");}}if(trace){trace(label);}}catch(e){}if(typeof window.__debug==="function"){window.__debug(source);}}function getPropertyInChain(base,chain){var pos=chain.indexOf(".");if(pos===-1){return {base:base,prop:chain};}var prop=chain.slice(0,pos);if(base===null){return {base:base,prop:prop,chain:chain};}var nextBase=base[prop];chain=chain.slice(pos+1);if((base instanceof Object||typeof base==="object")&&isEmptyObject(base)){return {base:base,prop:prop,chain:chain};}if(nextBase===null){return {base:base,prop:prop,chain:chain};}if(nextBase!==undefined){return getPropertyInChain(nextBase,chain);}Object.defineProperty(base,prop,{configurable:true});return {base:base,prop:prop,chain:chain};}function logMessage(source,message){var forced=arguments.length>2&&arguments[2]!==undefined?arguments[2]:false;var convertMessageToString=arguments.length>3&&arguments[3]!==undefined?arguments[3]:true;var name=source.name,verbose=source.verbose;if(!forced&&!verbose){return;}var nativeConsole=console.log;if(!convertMessageToString){nativeConsole("".concat(name,":"),message);return;}nativeConsole("".concat(name,": ").concat(message));}function isEmptyObject(obj){return Object.keys(obj).length===0&&!obj.prototype;}var updatedArgs=args?[].concat(source).concat(args):[source];try{callNoThrow.apply(this,updatedArgs);if(source.uniqueId){Object.defineProperty(Window.prototype.toString,uniqueIdentifier,{value:flag,enumerable:false,writable:false,configurable:false});}}catch(e){console.log(e);}}function debugCurrentInlineScript(source,args){var flag="done";var uniqueIdentifier=source.uniqueId+source.name+"_"+(Array.isArray(args)?args.join("_"):"");if(source.uniqueId){if(Window.prototype.toString[uniqueIdentifier]===flag){return;}}function debugCurrentInlineScript(source,property,search){var searchRegexp=toRegExp(search);var rid=randomId();var getCurrentScript=function getCurrentScript(){if("currentScript"in document){return document.currentScript;}var scripts=document.getElementsByTagName("script");return scripts[scripts.length-1];};var ourScript=getCurrentScript();var abort=function abort(){var scriptEl=getCurrentScript();if(!scriptEl){return;}var content=scriptEl.textContent;try{var textContentGetter=Object.getOwnPropertyDescriptor(Node.prototype,"textContent").get;content=textContentGetter.call(scriptEl);}catch(e){}if(scriptEl instanceof HTMLScriptElement&&content.length>0&&scriptEl!==ourScript&&searchRegexp.test(content)){hit(source);debugger;}};var setChainPropAccess=function setChainPropAccess(owner,property){var chainInfo=getPropertyInChain(owner,property);var base=chainInfo.base;var prop=chainInfo.prop,chain=chainInfo.chain;if(base instanceof Object===false&&base===null){var props=property.split(".");var propIndex=props.indexOf(prop);var baseName=props[propIndex-1];var message="The scriptlet had been executed before the ".concat(baseName," was loaded.");logMessage(message,source.verbose);return;}if(chain){var setter=function setter(a){base=a;if(a instanceof Object){setChainPropAccess(a,chain);}};Object.defineProperty(owner,prop,{get:function get(){return base;},set:setter});return;}var currentValue=base[prop];setPropertyAccess(base,prop,{set:function set(value){abort();currentValue=value;},get:function get(){abort();return currentValue;}});};setChainPropAccess(window,property);window.onerror=createOnErrorHandler(rid).bind();}function randomId(){return Math.random().toString(36).slice(2,9);}function setPropertyAccess(object,property,descriptor){var currentDescriptor=Object.getOwnPropertyDescriptor(object,property);if(currentDescriptor&&!currentDescriptor.configurable){return false;}Object.defineProperty(object,property,descriptor);return true;}function getPropertyInChain(base,chain){var pos=chain.indexOf(".");if(pos===-1){return {base:base,prop:chain};}var prop=chain.slice(0,pos);if(base===null){return {base:base,prop:prop,chain:chain};}var nextBase=base[prop];chain=chain.slice(pos+1);if((base instanceof Object||typeof base==="object")&&isEmptyObject(base)){return {base:base,prop:prop,chain:chain};}if(nextBase===null){return {base:base,prop:prop,chain:chain};}if(nextBase!==undefined){return getPropertyInChain(nextBase,chain);}Object.defineProperty(base,prop,{configurable:true});return {base:base,prop:prop,chain:chain};}function toRegExp(rawInput){var input=rawInput||"";var DEFAULT_VALUE=".?";var FORWARD_SLASH="/";if(input===""){return new RegExp(DEFAULT_VALUE);}var delimiterIndex=input.lastIndexOf(FORWARD_SLASH);var flagsPart=input.substring(delimiterIndex+1);var regExpPart=input.substring(0,delimiterIndex+1);var isValidRegExpFlag=function isValidRegExpFlag(flag){if(!flag){return false;}try{new RegExp("",flag);return true;}catch(ex){return false;}};var getRegExpFlags=function getRegExpFlags(regExpStr,flagsStr){if(regExpStr.startsWith(FORWARD_SLASH)&&regExpStr.endsWith(FORWARD_SLASH)&&!regExpStr.endsWith("\\/")&&isValidRegExpFlag(flagsStr)){return flagsStr;}return "";};var flags=getRegExpFlags(regExpPart,flagsPart);if(input.startsWith(FORWARD_SLASH)&&input.endsWith(FORWARD_SLASH)||flags){var regExpInput=flags?regExpPart:input;return new RegExp(regExpInput.slice(1,-1),flags);}var escaped=input.replace(/\\'/g,"'").replace(/\\"/g,'"').replace(/[.*+?^${}()|[\]\\]/g,"\\$&");return new RegExp(escaped);}function createOnErrorHandler(rid){var nativeOnError=window.onerror;return function onError(error){if(typeof error==="string"&&error.includes(rid)){return true;}if(nativeOnError instanceof Function){for(var _len=arguments.length,args=new Array(_len>1?_len-1:0),_key=1;_key<_len;_key++){args[_key-1]=arguments[_key];}return nativeOnError.apply(window,[error,...args]);}return false;};}function hit(source){var ADGUARD_PREFIX="[AdGuard]";if(!source.verbose){return;}try{var trace=console.trace.bind(console);var label="".concat(ADGUARD_PREFIX," ");if(source.engine==="corelibs"){label+=source.ruleText;}else {if(source.domainName){label+="".concat(source.domainName);}if(source.args){label+="#%#//scriptlet('".concat(source.name,"', '").concat(source.args.join("', '"),"')");}else {label+="#%#//scriptlet('".concat(source.name,"')");}}if(trace){trace(label);}}catch(e){}if(typeof window.__debug==="function"){window.__debug(source);}}function logMessage(source,message){var forced=arguments.length>2&&arguments[2]!==undefined?arguments[2]:false;var convertMessageToString=arguments.length>3&&arguments[3]!==undefined?arguments[3]:true;var name=source.name,verbose=source.verbose;if(!forced&&!verbose){return;}var nativeConsole=console.log;if(!convertMessageToString){nativeConsole("".concat(name,":"),message);return;}nativeConsole("".concat(name,": ").concat(message));}function isEmptyObject(obj){return Object.keys(obj).length===0&&!obj.prototype;}var updatedArgs=args?[].concat(source).concat(args):[source];try{debugCurrentInlineScript.apply(this,updatedArgs);if(source.uniqueId){Object.defineProperty(Window.prototype.toString,uniqueIdentifier,{value:flag,enumerable:false,writable:false,configurable:false});}}catch(e){console.log(e);}}function debugOnPropertyRead(source,args){var flag="done";var uniqueIdentifier=source.uniqueId+source.name+"_"+(Array.isArray(args)?args.join("_"):"");if(source.uniqueId){if(Window.prototype.toString[uniqueIdentifier]===flag){return;}}function debugOnPropertyRead(source,property){if(!property){return;}var rid=randomId();var abort=function abort(){hit(source);debugger;};var setChainPropAccess=function setChainPropAccess(owner,property){var chainInfo=getPropertyInChain(owner,property);var base=chainInfo.base;var prop=chainInfo.prop,chain=chainInfo.chain;if(chain){var setter=function setter(a){base=a;if(a instanceof Object){setChainPropAccess(a,chain);}};Object.defineProperty(owner,prop,{get:function get(){return base;},set:setter});return;}setPropertyAccess(base,prop,{get:abort,set:noopFunc});};setChainPropAccess(window,property);window.onerror=createOnErrorHandler(rid).bind();}function randomId(){return Math.random().toString(36).slice(2,9);}function setPropertyAccess(object,property,descriptor){var currentDescriptor=Object.getOwnPropertyDescriptor(object,property);if(currentDescriptor&&!currentDescriptor.configurable){return false;}Object.defineProperty(object,property,descriptor);return true;}function getPropertyInChain(base,chain){var pos=chain.indexOf(".");if(pos===-1){return {base:base,prop:chain};}var prop=chain.slice(0,pos);if(base===null){return {base:base,prop:prop,chain:chain};}var nextBase=base[prop];chain=chain.slice(pos+1);if((base instanceof Object||typeof base==="object")&&isEmptyObject(base)){return {base:base,prop:prop,chain:chain};}if(nextBase===null){return {base:base,prop:prop,chain:chain};}if(nextBase!==undefined){return getPropertyInChain(nextBase,chain);}Object.defineProperty(base,prop,{configurable:true});return {base:base,prop:prop,chain:chain};}function createOnErrorHandler(rid){var nativeOnError=window.onerror;return function onError(error){if(typeof error==="string"&&error.includes(rid)){return true;}if(nativeOnError instanceof Function){for(var _len=arguments.length,args=new Array(_len>1?_len-1:0),_key=1;_key<_len;_key++){args[_key-1]=arguments[_key];}return nativeOnError.apply(window,[error,...args]);}return false;};}function hit(source){var ADGUARD_PREFIX="[AdGuard]";if(!source.verbose){return;}try{var trace=console.trace.bind(console);var label="".concat(ADGUARD_PREFIX," ");if(source.engine==="corelibs"){label+=source.ruleText;}else {if(source.domainName){label+="".concat(source.domainName);}if(source.args){label+="#%#//scriptlet('".concat(source.name,"', '").concat(source.args.join("', '"),"')");}else {label+="#%#//scriptlet('".concat(source.name,"')");}}if(trace){trace(label);}}catch(e){}if(typeof window.__debug==="function"){window.__debug(source);}}function noopFunc(){}function isEmptyObject(obj){return Object.keys(obj).length===0&&!obj.prototype;}var updatedArgs=args?[].concat(source).concat(args):[source];try{debugOnPropertyRead.apply(this,updatedArgs);if(source.uniqueId){Object.defineProperty(Window.prototype.toString,uniqueIdentifier,{value:flag,enumerable:false,writable:false,configurable:false});}}catch(e){console.log(e);}}function debugOnPropertyWrite(source,args){var flag="done";var uniqueIdentifier=source.uniqueId+source.name+"_"+(Array.isArray(args)?args.join("_"):"");if(source.uniqueId){if(Window.prototype.toString[uniqueIdentifier]===flag){return;}}function debugOnPropertyWrite(source,property){if(!property){return;}var rid=randomId();var abort=function abort(){hit(source);debugger;};var setChainPropAccess=function setChainPropAccess(owner,property){var chainInfo=getPropertyInChain(owner,property);var base=chainInfo.base;var prop=chainInfo.prop,chain=chainInfo.chain;if(chain){var setter=function setter(a){base=a;if(a instanceof Object){setChainPropAccess(a,chain);}};Object.defineProperty(owner,prop,{get:function get(){return base;},set:setter});return;}setPropertyAccess(base,prop,{set:abort});};setChainPropAccess(window,property);window.onerror=createOnErrorHandler(rid).bind();}function randomId(){return Math.random().toString(36).slice(2,9);}function setPropertyAccess(object,property,descriptor){var currentDescriptor=Object.getOwnPropertyDescriptor(object,property);if(currentDescriptor&&!currentDescriptor.configurable){return false;}Object.defineProperty(object,property,descriptor);return true;}function getPropertyInChain(base,chain){var pos=chain.indexOf(".");if(pos===-1){return {base:base,prop:chain};}var prop=chain.slice(0,pos);if(base===null){return {base:base,prop:prop,chain:chain};}var nextBase=base[prop];chain=chain.slice(pos+1);if((base instanceof Object||typeof base==="object")&&isEmptyObject(base)){return {base:base,prop:prop,chain:chain};}if(nextBase===null){return {base:base,prop:prop,chain:chain};}if(nextBase!==undefined){return getPropertyInChain(nextBase,chain);}Object.defineProperty(base,prop,{configurable:true});return {base:base,prop:prop,chain:chain};}function createOnErrorHandler(rid){var nativeOnError=window.onerror;return function onError(error){if(typeof error==="string"&&error.includes(rid)){return true;}if(nativeOnError instanceof Function){for(var _len=arguments.length,args=new Array(_len>1?_len-1:0),_key=1;_key<_len;_key++){args[_key-1]=arguments[_key];}return nativeOnError.apply(window,[error,...args]);}return false;};}function hit(source){var ADGUARD_PREFIX="[AdGuard]";if(!source.verbose){return;}try{var trace=console.trace.bind(console);var label="".concat(ADGUARD_PREFIX," ");if(source.engine==="corelibs"){label+=source.ruleText;}else {if(source.domainName){label+="".concat(source.domainName);}if(source.args){label+="#%#//scriptlet('".concat(source.name,"', '").concat(source.args.join("', '"),"')");}else {label+="#%#//scriptlet('".concat(source.name,"')");}}if(trace){trace(label);}}catch(e){}if(typeof window.__debug==="function"){window.__debug(source);}}function isEmptyObject(obj){return Object.keys(obj).length===0&&!obj.prototype;}var updatedArgs=args?[].concat(source).concat(args):[source];try{debugOnPropertyWrite.apply(this,updatedArgs);if(source.uniqueId){Object.defineProperty(Window.prototype.toString,uniqueIdentifier,{value:flag,enumerable:false,writable:false,configurable:false});}}catch(e){console.log(e);}}function dirString(source,args){var flag="done";var uniqueIdentifier=source.uniqueId+source.name+"_"+(Array.isArray(args)?args.join("_"):"");if(source.uniqueId){if(Window.prototype.toString[uniqueIdentifier]===flag){return;}}function dirString(source,times){var _console=console,dir=_console.dir;function dirWrapper(object){if(typeof dir==="function"){dir.call(this,object);}hit(source);}console.dir=dirWrapper;}function hit(source){var ADGUARD_PREFIX="[AdGuard]";if(!source.verbose){return;}try{var trace=console.trace.bind(console);var label="".concat(ADGUARD_PREFIX," ");if(source.engine==="corelibs"){label+=source.ruleText;}else {if(source.domainName){label+="".concat(source.domainName);}if(source.args){label+="#%#//scriptlet('".concat(source.name,"', '").concat(source.args.join("', '"),"')");}else {label+="#%#//scriptlet('".concat(source.name,"')");}}if(trace){trace(label);}}catch(e){}if(typeof window.__debug==="function"){window.__debug(source);}}var updatedArgs=args?[].concat(source).concat(args):[source];try{dirString.apply(this,updatedArgs);if(source.uniqueId){Object.defineProperty(Window.prototype.toString,uniqueIdentifier,{value:flag,enumerable:false,writable:false,configurable:false});}}catch(e){console.log(e);}}function disableNewtabLinks(source,args){var flag="done";var uniqueIdentifier=source.uniqueId+source.name+"_"+(Array.isArray(args)?args.join("_"):"");if(source.uniqueId){if(Window.prototype.toString[uniqueIdentifier]===flag){return;}}function disableNewtabLinks(source){document.addEventListener("click",function(ev){var target=ev.target;while(target!==null){if(target.localName==="a"&&target.hasAttribute("target")){ev.stopPropagation();ev.preventDefault();hit(source);break;}target=target.parentNode;}});}function hit(source){var ADGUARD_PREFIX="[AdGuard]";if(!source.verbose){return;}try{var trace=console.trace.bind(console);var label="".concat(ADGUARD_PREFIX," ");if(source.engine==="corelibs"){label+=source.ruleText;}else {if(source.domainName){label+="".concat(source.domainName);}if(source.args){label+="#%#//scriptlet('".concat(source.name,"', '").concat(source.args.join("', '"),"')");}else {label+="#%#//scriptlet('".concat(source.name,"')");}}if(trace){trace(label);}}catch(e){}if(typeof window.__debug==="function"){window.__debug(source);}}var updatedArgs=args?[].concat(source).concat(args):[source];try{disableNewtabLinks.apply(this,updatedArgs);if(source.uniqueId){Object.defineProperty(Window.prototype.toString,uniqueIdentifier,{value:flag,enumerable:false,writable:false,configurable:false});}}catch(e){console.log(e);}}function evalDataPrune(source,args){var flag="done";var uniqueIdentifier=source.uniqueId+source.name+"_"+(Array.isArray(args)?args.join("_"):"");if(source.uniqueId){if(Window.prototype.toString[uniqueIdentifier]===flag){return;}}function evalDataPrune(source,propsToRemove,requiredInitialProps,stack){var prunePaths=getPrunePath(propsToRemove);var requiredPaths=getPrunePath(requiredInitialProps);var nativeObjects={nativeStringify:window.JSON.stringify};var evalWrapper=function evalWrapper(target,thisArg,args){var data=Reflect.apply(target,thisArg,args);if(typeof data==="object"){data=jsonPruner(source,data,prunePaths,requiredPaths,stack,nativeObjects);}return data;};var evalHandler={apply:evalWrapper};window.eval=new Proxy(window.eval,evalHandler);}function hit(source){var ADGUARD_PREFIX="[AdGuard]";if(!source.verbose){return;}try{var trace=console.trace.bind(console);var label="".concat(ADGUARD_PREFIX," ");if(source.engine==="corelibs"){label+=source.ruleText;}else {if(source.domainName){label+="".concat(source.domainName);}if(source.args){label+="#%#//scriptlet('".concat(source.name,"', '").concat(source.args.join("', '"),"')");}else {label+="#%#//scriptlet('".concat(source.name,"')");}}if(trace){trace(label);}}catch(e){}if(typeof window.__debug==="function"){window.__debug(source);}}function matchStackTrace(stackMatch,stackTrace){if(!stackMatch||stackMatch===""){return true;}var regExpValues=backupRegExpValues();if(shouldAbortInlineOrInjectedScript(stackMatch,stackTrace)){if(regExpValues.length&&regExpValues[0]!==RegExp.$1){restoreRegExpValues(regExpValues);}return true;}var stackRegexp=toRegExp(stackMatch);var refinedStackTrace=stackTrace.split("\n").slice(2).map(function(line){return line.trim();}).join("\n");if(regExpValues.length&&regExpValues[0]!==RegExp.$1){restoreRegExpValues(regExpValues);}return getNativeRegexpTest().call(stackRegexp,refinedStackTrace);}function getWildcardPropertyInChain(base,chain){var lookThrough=arguments.length>2&&arguments[2]!==undefined?arguments[2]:false;var output=arguments.length>3&&arguments[3]!==undefined?arguments[3]:[];var pos=chain.indexOf(".");if(pos===-1){if(chain==="*"||chain==="[]"){for(var key in base){if(Object.prototype.hasOwnProperty.call(base,key)){output.push({base:base,prop:key});}}}else {output.push({base:base,prop:chain});}return output;}var prop=chain.slice(0,pos);var shouldLookThrough=prop==="[]"&&Array.isArray(base)||prop==="*"&&base instanceof Object;if(shouldLookThrough){var nextProp=chain.slice(pos+1);var baseKeys=Object.keys(base);baseKeys.forEach(function(key){var item=base[key];getWildcardPropertyInChain(item,nextProp,lookThrough,output);});}if(Array.isArray(base)){base.forEach(function(key){var nextBase=key;if(nextBase!==undefined){getWildcardPropertyInChain(nextBase,chain,lookThrough,output);}});}var nextBase=base[prop];chain=chain.slice(pos+1);if(nextBase!==undefined){getWildcardPropertyInChain(nextBase,chain,lookThrough,output);}return output;}function logMessage(source,message){var forced=arguments.length>2&&arguments[2]!==undefined?arguments[2]:false;var convertMessageToString=arguments.length>3&&arguments[3]!==undefined?arguments[3]:true;var name=source.name,verbose=source.verbose;if(!forced&&!verbose){return;}var nativeConsole=console.log;if(!convertMessageToString){nativeConsole("".concat(name,":"),message);return;}nativeConsole("".concat(name,": ").concat(message));}function toRegExp(rawInput){var input=rawInput||"";var DEFAULT_VALUE=".?";var FORWARD_SLASH="/";if(input===""){return new RegExp(DEFAULT_VALUE);}var delimiterIndex=input.lastIndexOf(FORWARD_SLASH);var flagsPart=input.substring(delimiterIndex+1);var regExpPart=input.substring(0,delimiterIndex+1);var isValidRegExpFlag=function isValidRegExpFlag(flag){if(!flag){return false;}try{new RegExp("",flag);return true;}catch(ex){return false;}};var getRegExpFlags=function getRegExpFlags(regExpStr,flagsStr){if(regExpStr.startsWith(FORWARD_SLASH)&&regExpStr.endsWith(FORWARD_SLASH)&&!regExpStr.endsWith("\\/")&&isValidRegExpFlag(flagsStr)){return flagsStr;}return "";};var flags=getRegExpFlags(regExpPart,flagsPart);if(input.startsWith(FORWARD_SLASH)&&input.endsWith(FORWARD_SLASH)||flags){var regExpInput=flags?regExpPart:input;return new RegExp(regExpInput.slice(1,-1),flags);}var escaped=input.replace(/\\'/g,"'").replace(/\\"/g,'"').replace(/[.*+?^${}()|[\]\\]/g,"\\$&");return new RegExp(escaped);}function isPruningNeeded(source,root,prunePaths,requiredPaths,stack,nativeObjects){if(!root){return false;}var nativeStringify=nativeObjects.nativeStringify;var shouldProcess;if(prunePaths.length===0&&requiredPaths.length>0){var rootString=nativeStringify(root);var matchRegex=toRegExp(requiredPaths.join(""));var shouldLog=matchRegex.test(rootString);if(shouldLog){logMessage(source,"".concat(window.location.hostname,"\n").concat(nativeStringify(root,null,2),"\nStack trace:\n").concat(new Error().stack),true);if(root&&typeof root==="object"){logMessage(source,root,true,false);}shouldProcess=false;return shouldProcess;}}if(stack&&!matchStackTrace(stack,new Error().stack||"")){shouldProcess=false;return shouldProcess;}var wildcardSymbols=[".*.","*.",".*",".[].","[].",".[]"];var _loop=function _loop(){var requiredPath=requiredPaths[i];var lastNestedPropName=requiredPath.split(".").pop();var hasWildcard=wildcardSymbols.some(function(symbol){return requiredPath.includes(symbol);});var details=getWildcardPropertyInChain(root,requiredPath,hasWildcard);if(!details.length){shouldProcess=false;return {v:shouldProcess};}shouldProcess=!hasWildcard;for(var j=0;j<details.length;j+=1){var hasRequiredProp=typeof lastNestedPropName==="string"&&details[j].base[lastNestedPropName]!==undefined;if(hasWildcard){shouldProcess=hasRequiredProp||shouldProcess;}else {shouldProcess=hasRequiredProp&&shouldProcess;}}};for(var i=0;i<requiredPaths.length;i+=1){var _ret=_loop();if(typeof _ret==="object")return _ret.v;}return shouldProcess;}function jsonPruner(source,root,prunePaths,requiredPaths,stack,nativeObjects){var nativeStringify=nativeObjects.nativeStringify;if(prunePaths.length===0&&requiredPaths.length===0){logMessage(source,"".concat(window.location.hostname,"\n").concat(nativeStringify(root,null,2),"\nStack trace:\n").concat(new Error().stack),true);if(root&&typeof root==="object"){logMessage(source,root,true,false);}return root;}try{if(isPruningNeeded(source,root,prunePaths,requiredPaths,stack,nativeObjects)===false){return root;}prunePaths.forEach(function(path){var ownerObjArr=getWildcardPropertyInChain(root,path,true);ownerObjArr.forEach(function(ownerObj){if(ownerObj!==undefined&&ownerObj.base){delete ownerObj.base[ownerObj.prop];hit(source);}});});}catch(e){logMessage(source,e);}return root;}function getPrunePath(props){var validPropsString=typeof props==="string"&&props!==undefined&&props!=="";return validPropsString?props.split(/ +/):[];}function getNativeRegexpTest(){var descriptor=Object.getOwnPropertyDescriptor(RegExp.prototype,"test");var nativeRegexTest=descriptor===null||descriptor===void 0?void 0:descriptor.value;if(descriptor&&typeof descriptor.value==="function"){return nativeRegexTest;}throw new Error("RegExp.prototype.test is not a function");}function shouldAbortInlineOrInjectedScript(stackMatch,stackTrace){var INLINE_SCRIPT_STRING="inlineScript";var INJECTED_SCRIPT_STRING="injectedScript";var INJECTED_SCRIPT_MARKER="<anonymous>";var isInlineScript=function isInlineScript(match){return match.includes(INLINE_SCRIPT_STRING);};var isInjectedScript=function isInjectedScript(match){return match.includes(INJECTED_SCRIPT_STRING);};if(!(isInlineScript(stackMatch)||isInjectedScript(stackMatch))){return false;}var documentURL=window.location.href;var pos=documentURL.indexOf("#");if(pos!==-1){documentURL=documentURL.slice(0,pos);}var stackSteps=stackTrace.split("\n").slice(2).map(function(line){return line.trim();});var stackLines=stackSteps.map(function(line){var stack;var getStackTraceValues=/(.*?@)?(\S+)(:\d+)(:\d+)\)?$/.exec(line);if(getStackTraceValues){var _stackURL,_stackURL2;var stackURL=getStackTraceValues[2];var stackLine=getStackTraceValues[3];var stackCol=getStackTraceValues[4];if((_stackURL=stackURL)!==null&&_stackURL!==void 0&&_stackURL.startsWith("(")){stackURL=stackURL.slice(1);}if((_stackURL2=stackURL)!==null&&_stackURL2!==void 0&&_stackURL2.startsWith(INJECTED_SCRIPT_MARKER)){var _stackFunction;stackURL=INJECTED_SCRIPT_STRING;var stackFunction=getStackTraceValues[1]!==undefined?getStackTraceValues[1].slice(0,-1):line.slice(0,getStackTraceValues.index).trim();if((_stackFunction=stackFunction)!==null&&_stackFunction!==void 0&&_stackFunction.startsWith("at")){stackFunction=stackFunction.slice(2).trim();}stack="".concat(stackFunction," ").concat(stackURL).concat(stackLine).concat(stackCol).trim();}else if(stackURL===documentURL){stack="".concat(INLINE_SCRIPT_STRING).concat(stackLine).concat(stackCol).trim();}else {stack="".concat(stackURL).concat(stackLine).concat(stackCol).trim();}}else {stack=line;}return stack;});if(stackLines){for(var index=0;index<stackLines.length;index+=1){if(isInlineScript(stackMatch)&&stackLines[index].startsWith(INLINE_SCRIPT_STRING)&&stackLines[index].match(toRegExp(stackMatch))){return true;}if(isInjectedScript(stackMatch)&&stackLines[index].startsWith(INJECTED_SCRIPT_STRING)&&stackLines[index].match(toRegExp(stackMatch))){return true;}}}return false;}function backupRegExpValues(){try{var arrayOfRegexpValues=[];for(var index=1;index<10;index+=1){var value="$".concat(index);if(!RegExp[value]){break;}arrayOfRegexpValues.push(RegExp[value]);}return arrayOfRegexpValues;}catch(error){return [];}}function restoreRegExpValues(array){if(!array.length){return;}try{var stringPattern="";if(array.length===1){stringPattern="(".concat(array[0],")");}else {stringPattern=array.reduce(function(accumulator,currentValue,currentIndex){if(currentIndex===1){return "(".concat(accumulator,"),(").concat(currentValue,")");}return "".concat(accumulator,",(").concat(currentValue,")");});}var regExpGroup=new RegExp(stringPattern);array.toString().replace(regExpGroup,"");}catch(error){var message="Failed to restore RegExp values: ".concat(error);console.log(message);}}var updatedArgs=args?[].concat(source).concat(args):[source];try{evalDataPrune.apply(this,updatedArgs);if(source.uniqueId){Object.defineProperty(Window.prototype.toString,uniqueIdentifier,{value:flag,enumerable:false,writable:false,configurable:false});}}catch(e){console.log(e);}}function forceWindowClose(source,args){var flag="done";var uniqueIdentifier=source.uniqueId+source.name+"_"+(Array.isArray(args)?args.join("_"):"");if(source.uniqueId){if(Window.prototype.toString[uniqueIdentifier]===flag){return;}}function forceWindowClose(source){var path=arguments.length>1&&arguments[1]!==undefined?arguments[1]:"";if(typeof window.close!=="function"){var message="window.close() is not a function so 'close-window' scriptlet is unavailable";logMessage(source,message);return;}var closeImmediately=function closeImmediately(){try{hit(source);window.close();}catch(e){logMessage(source,e);}};var closeByExtension=function closeByExtension(){var extCall=function extCall(){dispatchEvent(new Event("adguard:scriptlet-close-window"));};window.addEventListener("adguard:subscribed-to-close-window",extCall,{once:true});setTimeout(function(){window.removeEventListener("adguard:subscribed-to-close-window",extCall,{once:true});},5e3);};var shouldClose=function shouldClose(){if(path===""){return true;}var pathRegexp=toRegExp(path);var currentPath="".concat(window.location.pathname).concat(window.location.search);return pathRegexp.test(currentPath);};if(shouldClose()){closeImmediately();if(navigator.userAgent.includes("Chrome")){closeByExtension();}}}function hit(source){var ADGUARD_PREFIX="[AdGuard]";if(!source.verbose){return;}try{var trace=console.trace.bind(console);var label="".concat(ADGUARD_PREFIX," ");if(source.engine==="corelibs"){label+=source.ruleText;}else {if(source.domainName){label+="".concat(source.domainName);}if(source.args){label+="#%#//scriptlet('".concat(source.name,"', '").concat(source.args.join("', '"),"')");}else {label+="#%#//scriptlet('".concat(source.name,"')");}}if(trace){trace(label);}}catch(e){}if(typeof window.__debug==="function"){window.__debug(source);}}function toRegExp(rawInput){var input=rawInput||"";var DEFAULT_VALUE=".?";var FORWARD_SLASH="/";if(input===""){return new RegExp(DEFAULT_VALUE);}var delimiterIndex=input.lastIndexOf(FORWARD_SLASH);var flagsPart=input.substring(delimiterIndex+1);var regExpPart=input.substring(0,delimiterIndex+1);var isValidRegExpFlag=function isValidRegExpFlag(flag){if(!flag){return false;}try{new RegExp("",flag);return true;}catch(ex){return false;}};var getRegExpFlags=function getRegExpFlags(regExpStr,flagsStr){if(regExpStr.startsWith(FORWARD_SLASH)&&regExpStr.endsWith(FORWARD_SLASH)&&!regExpStr.endsWith("\\/")&&isValidRegExpFlag(flagsStr)){return flagsStr;}return "";};var flags=getRegExpFlags(regExpPart,flagsPart);if(input.startsWith(FORWARD_SLASH)&&input.endsWith(FORWARD_SLASH)||flags){var regExpInput=flags?regExpPart:input;return new RegExp(regExpInput.slice(1,-1),flags);}var escaped=input.replace(/\\'/g,"'").replace(/\\"/g,'"').replace(/[.*+?^${}()|[\]\\]/g,"\\$&");return new RegExp(escaped);}function logMessage(source,message){var forced=arguments.length>2&&arguments[2]!==undefined?arguments[2]:false;var convertMessageToString=arguments.length>3&&arguments[3]!==undefined?arguments[3]:true;var name=source.name,verbose=source.verbose;if(!forced&&!verbose){return;}var nativeConsole=console.log;if(!convertMessageToString){nativeConsole("".concat(name,":"),message);return;}nativeConsole("".concat(name,": ").concat(message));}var updatedArgs=args?[].concat(source).concat(args):[source];try{forceWindowClose.apply(this,updatedArgs);if(source.uniqueId){Object.defineProperty(Window.prototype.toString,uniqueIdentifier,{value:flag,enumerable:false,writable:false,configurable:false});}}catch(e){console.log(e);}}function hideInShadowDom(source,args){var flag="done";var uniqueIdentifier=source.uniqueId+source.name+"_"+(Array.isArray(args)?args.join("_"):"");if(source.uniqueId){if(Window.prototype.toString[uniqueIdentifier]===flag){return;}}function hideInShadowDom(source,selector,baseSelector){if(!Element.prototype.attachShadow){return;}var hideElement=function hideElement(targetElement){var DISPLAY_NONE_CSS="display:none!important;";targetElement.style.cssText=DISPLAY_NONE_CSS;};var hideHandler=function hideHandler(){var hostElements=!baseSelector?findHostElements(document.documentElement):document.querySelectorAll(baseSelector);var _loop=function _loop(){var isHidden=false;var _pierceShadowDom=pierceShadowDom(selector,hostElements),targets=_pierceShadowDom.targets,innerHosts=_pierceShadowDom.innerHosts;targets.forEach(function(targetEl){hideElement(targetEl);isHidden=true;});if(isHidden){hit(source);}hostElements=innerHosts;};while(hostElements.length!==0){_loop();}};hideHandler();observeDOMChanges(hideHandler,true);}function hit(source){var ADGUARD_PREFIX="[AdGuard]";if(!source.verbose){return;}try{var trace=console.trace.bind(console);var label="".concat(ADGUARD_PREFIX," ");if(source.engine==="corelibs"){label+=source.ruleText;}else {if(source.domainName){label+="".concat(source.domainName);}if(source.args){label+="#%#//scriptlet('".concat(source.name,"', '").concat(source.args.join("', '"),"')");}else {label+="#%#//scriptlet('".concat(source.name,"')");}}if(trace){trace(label);}}catch(e){}if(typeof window.__debug==="function"){window.__debug(source);}}function observeDOMChanges(callback){var observeAttrs=arguments.length>1&&arguments[1]!==undefined?arguments[1]:false;var attrsToObserve=arguments.length>2&&arguments[2]!==undefined?arguments[2]:[];var THROTTLE_DELAY_MS=20;var observer=new MutationObserver(throttle(callbackWrapper,THROTTLE_DELAY_MS));var connect=function connect(){if(attrsToObserve.length>0){observer.observe(document.documentElement,{childList:true,subtree:true,attributes:observeAttrs,attributeFilter:attrsToObserve});}else {observer.observe(document.documentElement,{childList:true,subtree:true,attributes:observeAttrs});}};var disconnect=function disconnect(){observer.disconnect();};function callbackWrapper(){disconnect();callback();connect();}connect();}function findHostElements(rootElement){var hosts=[];if(rootElement){var domElems=rootElement.querySelectorAll("*");domElems.forEach(function(el){if(el.shadowRoot){hosts.push(el);}});}return hosts;}function pierceShadowDom(selector,hostElements){var targets=[];var innerHostsAcc=[];hostElements.forEach(function(host){var simpleElems=host.querySelectorAll(selector);targets=targets.concat([].slice.call(simpleElems));var shadowRootElem=host.shadowRoot;var shadowChildren=shadowRootElem.querySelectorAll(selector);targets=targets.concat([].slice.call(shadowChildren));innerHostsAcc.push(findHostElements(shadowRootElem));});var innerHosts=flatten(innerHostsAcc);return {targets:targets,innerHosts:innerHosts};}function flatten(input){var stack=[];input.forEach(function(el){return stack.push(el);});var res=[];while(stack.length){var next=stack.pop();if(Array.isArray(next)){next.forEach(function(el){return stack.push(el);});}else {res.push(next);}}return res.reverse();}function throttle(cb,delay){var wait=false;var savedArgs;var wrapper=function wrapper(){for(var _len=arguments.length,args=new Array(_len),_key=0;_key<_len;_key++){args[_key]=arguments[_key];}if(wait){savedArgs=args;return;}cb(...args);wait=true;setTimeout(function(){wait=false;if(savedArgs){wrapper(...savedArgs);savedArgs=null;}},delay);};return wrapper;}var updatedArgs=args?[].concat(source).concat(args):[source];try{hideInShadowDom.apply(this,updatedArgs);if(source.uniqueId){Object.defineProperty(Window.prototype.toString,uniqueIdentifier,{value:flag,enumerable:false,writable:false,configurable:false});}}catch(e){console.log(e);}}function hrefSanitizer(source,args){var flag="done";var uniqueIdentifier=source.uniqueId+source.name+"_"+(Array.isArray(args)?args.join("_"):"");if(source.uniqueId){if(Window.prototype.toString[uniqueIdentifier]===flag){return;}}function hrefSanitizer(source,selector){var attribute=arguments.length>2&&arguments[2]!==undefined?arguments[2]:"text";if(!selector){logMessage(source,"Selector is required.");return;}var regexpNotValidAtStart=/^(?:[\0- \x7F-\xA9\xAB-\xB4\xB6-\xB9\xBB-\xBF\xD7\xF7\u02C2-\u02C5\u02D2-\u02DF\u02E5-\u02EB\u02ED\u02EF-\u036F\u0375\u0378\u0379\u037E\u0380-\u0385\u0387\u038B\u038D\u03A2\u03F6\u0482-\u0489\u0530\u0557\u0558\u055A-\u055F\u0589-\u05CF\u05EB-\u05EE\u05F3-\u061F\u064B-\u066D\u0670\u06D4\u06D6-\u06E4\u06E7-\u06ED\u06F0-\u06F9\u06FD\u06FE\u0700-\u070F\u0711\u0730-\u074C\u07A6-\u07B0\u07B2-\u07C9\u07EB-\u07F3\u07F6-\u07F9\u07FB-\u07FF\u0816-\u0819\u081B-\u0823\u0825-\u0827\u0829-\u083F\u0859-\u085F\u086B-\u086F\u0888\u088F-\u089F\u08CA-\u0903\u093A-\u093C\u093E-\u094F\u0951-\u0957\u0962-\u0970\u0981-\u0984\u098D\u098E\u0991\u0992\u09A9\u09B1\u09B3-\u09B5\u09BA-\u09BC\u09BE-\u09CD\u09CF-\u09DB\u09DE\u09E2-\u09EF\u09F2-\u09FB\u09FD-\u0A04\u0A0B-\u0A0E\u0A11\u0A12\u0A29\u0A31\u0A34\u0A37\u0A3A-\u0A58\u0A5D\u0A5F-\u0A71\u0A75-\u0A84\u0A8E\u0A92\u0AA9\u0AB1\u0AB4\u0ABA-\u0ABC\u0ABE-\u0ACF\u0AD1-\u0ADF\u0AE2-\u0AF8\u0AFA-\u0B04\u0B0D\u0B0E\u0B11\u0B12\u0B29\u0B31\u0B34\u0B3A-\u0B3C\u0B3E-\u0B5B\u0B5E\u0B62-\u0B70\u0B72-\u0B82\u0B84\u0B8B-\u0B8D\u0B91\u0B96-\u0B98\u0B9B\u0B9D\u0BA0-\u0BA2\u0BA5-\u0BA7\u0BAB-\u0BAD\u0BBA-\u0BCF\u0BD1-\u0C04\u0C0D\u0C11\u0C29\u0C3A-\u0C3C\u0C3E-\u0C57\u0C5B\u0C5C\u0C5E\u0C5F\u0C62-\u0C7F\u0C81-\u0C84\u0C8D\u0C91\u0CA9\u0CB4\u0CBA-\u0CBC\u0CBE-\u0CDC\u0CDF\u0CE2-\u0CF0\u0CF3-\u0D03\u0D0D\u0D11\u0D3B\u0D3C\u0D3E-\u0D4D\u0D4F-\u0D53\u0D57-\u0D5E\u0D62-\u0D79\u0D80-\u0D84\u0D97-\u0D99\u0DB2\u0DBC\u0DBE\u0DBF\u0DC7-\u0E00\u0E31\u0E34-\u0E3F\u0E47-\u0E80\u0E83\u0E85\u0E8B\u0EA4\u0EA6\u0EB1\u0EB4-\u0EBC\u0EBE\u0EBF\u0EC5\u0EC7-\u0EDB\u0EE0-\u0EFF\u0F01-\u0F3F\u0F48\u0F6D-\u0F87\u0F8D-\u0FFF\u102B-\u103E\u1040-\u104F\u1056-\u1059\u105E-\u1060\u1062-\u1064\u1067-\u106D\u1071-\u1074\u1082-\u108D\u108F-\u109F\u10C6\u10C8-\u10CC\u10CE\u10CF\u10FB\u1249\u124E\u124F\u1257\u1259\u125E\u125F\u1289\u128E\u128F\u12B1\u12B6\u12B7\u12BF\u12C1\u12C6\u12C7\u12D7\u1311\u1316\u1317\u135B-\u137F\u1390-\u139F\u13F6\u13F7\u13FE-\u1400\u166D\u166E\u1680\u169B-\u169F\u16EB-\u16F0\u16F9-\u16FF\u1712-\u171E\u1732-\u173F\u1752-\u175F\u176D\u1771-\u177F\u17B4-\u17D6\u17D8-\u17DB\u17DD-\u181F\u1879-\u187F\u1885\u1886\u18A9\u18AB-\u18AF\u18F6-\u18FF\u191F-\u194F\u196E\u196F\u1975-\u197F\u19AC-\u19AF\u19CA-\u19FF\u1A17-\u1A1F\u1A55-\u1AA6\u1AA8-\u1B04\u1B34-\u1B44\u1B4D-\u1B82\u1BA1-\u1BAD\u1BB0-\u1BB9\u1BE6-\u1BFF\u1C24-\u1C4C\u1C50-\u1C59\u1C7E\u1C7F\u1C89-\u1C8F\u1CBB\u1CBC\u1CC0-\u1CE8\u1CED\u1CF4\u1CF7-\u1CF9\u1CFB-\u1CFF\u1DC0-\u1DFF\u1F16\u1F17\u1F1E\u1F1F\u1F46\u1F47\u1F4E\u1F4F\u1F58\u1F5A\u1F5C\u1F5E\u1F7E\u1F7F\u1FB5\u1FBD\u1FBF-\u1FC1\u1FC5\u1FCD-\u1FCF\u1FD4\u1FD5\u1FDC-\u1FDF\u1FED-\u1FF1\u1FF5\u1FFD-\u2070\u2072-\u207E\u2080-\u208F\u209D-\u2101\u2103-\u2106\u2108\u2109\u2114\u2116-\u2118\u211E-\u2123\u2125\u2127\u2129\u212E\u213A\u213B\u2140-\u2144\u214A-\u214D\u214F-\u2182\u2185-\u2BFF\u2CE5-\u2CEA\u2CEF-\u2CF1\u2CF4-\u2CFF\u2D26\u2D28-\u2D2C\u2D2E\u2D2F\u2D68-\u2D6E\u2D70-\u2D7F\u2D97-\u2D9F\u2DA7\u2DAF\u2DB7\u2DBF\u2DC7\u2DCF\u2DD7\u2DDF-\u2E2E\u2E30-\u3004\u3007-\u3030\u3036-\u303A\u303D-\u3040\u3097-\u309C\u30A0\u30FB\u3100-\u3104\u3130\u318F-\u319F\u31C0-\u31EF\u3200-\u33FF\u4DC0-\u4DFF\uA48D-\uA4CF\uA4FE\uA4FF\uA60D-\uA60F\uA620-\uA629\uA62C-\uA63F\uA66F-\uA67E\uA69E\uA69F\uA6E6-\uA716\uA720\uA721\uA789\uA78A\uA7CB-\uA7CF\uA7D2\uA7D4\uA7DA-\uA7F1\uA802\uA806\uA80B\uA823-\uA83F\uA874-\uA881\uA8B4-\uA8F1\uA8F8-\uA8FA\uA8FC\uA8FF-\uA909\uA926-\uA92F\uA947-\uA95F\uA97D-\uA983\uA9B3-\uA9CE\uA9D0-\uA9DF\uA9E5\uA9F0-\uA9F9\uA9FF\uAA29-\uAA3F\uAA43\uAA4C-\uAA5F\uAA77-\uAA79\uAA7B-\uAA7D\uAAB0\uAAB2-\uAAB4\uAAB7\uAAB8\uAABE\uAABF\uAAC1\uAAC3-\uAADA\uAADE\uAADF\uAAEB-\uAAF1\uAAF5-\uAB00\uAB07\uAB08\uAB0F\uAB10\uAB17-\uAB1F\uAB27\uAB2F\uAB5B\uAB6A-\uAB6F\uABE3-\uABFF\uD7A4-\uD7AF\uD7C7-\uD7CA\uD7FC-\uD7FF\uE000-\uF8FF\uFA6E\uFA6F\uFADA-\uFAFF\uFB07-\uFB12\uFB18-\uFB1C\uFB1E\uFB29\uFB37\uFB3D\uFB3F\uFB42\uFB45\uFBB2-\uFBD2\uFD3E-\uFD4F\uFD90\uFD91\uFDC8-\uFDEF\uFDFC-\uFE6F\uFE75\uFEFD-\uFF20\uFF3B-\uFF40\uFF5B-\uFF65\uFFBF-\uFFC1\uFFC8\uFFC9\uFFD0\uFFD1\uFFD8\uFFD9\uFFDD-\uFFFF]|\uD800[\uDC0C\uDC27\uDC3B\uDC3E\uDC4E\uDC4F\uDC5E-\uDC7F\uDCFB-\uDE7F\uDE9D-\uDE9F\uDED1-\uDEFF\uDF20-\uDF2C\uDF41\uDF4A-\uDF4F\uDF76-\uDF7F\uDF9E\uDF9F\uDFC4-\uDFC7\uDFD0-\uDFFF]|\uD801[\uDC9E-\uDCAF\uDCD4-\uDCD7\uDCFC-\uDCFF\uDD28-\uDD2F\uDD64-\uDD6F\uDD7B\uDD8B\uDD93\uDD96\uDDA2\uDDB2\uDDBA\uDDBD-\uDDFF\uDF37-\uDF3F\uDF56-\uDF5F\uDF68-\uDF7F\uDF86\uDFB1\uDFBB-\uDFFF]|\uD802[\uDC06\uDC07\uDC09\uDC36\uDC39-\uDC3B\uDC3D\uDC3E\uDC56-\uDC5F\uDC77-\uDC7F\uDC9F-\uDCDF\uDCF3\uDCF6-\uDCFF\uDD16-\uDD1F\uDD3A-\uDD7F\uDDB8-\uDDBD\uDDC0-\uDDFF\uDE01-\uDE0F\uDE14\uDE18\uDE36-\uDE5F\uDE7D-\uDE7F\uDE9D-\uDEBF\uDEC8\uDEE5-\uDEFF\uDF36-\uDF3F\uDF56-\uDF5F\uDF73-\uDF7F\uDF92-\uDFFF]|\uD803[\uDC49-\uDC7F\uDCB3-\uDCBF\uDCF3-\uDCFF\uDD24-\uDE7F\uDEAA-\uDEAF\uDEB2-\uDEFF\uDF1D-\uDF26\uDF28-\uDF2F\uDF46-\uDF6F\uDF82-\uDFAF\uDFC5-\uDFDF\uDFF7-\uDFFF]|\uD804[\uDC00-\uDC02\uDC38-\uDC70\uDC73\uDC74\uDC76-\uDC82\uDCB0-\uDCCF\uDCE9-\uDD02\uDD27-\uDD43\uDD45\uDD46\uDD48-\uDD4F\uDD73-\uDD75\uDD77-\uDD82\uDDB3-\uDDC0\uDDC5-\uDDD9\uDDDB\uDDDD-\uDDFF\uDE12\uDE2C-\uDE3E\uDE41-\uDE7F\uDE87\uDE89\uDE8E\uDE9E\uDEA9-\uDEAF\uDEDF-\uDF04\uDF0D\uDF0E\uDF11\uDF12\uDF29\uDF31\uDF34\uDF3A-\uDF3C\uDF3E-\uDF4F\uDF51-\uDF5C\uDF62-\uDFFF]|\uD805[\uDC35-\uDC46\uDC4B-\uDC5E\uDC62-\uDC7F\uDCB0-\uDCC3\uDCC6\uDCC8-\uDD7F\uDDAF-\uDDD7\uDDDC-\uDDFF\uDE30-\uDE43\uDE45-\uDE7F\uDEAB-\uDEB7\uDEB9-\uDEFF\uDF1B-\uDF3F\uDF47-\uDFFF]|\uD806[\uDC2C-\uDC9F\uDCE0-\uDCFE\uDD07\uDD08\uDD0A\uDD0B\uDD14\uDD17\uDD30-\uDD3E\uDD40\uDD42-\uDD9F\uDDA8\uDDA9\uDDD1-\uDDE0\uDDE2\uDDE4-\uDDFF\uDE01-\uDE0A\uDE33-\uDE39\uDE3B-\uDE4F\uDE51-\uDE5B\uDE8A-\uDE9C\uDE9E-\uDEAF\uDEF9-\uDFFF]|\uD807[\uDC09\uDC2F-\uDC3F\uDC41-\uDC71\uDC90-\uDCFF\uDD07\uDD0A\uDD31-\uDD45\uDD47-\uDD5F\uDD66\uDD69\uDD8A-\uDD97\uDD99-\uDEDF\uDEF3-\uDF01\uDF03\uDF11\uDF34-\uDFAF\uDFB1-\uDFFF]|\uD808[\uDF9A-\uDFFF]|\uD809[\uDC00-\uDC7F\uDD44-\uDFFF]|[\uD80A\uD80E-\uD810\uD812-\uD819\uD824-\uD82A\uD82D\uD82E\uD830-\uD834\uD836\uD83C-\uD83F\uD87B-\uD87D\uD87F\uD889-\uDBFF][\uDC00-\uDFFF]|\uD80B[\uDC00-\uDF8F\uDFF1-\uDFFF]|\uD80D[\uDC30-\uDC40\uDC47-\uDFFF]|\uD811[\uDE47-\uDFFF]|\uD81A[\uDE39-\uDE3F\uDE5F-\uDE6F\uDEBF-\uDECF\uDEEE-\uDEFF\uDF30-\uDF3F\uDF44-\uDF62\uDF78-\uDF7C\uDF90-\uDFFF]|\uD81B[\uDC00-\uDE3F\uDE80-\uDEFF\uDF4B-\uDF4F\uDF51-\uDF92\uDFA0-\uDFDF\uDFE2\uDFE4-\uDFFF]|\uD821[\uDFF8-\uDFFF]|\uD823[\uDCD6-\uDCFF\uDD09-\uDFFF]|\uD82B[\uDC00-\uDFEF\uDFF4\uDFFC\uDFFF]|\uD82C[\uDD23-\uDD31\uDD33-\uDD4F\uDD53\uDD54\uDD56-\uDD63\uDD68-\uDD6F\uDEFC-\uDFFF]|\uD82F[\uDC6B-\uDC6F\uDC7D-\uDC7F\uDC89-\uDC8F\uDC9A-\uDFFF]|\uD835[\uDC55\uDC9D\uDCA0\uDCA1\uDCA3\uDCA4\uDCA7\uDCA8\uDCAD\uDCBA\uDCBC\uDCC4\uDD06\uDD0B\uDD0C\uDD15\uDD1D\uDD3A\uDD3F\uDD45\uDD47-\uDD49\uDD51\uDEA6\uDEA7\uDEC1\uDEDB\uDEFB\uDF15\uDF35\uDF4F\uDF6F\uDF89\uDFA9\uDFC3\uDFCC-\uDFFF]|\uD837[\uDC00-\uDEFF\uDF1F-\uDF24\uDF2B-\uDFFF]|\uD838[\uDC00-\uDC2F\uDC6E-\uDCFF\uDD2D-\uDD36\uDD3E-\uDD4D\uDD4F-\uDE8F\uDEAE-\uDEBF\uDEEC-\uDFFF]|\uD839[\uDC00-\uDCCF\uDCEC-\uDFDF\uDFE7\uDFEC\uDFEF\uDFFF]|\uD83A[\uDCC5-\uDCFF\uDD44-\uDD4A\uDD4C-\uDFFF]|\uD83B[\uDC00-\uDDFF\uDE04\uDE20\uDE23\uDE25\uDE26\uDE28\uDE33\uDE38\uDE3A\uDE3C-\uDE41\uDE43-\uDE46\uDE48\uDE4A\uDE4C\uDE50\uDE53\uDE55\uDE56\uDE58\uDE5A\uDE5C\uDE5E\uDE60\uDE63\uDE65\uDE66\uDE6B\uDE73\uDE78\uDE7D\uDE7F\uDE8A\uDE9C-\uDEA0\uDEA4\uDEAA\uDEBC-\uDFFF]|\uD869[\uDEE0-\uDEFF]|\uD86D[\uDF3A-\uDF3F]|\uD86E[\uDC1E\uDC1F]|\uD873[\uDEA2-\uDEAF]|\uD87A[\uDFE1-\uDFFF]|\uD87E[\uDE1E-\uDFFF]|\uD884[\uDF4B-\uDF4F]|\uD888[\uDFB0-\uDFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF])+/;var regexpNotValidAtEnd=/(?:[\0- \x7F-\xA9\xAB-\xB4\xB6-\xB9\xBB-\xBF\xD7\xF7\u02C2-\u02C5\u02D2-\u02DF\u02E5-\u02EB\u02ED\u02EF-\u036F\u0375\u0378\u0379\u037E\u0380-\u0385\u0387\u038B\u038D\u03A2\u03F6\u0482-\u0489\u0530\u0557\u0558\u055A-\u055F\u0589-\u05CF\u05EB-\u05EE\u05F3-\u061F\u064B-\u066D\u0670\u06D4\u06D6-\u06E4\u06E7-\u06ED\u06F0-\u06F9\u06FD\u06FE\u0700-\u070F\u0711\u0730-\u074C\u07A6-\u07B0\u07B2-\u07C9\u07EB-\u07F3\u07F6-\u07F9\u07FB-\u07FF\u0816-\u0819\u081B-\u0823\u0825-\u0827\u0829-\u083F\u0859-\u085F\u086B-\u086F\u0888\u088F-\u089F\u08CA-\u0903\u093A-\u093C\u093E-\u094F\u0951-\u0957\u0962-\u0970\u0981-\u0984\u098D\u098E\u0991\u0992\u09A9\u09B1\u09B3-\u09B5\u09BA-\u09BC\u09BE-\u09CD\u09CF-\u09DB\u09DE\u09E2-\u09EF\u09F2-\u09FB\u09FD-\u0A04\u0A0B-\u0A0E\u0A11\u0A12\u0A29\u0A31\u0A34\u0A37\u0A3A-\u0A58\u0A5D\u0A5F-\u0A71\u0A75-\u0A84\u0A8E\u0A92\u0AA9\u0AB1\u0AB4\u0ABA-\u0ABC\u0ABE-\u0ACF\u0AD1-\u0ADF\u0AE2-\u0AF8\u0AFA-\u0B04\u0B0D\u0B0E\u0B11\u0B12\u0B29\u0B31\u0B34\u0B3A-\u0B3C\u0B3E-\u0B5B\u0B5E\u0B62-\u0B70\u0B72-\u0B82\u0B84\u0B8B-\u0B8D\u0B91\u0B96-\u0B98\u0B9B\u0B9D\u0BA0-\u0BA2\u0BA5-\u0BA7\u0BAB-\u0BAD\u0BBA-\u0BCF\u0BD1-\u0C04\u0C0D\u0C11\u0C29\u0C3A-\u0C3C\u0C3E-\u0C57\u0C5B\u0C5C\u0C5E\u0C5F\u0C62-\u0C7F\u0C81-\u0C84\u0C8D\u0C91\u0CA9\u0CB4\u0CBA-\u0CBC\u0CBE-\u0CDC\u0CDF\u0CE2-\u0CF0\u0CF3-\u0D03\u0D0D\u0D11\u0D3B\u0D3C\u0D3E-\u0D4D\u0D4F-\u0D53\u0D57-\u0D5E\u0D62-\u0D79\u0D80-\u0D84\u0D97-\u0D99\u0DB2\u0DBC\u0DBE\u0DBF\u0DC7-\u0E00\u0E31\u0E34-\u0E3F\u0E47-\u0E80\u0E83\u0E85\u0E8B\u0EA4\u0EA6\u0EB1\u0EB4-\u0EBC\u0EBE\u0EBF\u0EC5\u0EC7-\u0EDB\u0EE0-\u0EFF\u0F01-\u0F3F\u0F48\u0F6D-\u0F87\u0F8D-\u0FFF\u102B-\u103E\u1040-\u104F\u1056-\u1059\u105E-\u1060\u1062-\u1064\u1067-\u106D\u1071-\u1074\u1082-\u108D\u108F-\u109F\u10C6\u10C8-\u10CC\u10CE\u10CF\u10FB\u1249\u124E\u124F\u1257\u1259\u125E\u125F\u1289\u128E\u128F\u12B1\u12B6\u12B7\u12BF\u12C1\u12C6\u12C7\u12D7\u1311\u1316\u1317\u135B-\u137F\u1390-\u139F\u13F6\u13F7\u13FE-\u1400\u166D\u166E\u1680\u169B-\u169F\u16EB-\u16F0\u16F9-\u16FF\u1712-\u171E\u1732-\u173F\u1752-\u175F\u176D\u1771-\u177F\u17B4-\u17D6\u17D8-\u17DB\u17DD-\u181F\u1879-\u187F\u1885\u1886\u18A9\u18AB-\u18AF\u18F6-\u18FF\u191F-\u194F\u196E\u196F\u1975-\u197F\u19AC-\u19AF\u19CA-\u19FF\u1A17-\u1A1F\u1A55-\u1AA6\u1AA8-\u1B04\u1B34-\u1B44\u1B4D-\u1B82\u1BA1-\u1BAD\u1BB0-\u1BB9\u1BE6-\u1BFF\u1C24-\u1C4C\u1C50-\u1C59\u1C7E\u1C7F\u1C89-\u1C8F\u1CBB\u1CBC\u1CC0-\u1CE8\u1CED\u1CF4\u1CF7-\u1CF9\u1CFB-\u1CFF\u1DC0-\u1DFF\u1F16\u1F17\u1F1E\u1F1F\u1F46\u1F47\u1F4E\u1F4F\u1F58\u1F5A\u1F5C\u1F5E\u1F7E\u1F7F\u1FB5\u1FBD\u1FBF-\u1FC1\u1FC5\u1FCD-\u1FCF\u1FD4\u1FD5\u1FDC-\u1FDF\u1FED-\u1FF1\u1FF5\u1FFD-\u2070\u2072-\u207E\u2080-\u208F\u209D-\u2101\u2103-\u2106\u2108\u2109\u2114\u2116-\u2118\u211E-\u2123\u2125\u2127\u2129\u212E\u213A\u213B\u2140-\u2144\u214A-\u214D\u214F-\u2182\u2185-\u2BFF\u2CE5-\u2CEA\u2CEF-\u2CF1\u2CF4-\u2CFF\u2D26\u2D28-\u2D2C\u2D2E\u2D2F\u2D68-\u2D6E\u2D70-\u2D7F\u2D97-\u2D9F\u2DA7\u2DAF\u2DB7\u2DBF\u2DC7\u2DCF\u2DD7\u2DDF-\u2E2E\u2E30-\u3004\u3007-\u3030\u3036-\u303A\u303D-\u3040\u3097-\u309C\u30A0\u30FB\u3100-\u3104\u3130\u318F-\u319F\u31C0-\u31EF\u3200-\u33FF\u4DC0-\u4DFF\uA48D-\uA4CF\uA4FE\uA4FF\uA60D-\uA60F\uA620-\uA629\uA62C-\uA63F\uA66F-\uA67E\uA69E\uA69F\uA6E6-\uA716\uA720\uA721\uA789\uA78A\uA7CB-\uA7CF\uA7D2\uA7D4\uA7DA-\uA7F1\uA802\uA806\uA80B\uA823-\uA83F\uA874-\uA881\uA8B4-\uA8F1\uA8F8-\uA8FA\uA8FC\uA8FF-\uA909\uA926-\uA92F\uA947-\uA95F\uA97D-\uA983\uA9B3-\uA9CE\uA9D0-\uA9DF\uA9E5\uA9F0-\uA9F9\uA9FF\uAA29-\uAA3F\uAA43\uAA4C-\uAA5F\uAA77-\uAA79\uAA7B-\uAA7D\uAAB0\uAAB2-\uAAB4\uAAB7\uAAB8\uAABE\uAABF\uAAC1\uAAC3-\uAADA\uAADE\uAADF\uAAEB-\uAAF1\uAAF5-\uAB00\uAB07\uAB08\uAB0F\uAB10\uAB17-\uAB1F\uAB27\uAB2F\uAB5B\uAB6A-\uAB6F\uABE3-\uABFF\uD7A4-\uD7AF\uD7C7-\uD7CA\uD7FC-\uD7FF\uE000-\uF8FF\uFA6E\uFA6F\uFADA-\uFAFF\uFB07-\uFB12\uFB18-\uFB1C\uFB1E\uFB29\uFB37\uFB3D\uFB3F\uFB42\uFB45\uFBB2-\uFBD2\uFD3E-\uFD4F\uFD90\uFD91\uFDC8-\uFDEF\uFDFC-\uFE6F\uFE75\uFEFD-\uFF20\uFF3B-\uFF40\uFF5B-\uFF65\uFFBF-\uFFC1\uFFC8\uFFC9\uFFD0\uFFD1\uFFD8\uFFD9\uFFDD-\uFFFF]|\uD800[\uDC0C\uDC27\uDC3B\uDC3E\uDC4E\uDC4F\uDC5E-\uDC7F\uDCFB-\uDE7F\uDE9D-\uDE9F\uDED1-\uDEFF\uDF20-\uDF2C\uDF41\uDF4A-\uDF4F\uDF76-\uDF7F\uDF9E\uDF9F\uDFC4-\uDFC7\uDFD0-\uDFFF]|\uD801[\uDC9E-\uDCAF\uDCD4-\uDCD7\uDCFC-\uDCFF\uDD28-\uDD2F\uDD64-\uDD6F\uDD7B\uDD8B\uDD93\uDD96\uDDA2\uDDB2\uDDBA\uDDBD-\uDDFF\uDF37-\uDF3F\uDF56-\uDF5F\uDF68-\uDF7F\uDF86\uDFB1\uDFBB-\uDFFF]|\uD802[\uDC06\uDC07\uDC09\uDC36\uDC39-\uDC3B\uDC3D\uDC3E\uDC56-\uDC5F\uDC77-\uDC7F\uDC9F-\uDCDF\uDCF3\uDCF6-\uDCFF\uDD16-\uDD1F\uDD3A-\uDD7F\uDDB8-\uDDBD\uDDC0-\uDDFF\uDE01-\uDE0F\uDE14\uDE18\uDE36-\uDE5F\uDE7D-\uDE7F\uDE9D-\uDEBF\uDEC8\uDEE5-\uDEFF\uDF36-\uDF3F\uDF56-\uDF5F\uDF73-\uDF7F\uDF92-\uDFFF]|\uD803[\uDC49-\uDC7F\uDCB3-\uDCBF\uDCF3-\uDCFF\uDD24-\uDE7F\uDEAA-\uDEAF\uDEB2-\uDEFF\uDF1D-\uDF26\uDF28-\uDF2F\uDF46-\uDF6F\uDF82-\uDFAF\uDFC5-\uDFDF\uDFF7-\uDFFF]|\uD804[\uDC00-\uDC02\uDC38-\uDC70\uDC73\uDC74\uDC76-\uDC82\uDCB0-\uDCCF\uDCE9-\uDD02\uDD27-\uDD43\uDD45\uDD46\uDD48-\uDD4F\uDD73-\uDD75\uDD77-\uDD82\uDDB3-\uDDC0\uDDC5-\uDDD9\uDDDB\uDDDD-\uDDFF\uDE12\uDE2C-\uDE3E\uDE41-\uDE7F\uDE87\uDE89\uDE8E\uDE9E\uDEA9-\uDEAF\uDEDF-\uDF04\uDF0D\uDF0E\uDF11\uDF12\uDF29\uDF31\uDF34\uDF3A-\uDF3C\uDF3E-\uDF4F\uDF51-\uDF5C\uDF62-\uDFFF]|\uD805[\uDC35-\uDC46\uDC4B-\uDC5E\uDC62-\uDC7F\uDCB0-\uDCC3\uDCC6\uDCC8-\uDD7F\uDDAF-\uDDD7\uDDDC-\uDDFF\uDE30-\uDE43\uDE45-\uDE7F\uDEAB-\uDEB7\uDEB9-\uDEFF\uDF1B-\uDF3F\uDF47-\uDFFF]|\uD806[\uDC2C-\uDC9F\uDCE0-\uDCFE\uDD07\uDD08\uDD0A\uDD0B\uDD14\uDD17\uDD30-\uDD3E\uDD40\uDD42-\uDD9F\uDDA8\uDDA9\uDDD1-\uDDE0\uDDE2\uDDE4-\uDDFF\uDE01-\uDE0A\uDE33-\uDE39\uDE3B-\uDE4F\uDE51-\uDE5B\uDE8A-\uDE9C\uDE9E-\uDEAF\uDEF9-\uDFFF]|\uD807[\uDC09\uDC2F-\uDC3F\uDC41-\uDC71\uDC90-\uDCFF\uDD07\uDD0A\uDD31-\uDD45\uDD47-\uDD5F\uDD66\uDD69\uDD8A-\uDD97\uDD99-\uDEDF\uDEF3-\uDF01\uDF03\uDF11\uDF34-\uDFAF\uDFB1-\uDFFF]|\uD808[\uDF9A-\uDFFF]|\uD809[\uDC00-\uDC7F\uDD44-\uDFFF]|[\uD80A\uD80E-\uD810\uD812-\uD819\uD824-\uD82A\uD82D\uD82E\uD830-\uD834\uD836\uD83C-\uD83F\uD87B-\uD87D\uD87F\uD889-\uDBFF][\uDC00-\uDFFF]|\uD80B[\uDC00-\uDF8F\uDFF1-\uDFFF]|\uD80D[\uDC30-\uDC40\uDC47-\uDFFF]|\uD811[\uDE47-\uDFFF]|\uD81A[\uDE39-\uDE3F\uDE5F-\uDE6F\uDEBF-\uDECF\uDEEE-\uDEFF\uDF30-\uDF3F\uDF44-\uDF62\uDF78-\uDF7C\uDF90-\uDFFF]|\uD81B[\uDC00-\uDE3F\uDE80-\uDEFF\uDF4B-\uDF4F\uDF51-\uDF92\uDFA0-\uDFDF\uDFE2\uDFE4-\uDFFF]|\uD821[\uDFF8-\uDFFF]|\uD823[\uDCD6-\uDCFF\uDD09-\uDFFF]|\uD82B[\uDC00-\uDFEF\uDFF4\uDFFC\uDFFF]|\uD82C[\uDD23-\uDD31\uDD33-\uDD4F\uDD53\uDD54\uDD56-\uDD63\uDD68-\uDD6F\uDEFC-\uDFFF]|\uD82F[\uDC6B-\uDC6F\uDC7D-\uDC7F\uDC89-\uDC8F\uDC9A-\uDFFF]|\uD835[\uDC55\uDC9D\uDCA0\uDCA1\uDCA3\uDCA4\uDCA7\uDCA8\uDCAD\uDCBA\uDCBC\uDCC4\uDD06\uDD0B\uDD0C\uDD15\uDD1D\uDD3A\uDD3F\uDD45\uDD47-\uDD49\uDD51\uDEA6\uDEA7\uDEC1\uDEDB\uDEFB\uDF15\uDF35\uDF4F\uDF6F\uDF89\uDFA9\uDFC3\uDFCC-\uDFFF]|\uD837[\uDC00-\uDEFF\uDF1F-\uDF24\uDF2B-\uDFFF]|\uD838[\uDC00-\uDC2F\uDC6E-\uDCFF\uDD2D-\uDD36\uDD3E-\uDD4D\uDD4F-\uDE8F\uDEAE-\uDEBF\uDEEC-\uDFFF]|\uD839[\uDC00-\uDCCF\uDCEC-\uDFDF\uDFE7\uDFEC\uDFEF\uDFFF]|\uD83A[\uDCC5-\uDCFF\uDD44-\uDD4A\uDD4C-\uDFFF]|\uD83B[\uDC00-\uDDFF\uDE04\uDE20\uDE23\uDE25\uDE26\uDE28\uDE33\uDE38\uDE3A\uDE3C-\uDE41\uDE43-\uDE46\uDE48\uDE4A\uDE4C\uDE50\uDE53\uDE55\uDE56\uDE58\uDE5A\uDE5C\uDE5E\uDE60\uDE63\uDE65\uDE66\uDE6B\uDE73\uDE78\uDE7D\uDE7F\uDE8A\uDE9C-\uDEA0\uDEA4\uDEAA\uDEBC-\uDFFF]|\uD869[\uDEE0-\uDEFF]|\uD86D[\uDF3A-\uDF3F]|\uD86E[\uDC1E\uDC1F]|\uD873[\uDEA2-\uDEAF]|\uD87A[\uDFE1-\uDFFF]|\uD87E[\uDE1E-\uDFFF]|\uD884[\uDF4B-\uDF4F]|\uD888[\uDFB0-\uDFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF])+$/;var extractNewHref=function extractNewHref(anchor,attr){if(attr==="text"){if(!anchor.textContent){return "";}return anchor.textContent.replace(regexpNotValidAtStart,"").replace(regexpNotValidAtEnd,"");}if(attr.startsWith("?")){try{var url=new URL(anchor.href,document.location.href);return url.searchParams.get(attr.slice(1))||"";}catch(ex){logMessage(source,"Cannot retrieve the parameter '".concat(attr.slice(1),"' from the URL '").concat(anchor.href));return "";}}if(attr.startsWith("[")&&attr.endsWith("]")){return anchor.getAttribute(attr.slice(1,-1))||"";}return "";};var getValidURL=function getValidURL(text){if(!text){return null;}try{var _URL=new URL(text,document.location.href),href=_URL.href,protocol=_URL.protocol;if(protocol!=="http:"&&protocol!=="https:"){logMessage(source,'Protocol not allowed: "'.concat(protocol,'", from URL: "').concat(href,'"'));return null;}return href;}catch(_unused){return null;}};var isSanitizableAnchor=function isSanitizableAnchor(element){return element.nodeName.toLowerCase()==="a"&&element.hasAttribute("href");};var sanitize=function sanitize(elementSelector){var elements;try{elements=document.querySelectorAll(elementSelector);}catch(e){logMessage(source,'Invalid selector "'.concat(elementSelector,'"'));return;}elements.forEach(function(elem){try{if(!isSanitizableAnchor(elem)){return;}var newHref=extractNewHref(elem,attribute);var newValidHref=getValidURL(newHref);if(!newValidHref){logMessage(source,"Invalid URL: ".concat(newHref));return;}var oldHref=elem.href;elem.setAttribute("href",newValidHref);if(newValidHref!==oldHref){logMessage(source,'Sanitized "'.concat(oldHref,'" to "').concat(newValidHref,'".'));}}catch(ex){logMessage(source,"Failed to sanitize ".concat(elem,"."));}});hit(source);};var run=function run(){sanitize(selector);observeDOMChanges(function(){return sanitize(selector);},true);};if(document.readyState==="loading"){window.addEventListener("DOMContentLoaded",run,{once:true});}else {run();}}function observeDOMChanges(callback){var observeAttrs=arguments.length>1&&arguments[1]!==undefined?arguments[1]:false;var attrsToObserve=arguments.length>2&&arguments[2]!==undefined?arguments[2]:[];var THROTTLE_DELAY_MS=20;var observer=new MutationObserver(throttle(callbackWrapper,THROTTLE_DELAY_MS));var connect=function connect(){if(attrsToObserve.length>0){observer.observe(document.documentElement,{childList:true,subtree:true,attributes:observeAttrs,attributeFilter:attrsToObserve});}else {observer.observe(document.documentElement,{childList:true,subtree:true,attributes:observeAttrs});}};var disconnect=function disconnect(){observer.disconnect();};function callbackWrapper(){disconnect();callback();connect();}connect();}function hit(source){var ADGUARD_PREFIX="[AdGuard]";if(!source.verbose){return;}try{var trace=console.trace.bind(console);var label="".concat(ADGUARD_PREFIX," ");if(source.engine==="corelibs"){label+=source.ruleText;}else {if(source.domainName){label+="".concat(source.domainName);}if(source.args){label+="#%#//scriptlet('".concat(source.name,"', '").concat(source.args.join("', '"),"')");}else {label+="#%#//scriptlet('".concat(source.name,"')");}}if(trace){trace(label);}}catch(e){}if(typeof window.__debug==="function"){window.__debug(source);}}function logMessage(source,message){var forced=arguments.length>2&&arguments[2]!==undefined?arguments[2]:false;var convertMessageToString=arguments.length>3&&arguments[3]!==undefined?arguments[3]:true;var name=source.name,verbose=source.verbose;if(!forced&&!verbose){return;}var nativeConsole=console.log;if(!convertMessageToString){nativeConsole("".concat(name,":"),message);return;}nativeConsole("".concat(name,": ").concat(message));}function throttle(cb,delay){var wait=false;var savedArgs;var wrapper=function wrapper(){for(var _len=arguments.length,args=new Array(_len),_key=0;_key<_len;_key++){args[_key]=arguments[_key];}if(wait){savedArgs=args;return;}cb(...args);wait=true;setTimeout(function(){wait=false;if(savedArgs){wrapper(...savedArgs);savedArgs=null;}},delay);};return wrapper;}var updatedArgs=args?[].concat(source).concat(args):[source];try{hrefSanitizer.apply(this,updatedArgs);if(source.uniqueId){Object.defineProperty(Window.prototype.toString,uniqueIdentifier,{value:flag,enumerable:false,writable:false,configurable:false});}}catch(e){console.log(e);}}function injectCssInShadowDom(source,args){var flag="done";var uniqueIdentifier=source.uniqueId+source.name+"_"+(Array.isArray(args)?args.join("_"):"");if(source.uniqueId){if(Window.prototype.toString[uniqueIdentifier]===flag){return;}}function injectCssInShadowDom(source,cssRule){var hostSelector=arguments.length>2&&arguments[2]!==undefined?arguments[2]:"";if(!Element.prototype.attachShadow||typeof Proxy==="undefined"||typeof Reflect==="undefined"){return;}if(cssRule.match(/(url|image-set)\(.*\)/i)){logMessage(source,'"url()" function is not allowed for css rules');return;}var callback=function callback(shadowRoot){try{var stylesheet=new CSSStyleSheet();try{stylesheet.insertRule(cssRule);}catch(e){logMessage(source,"Unable to apply the rule '".concat(cssRule,"' due to: \n'").concat(e.message,"'"));return;}shadowRoot.adoptedStyleSheets=[...shadowRoot.adoptedStyleSheets,stylesheet];}catch(_unused){var styleTag=document.createElement("style");styleTag.innerText=cssRule;shadowRoot.appendChild(styleTag);}hit(source);};hijackAttachShadow(window,hostSelector,callback);}function hit(source){var ADGUARD_PREFIX="[AdGuard]";if(!source.verbose){return;}try{var trace=console.trace.bind(console);var label="".concat(ADGUARD_PREFIX," ");if(source.engine==="corelibs"){label+=source.ruleText;}else {if(source.domainName){label+="".concat(source.domainName);}if(source.args){label+="#%#//scriptlet('".concat(source.name,"', '").concat(source.args.join("', '"),"')");}else {label+="#%#//scriptlet('".concat(source.name,"')");}}if(trace){trace(label);}}catch(e){}if(typeof window.__debug==="function"){window.__debug(source);}}function logMessage(source,message){var forced=arguments.length>2&&arguments[2]!==undefined?arguments[2]:false;var convertMessageToString=arguments.length>3&&arguments[3]!==undefined?arguments[3]:true;var name=source.name,verbose=source.verbose;if(!forced&&!verbose){return;}var nativeConsole=console.log;if(!convertMessageToString){nativeConsole("".concat(name,":"),message);return;}nativeConsole("".concat(name,": ").concat(message));}function hijackAttachShadow(context,hostSelector,callback){var handlerWrapper=function handlerWrapper(target,thisArg,args){var shadowRoot=Reflect.apply(target,thisArg,args);if(thisArg&&thisArg.matches(hostSelector||"*")){callback(shadowRoot);}return shadowRoot;};var attachShadowHandler={apply:handlerWrapper};context.Element.prototype.attachShadow=new Proxy(context.Element.prototype.attachShadow,attachShadowHandler);}var updatedArgs=args?[].concat(source).concat(args):[source];try{injectCssInShadowDom.apply(this,updatedArgs);if(source.uniqueId){Object.defineProperty(Window.prototype.toString,uniqueIdentifier,{value:flag,enumerable:false,writable:false,configurable:false});}}catch(e){console.log(e);}}function jsonPrune(source,args){var flag="done";var uniqueIdentifier=source.uniqueId+source.name+"_"+(Array.isArray(args)?args.join("_"):"");if(source.uniqueId){if(Window.prototype.toString[uniqueIdentifier]===flag){return;}}function jsonPrune(source,propsToRemove,requiredInitialProps){var stack=arguments.length>3&&arguments[3]!==undefined?arguments[3]:"";var prunePaths=getPrunePath(propsToRemove);var requiredPaths=getPrunePath(requiredInitialProps);var nativeObjects={nativeStringify:window.JSON.stringify};var nativeJSONParse=JSON.parse;var jsonParseWrapper=function jsonParseWrapper(){for(var _len=arguments.length,args=new Array(_len),_key=0;_key<_len;_key++){args[_key]=arguments[_key];}var root=nativeJSONParse.apply(JSON,args);return jsonPruner(source,root,prunePaths,requiredPaths,stack,nativeObjects);};jsonParseWrapper.toString=nativeJSONParse.toString.bind(nativeJSONParse);JSON.parse=jsonParseWrapper;var nativeResponseJson=Response.prototype.json;var responseJsonWrapper=function responseJsonWrapper(){var promise=nativeResponseJson.apply(this);return promise.then(function(obj){return jsonPruner(source,obj,prunePaths,requiredPaths,stack,nativeObjects);});};if(typeof Response==="undefined"){return;}Response.prototype.json=responseJsonWrapper;}function hit(source){var ADGUARD_PREFIX="[AdGuard]";if(!source.verbose){return;}try{var trace=console.trace.bind(console);var label="".concat(ADGUARD_PREFIX," ");if(source.engine==="corelibs"){label+=source.ruleText;}else {if(source.domainName){label+="".concat(source.domainName);}if(source.args){label+="#%#//scriptlet('".concat(source.name,"', '").concat(source.args.join("', '"),"')");}else {label+="#%#//scriptlet('".concat(source.name,"')");}}if(trace){trace(label);}}catch(e){}if(typeof window.__debug==="function"){window.__debug(source);}}function matchStackTrace(stackMatch,stackTrace){if(!stackMatch||stackMatch===""){return true;}var regExpValues=backupRegExpValues();if(shouldAbortInlineOrInjectedScript(stackMatch,stackTrace)){if(regExpValues.length&&regExpValues[0]!==RegExp.$1){restoreRegExpValues(regExpValues);}return true;}var stackRegexp=toRegExp(stackMatch);var refinedStackTrace=stackTrace.split("\n").slice(2).map(function(line){return line.trim();}).join("\n");if(regExpValues.length&&regExpValues[0]!==RegExp.$1){restoreRegExpValues(regExpValues);}return getNativeRegexpTest().call(stackRegexp,refinedStackTrace);}function getWildcardPropertyInChain(base,chain){var lookThrough=arguments.length>2&&arguments[2]!==undefined?arguments[2]:false;var output=arguments.length>3&&arguments[3]!==undefined?arguments[3]:[];var pos=chain.indexOf(".");if(pos===-1){if(chain==="*"||chain==="[]"){for(var key in base){if(Object.prototype.hasOwnProperty.call(base,key)){output.push({base:base,prop:key});}}}else {output.push({base:base,prop:chain});}return output;}var prop=chain.slice(0,pos);var shouldLookThrough=prop==="[]"&&Array.isArray(base)||prop==="*"&&base instanceof Object;if(shouldLookThrough){var nextProp=chain.slice(pos+1);var baseKeys=Object.keys(base);baseKeys.forEach(function(key){var item=base[key];getWildcardPropertyInChain(item,nextProp,lookThrough,output);});}if(Array.isArray(base)){base.forEach(function(key){var nextBase=key;if(nextBase!==undefined){getWildcardPropertyInChain(nextBase,chain,lookThrough,output);}});}var nextBase=base[prop];chain=chain.slice(pos+1);if(nextBase!==undefined){getWildcardPropertyInChain(nextBase,chain,lookThrough,output);}return output;}function logMessage(source,message){var forced=arguments.length>2&&arguments[2]!==undefined?arguments[2]:false;var convertMessageToString=arguments.length>3&&arguments[3]!==undefined?arguments[3]:true;var name=source.name,verbose=source.verbose;if(!forced&&!verbose){return;}var nativeConsole=console.log;if(!convertMessageToString){nativeConsole("".concat(name,":"),message);return;}nativeConsole("".concat(name,": ").concat(message));}function isPruningNeeded(source,root,prunePaths,requiredPaths,stack,nativeObjects){if(!root){return false;}var nativeStringify=nativeObjects.nativeStringify;var shouldProcess;if(prunePaths.length===0&&requiredPaths.length>0){var rootString=nativeStringify(root);var matchRegex=toRegExp(requiredPaths.join(""));var shouldLog=matchRegex.test(rootString);if(shouldLog){logMessage(source,"".concat(window.location.hostname,"\n").concat(nativeStringify(root,null,2),"\nStack trace:\n").concat(new Error().stack),true);if(root&&typeof root==="object"){logMessage(source,root,true,false);}shouldProcess=false;return shouldProcess;}}if(stack&&!matchStackTrace(stack,new Error().stack||"")){shouldProcess=false;return shouldProcess;}var wildcardSymbols=[".*.","*.",".*",".[].","[].",".[]"];var _loop=function _loop(){var requiredPath=requiredPaths[i];var lastNestedPropName=requiredPath.split(".").pop();var hasWildcard=wildcardSymbols.some(function(symbol){return requiredPath.includes(symbol);});var details=getWildcardPropertyInChain(root,requiredPath,hasWildcard);if(!details.length){shouldProcess=false;return {v:shouldProcess};}shouldProcess=!hasWildcard;for(var j=0;j<details.length;j+=1){var hasRequiredProp=typeof lastNestedPropName==="string"&&details[j].base[lastNestedPropName]!==undefined;if(hasWildcard){shouldProcess=hasRequiredProp||shouldProcess;}else {shouldProcess=hasRequiredProp&&shouldProcess;}}};for(var i=0;i<requiredPaths.length;i+=1){var _ret=_loop();if(typeof _ret==="object")return _ret.v;}return shouldProcess;}function jsonPruner(source,root,prunePaths,requiredPaths,stack,nativeObjects){var nativeStringify=nativeObjects.nativeStringify;if(prunePaths.length===0&&requiredPaths.length===0){logMessage(source,"".concat(window.location.hostname,"\n").concat(nativeStringify(root,null,2),"\nStack trace:\n").concat(new Error().stack),true);if(root&&typeof root==="object"){logMessage(source,root,true,false);}return root;}try{if(isPruningNeeded(source,root,prunePaths,requiredPaths,stack,nativeObjects)===false){return root;}prunePaths.forEach(function(path){var ownerObjArr=getWildcardPropertyInChain(root,path,true);ownerObjArr.forEach(function(ownerObj){if(ownerObj!==undefined&&ownerObj.base){delete ownerObj.base[ownerObj.prop];hit(source);}});});}catch(e){logMessage(source,e);}return root;}function getPrunePath(props){var validPropsString=typeof props==="string"&&props!==undefined&&props!=="";return validPropsString?props.split(/ +/):[];}function toRegExp(rawInput){var input=rawInput||"";var DEFAULT_VALUE=".?";var FORWARD_SLASH="/";if(input===""){return new RegExp(DEFAULT_VALUE);}var delimiterIndex=input.lastIndexOf(FORWARD_SLASH);var flagsPart=input.substring(delimiterIndex+1);var regExpPart=input.substring(0,delimiterIndex+1);var isValidRegExpFlag=function isValidRegExpFlag(flag){if(!flag){return false;}try{new RegExp("",flag);return true;}catch(ex){return false;}};var getRegExpFlags=function getRegExpFlags(regExpStr,flagsStr){if(regExpStr.startsWith(FORWARD_SLASH)&&regExpStr.endsWith(FORWARD_SLASH)&&!regExpStr.endsWith("\\/")&&isValidRegExpFlag(flagsStr)){return flagsStr;}return "";};var flags=getRegExpFlags(regExpPart,flagsPart);if(input.startsWith(FORWARD_SLASH)&&input.endsWith(FORWARD_SLASH)||flags){var regExpInput=flags?regExpPart:input;return new RegExp(regExpInput.slice(1,-1),flags);}var escaped=input.replace(/\\'/g,"'").replace(/\\"/g,'"').replace(/[.*+?^${}()|[\]\\]/g,"\\$&");return new RegExp(escaped);}function getNativeRegexpTest(){var descriptor=Object.getOwnPropertyDescriptor(RegExp.prototype,"test");var nativeRegexTest=descriptor===null||descriptor===void 0?void 0:descriptor.value;if(descriptor&&typeof descriptor.value==="function"){return nativeRegexTest;}throw new Error("RegExp.prototype.test is not a function");}function shouldAbortInlineOrInjectedScript(stackMatch,stackTrace){var INLINE_SCRIPT_STRING="inlineScript";var INJECTED_SCRIPT_STRING="injectedScript";var INJECTED_SCRIPT_MARKER="<anonymous>";var isInlineScript=function isInlineScript(match){return match.includes(INLINE_SCRIPT_STRING);};var isInjectedScript=function isInjectedScript(match){return match.includes(INJECTED_SCRIPT_STRING);};if(!(isInlineScript(stackMatch)||isInjectedScript(stackMatch))){return false;}var documentURL=window.location.href;var pos=documentURL.indexOf("#");if(pos!==-1){documentURL=documentURL.slice(0,pos);}var stackSteps=stackTrace.split("\n").slice(2).map(function(line){return line.trim();});var stackLines=stackSteps.map(function(line){var stack;var getStackTraceValues=/(.*?@)?(\S+)(:\d+)(:\d+)\)?$/.exec(line);if(getStackTraceValues){var _stackURL,_stackURL2;var stackURL=getStackTraceValues[2];var stackLine=getStackTraceValues[3];var stackCol=getStackTraceValues[4];if((_stackURL=stackURL)!==null&&_stackURL!==void 0&&_stackURL.startsWith("(")){stackURL=stackURL.slice(1);}if((_stackURL2=stackURL)!==null&&_stackURL2!==void 0&&_stackURL2.startsWith(INJECTED_SCRIPT_MARKER)){var _stackFunction;stackURL=INJECTED_SCRIPT_STRING;var stackFunction=getStackTraceValues[1]!==undefined?getStackTraceValues[1].slice(0,-1):line.slice(0,getStackTraceValues.index).trim();if((_stackFunction=stackFunction)!==null&&_stackFunction!==void 0&&_stackFunction.startsWith("at")){stackFunction=stackFunction.slice(2).trim();}stack="".concat(stackFunction," ").concat(stackURL).concat(stackLine).concat(stackCol).trim();}else if(stackURL===documentURL){stack="".concat(INLINE_SCRIPT_STRING).concat(stackLine).concat(stackCol).trim();}else {stack="".concat(stackURL).concat(stackLine).concat(stackCol).trim();}}else {stack=line;}return stack;});if(stackLines){for(var index=0;index<stackLines.length;index+=1){if(isInlineScript(stackMatch)&&stackLines[index].startsWith(INLINE_SCRIPT_STRING)&&stackLines[index].match(toRegExp(stackMatch))){return true;}if(isInjectedScript(stackMatch)&&stackLines[index].startsWith(INJECTED_SCRIPT_STRING)&&stackLines[index].match(toRegExp(stackMatch))){return true;}}}return false;}function backupRegExpValues(){try{var arrayOfRegexpValues=[];for(var index=1;index<10;index+=1){var value="$".concat(index);if(!RegExp[value]){break;}arrayOfRegexpValues.push(RegExp[value]);}return arrayOfRegexpValues;}catch(error){return [];}}function restoreRegExpValues(array){if(!array.length){return;}try{var stringPattern="";if(array.length===1){stringPattern="(".concat(array[0],")");}else {stringPattern=array.reduce(function(accumulator,currentValue,currentIndex){if(currentIndex===1){return "(".concat(accumulator,"),(").concat(currentValue,")");}return "".concat(accumulator,",(").concat(currentValue,")");});}var regExpGroup=new RegExp(stringPattern);array.toString().replace(regExpGroup,"");}catch(error){var message="Failed to restore RegExp values: ".concat(error);console.log(message);}}var updatedArgs=args?[].concat(source).concat(args):[source];try{jsonPrune.apply(this,updatedArgs);if(source.uniqueId){Object.defineProperty(Window.prototype.toString,uniqueIdentifier,{value:flag,enumerable:false,writable:false,configurable:false});}}catch(e){console.log(e);}}function jsonPruneFetchResponse(source,args){var flag="done";var uniqueIdentifier=source.uniqueId+source.name+"_"+(Array.isArray(args)?args.join("_"):"");if(source.uniqueId){if(Window.prototype.toString[uniqueIdentifier]===flag){return;}}function jsonPruneFetchResponse(source,propsToRemove,obligatoryProps){var propsToMatch=arguments.length>3&&arguments[3]!==undefined?arguments[3]:"";var stack=arguments.length>4&&arguments[4]!==undefined?arguments[4]:"";if(typeof fetch==="undefined"||typeof Proxy==="undefined"||typeof Response==="undefined"){return;}var prunePaths=getPrunePath(propsToRemove);var requiredPaths=getPrunePath(obligatoryProps);var nativeStringify=window.JSON.stringify;var nativeRequestClone=window.Request.prototype.clone;var nativeResponseClone=window.Response.prototype.clone;var nativeFetch=window.fetch;var fetchHandlerWrapper=async function fetchHandlerWrapper(target,thisArg,args){var fetchData=getFetchData(args,nativeRequestClone);if(!matchRequestProps(source,propsToMatch,fetchData)){return Reflect.apply(target,thisArg,args);}var originalResponse;var clonedResponse;try{originalResponse=await nativeFetch.apply(null,args);clonedResponse=nativeResponseClone.call(originalResponse);}catch(_unused){logMessage(source,"Could not make an original fetch request: ".concat(fetchData.url));return Reflect.apply(target,thisArg,args);}var json;try{json=await originalResponse.json();}catch(e){var message="Response body can't be converted to json: ".concat(objectToString(fetchData));logMessage(source,message);return clonedResponse;}var modifiedJson=jsonPruner(source,json,prunePaths,requiredPaths,stack,{nativeStringify:nativeStringify,nativeRequestClone:nativeRequestClone,nativeResponseClone:nativeResponseClone,nativeFetch:nativeFetch});var forgedResponse=forgeResponse(originalResponse,nativeStringify(modifiedJson));hit(source);return forgedResponse;};var fetchHandler={apply:fetchHandlerWrapper};window.fetch=new Proxy(window.fetch,fetchHandler);}function hit(source){var ADGUARD_PREFIX="[AdGuard]";if(!source.verbose){return;}try{var trace=console.trace.bind(console);var label="".concat(ADGUARD_PREFIX," ");if(source.engine==="corelibs"){label+=source.ruleText;}else {if(source.domainName){label+="".concat(source.domainName);}if(source.args){label+="#%#//scriptlet('".concat(source.name,"', '").concat(source.args.join("', '"),"')");}else {label+="#%#//scriptlet('".concat(source.name,"')");}}if(trace){trace(label);}}catch(e){}if(typeof window.__debug==="function"){window.__debug(source);}}function logMessage(source,message){var forced=arguments.length>2&&arguments[2]!==undefined?arguments[2]:false;var convertMessageToString=arguments.length>3&&arguments[3]!==undefined?arguments[3]:true;var name=source.name,verbose=source.verbose;if(!forced&&!verbose){return;}var nativeConsole=console.log;if(!convertMessageToString){nativeConsole("".concat(name,":"),message);return;}nativeConsole("".concat(name,": ").concat(message));}function getFetchData(args,nativeRequestClone){var fetchPropsObj={};var resource=args[0];var fetchUrl;var fetchInit;if(resource instanceof Request){var realData=nativeRequestClone.call(resource);var requestData=getRequestData(realData);fetchUrl=requestData.url;fetchInit=requestData;}else {fetchUrl=resource;fetchInit=args[1];}fetchPropsObj.url=fetchUrl;if(fetchInit instanceof Object){var props=Object.keys(fetchInit);props.forEach(function(prop){fetchPropsObj[prop]=fetchInit[prop];});}return fetchPropsObj;}function objectToString(obj){if(!obj||typeof obj!=="object"){return String(obj);}if(isEmptyObject(obj)){return "{}";}return Object.entries(obj).map(function(pair){var key=pair[0];var value=pair[1];var recordValueStr=value;if(value instanceof Object){recordValueStr="{ ".concat(objectToString(value)," }");}return "".concat(key,':"').concat(recordValueStr,'"');}).join(" ");}function matchRequestProps(source,propsToMatch,requestData){if(propsToMatch===""||propsToMatch==="*"){return true;}var isMatched;var parsedData=parseMatchProps(propsToMatch);if(!isValidParsedData(parsedData)){logMessage(source,"Invalid parameter: ".concat(propsToMatch));isMatched=false;}else {var matchData=getMatchPropsData(parsedData);var matchKeys=Object.keys(matchData);isMatched=matchKeys.every(function(matchKey){var matchValue=matchData[matchKey];var dataValue=requestData[matchKey];return Object.prototype.hasOwnProperty.call(requestData,matchKey)&&typeof dataValue==="string"&&(matchValue===null||matchValue===void 0?void 0:matchValue.test(dataValue));});}return isMatched;}function jsonPruner(source,root,prunePaths,requiredPaths,stack,nativeObjects){var nativeStringify=nativeObjects.nativeStringify;if(prunePaths.length===0&&requiredPaths.length===0){logMessage(source,"".concat(window.location.hostname,"\n").concat(nativeStringify(root,null,2),"\nStack trace:\n").concat(new Error().stack),true);if(root&&typeof root==="object"){logMessage(source,root,true,false);}return root;}try{if(isPruningNeeded(source,root,prunePaths,requiredPaths,stack,nativeObjects)===false){return root;}prunePaths.forEach(function(path){var ownerObjArr=getWildcardPropertyInChain(root,path,true);ownerObjArr.forEach(function(ownerObj){if(ownerObj!==undefined&&ownerObj.base){delete ownerObj.base[ownerObj.prop];hit(source);}});});}catch(e){logMessage(source,e);}return root;}function getPrunePath(props){var validPropsString=typeof props==="string"&&props!==undefined&&props!=="";return validPropsString?props.split(/ +/):[];}function forgeResponse(response,textContent){var bodyUsed=response.bodyUsed,headers=response.headers,ok=response.ok,redirected=response.redirected,status=response.status,statusText=response.statusText,type=response.type,url=response.url;var forgedResponse=new Response(textContent,{status:status,statusText:statusText,headers:headers});Object.defineProperties(forgedResponse,{url:{value:url},type:{value:type},ok:{value:ok},bodyUsed:{value:bodyUsed},redirected:{value:redirected}});return forgedResponse;}function isPruningNeeded(source,root,prunePaths,requiredPaths,stack,nativeObjects){if(!root){return false;}var nativeStringify=nativeObjects.nativeStringify;var shouldProcess;if(prunePaths.length===0&&requiredPaths.length>0){var rootString=nativeStringify(root);var matchRegex=toRegExp(requiredPaths.join(""));var shouldLog=matchRegex.test(rootString);if(shouldLog){logMessage(source,"".concat(window.location.hostname,"\n").concat(nativeStringify(root,null,2),"\nStack trace:\n").concat(new Error().stack),true);if(root&&typeof root==="object"){logMessage(source,root,true,false);}shouldProcess=false;return shouldProcess;}}if(stack&&!matchStackTrace(stack,new Error().stack||"")){shouldProcess=false;return shouldProcess;}var wildcardSymbols=[".*.","*.",".*",".[].","[].",".[]"];var _loop=function _loop(){var requiredPath=requiredPaths[i];var lastNestedPropName=requiredPath.split(".").pop();var hasWildcard=wildcardSymbols.some(function(symbol){return requiredPath.includes(symbol);});var details=getWildcardPropertyInChain(root,requiredPath,hasWildcard);if(!details.length){shouldProcess=false;return {v:shouldProcess};}shouldProcess=!hasWildcard;for(var j=0;j<details.length;j+=1){var hasRequiredProp=typeof lastNestedPropName==="string"&&details[j].base[lastNestedPropName]!==undefined;if(hasWildcard){shouldProcess=hasRequiredProp||shouldProcess;}else {shouldProcess=hasRequiredProp&&shouldProcess;}}};for(var i=0;i<requiredPaths.length;i+=1){var _ret=_loop();if(typeof _ret==="object")return _ret.v;}return shouldProcess;}function matchStackTrace(stackMatch,stackTrace){if(!stackMatch||stackMatch===""){return true;}var regExpValues=backupRegExpValues();if(shouldAbortInlineOrInjectedScript(stackMatch,stackTrace)){if(regExpValues.length&&regExpValues[0]!==RegExp.$1){restoreRegExpValues(regExpValues);}return true;}var stackRegexp=toRegExp(stackMatch);var refinedStackTrace=stackTrace.split("\n").slice(2).map(function(line){return line.trim();}).join("\n");if(regExpValues.length&&regExpValues[0]!==RegExp.$1){restoreRegExpValues(regExpValues);}return getNativeRegexpTest().call(stackRegexp,refinedStackTrace);}function toRegExp(rawInput){var input=rawInput||"";var DEFAULT_VALUE=".?";var FORWARD_SLASH="/";if(input===""){return new RegExp(DEFAULT_VALUE);}var delimiterIndex=input.lastIndexOf(FORWARD_SLASH);var flagsPart=input.substring(delimiterIndex+1);var regExpPart=input.substring(0,delimiterIndex+1);var isValidRegExpFlag=function isValidRegExpFlag(flag){if(!flag){return false;}try{new RegExp("",flag);return true;}catch(ex){return false;}};var getRegExpFlags=function getRegExpFlags(regExpStr,flagsStr){if(regExpStr.startsWith(FORWARD_SLASH)&&regExpStr.endsWith(FORWARD_SLASH)&&!regExpStr.endsWith("\\/")&&isValidRegExpFlag(flagsStr)){return flagsStr;}return "";};var flags=getRegExpFlags(regExpPart,flagsPart);if(input.startsWith(FORWARD_SLASH)&&input.endsWith(FORWARD_SLASH)||flags){var regExpInput=flags?regExpPart:input;return new RegExp(regExpInput.slice(1,-1),flags);}var escaped=input.replace(/\\'/g,"'").replace(/\\"/g,'"').replace(/[.*+?^${}()|[\]\\]/g,"\\$&");return new RegExp(escaped);}function isValidStrPattern(input){var FORWARD_SLASH="/";var str=escapeRegExp(input);if(input[0]===FORWARD_SLASH&&input[input.length-1]===FORWARD_SLASH){str=input.slice(1,-1);}var isValid;try{isValid=new RegExp(str);isValid=true;}catch(e){isValid=false;}return isValid;}function escapeRegExp(str){return str.replace(/[.*+?^${}()|[\]\\]/g,"\\$&");}function isEmptyObject(obj){return Object.keys(obj).length===0&&!obj.prototype;}function getRequestData(request){var requestInitOptions=getRequestProps();var entries=requestInitOptions.map(function(key){var value=request[key];return [key,value];});return Object.fromEntries(entries);}function getRequestProps(){return ["url","method","headers","body","credentials","cache","redirect","referrer","referrerPolicy","integrity","keepalive","signal","mode"];}function parseMatchProps(propsToMatchStr){var PROPS_DIVIDER=" ";var PAIRS_MARKER=":";var isRequestProp=function isRequestProp(prop){return getRequestProps().includes(prop);};var propsObj={};var props=propsToMatchStr.split(PROPS_DIVIDER);props.forEach(function(prop){var dividerInd=prop.indexOf(PAIRS_MARKER);var key=prop.slice(0,dividerInd);if(isRequestProp(key)){var value=prop.slice(dividerInd+1);propsObj[key]=value;}else {propsObj.url=prop;}});return propsObj;}function isValidParsedData(data){return Object.values(data).every(function(value){return isValidStrPattern(value);});}function getMatchPropsData(data){var matchData={};var dataKeys=Object.keys(data);dataKeys.forEach(function(key){matchData[key]=toRegExp(data[key]);});return matchData;}function getWildcardPropertyInChain(base,chain){var lookThrough=arguments.length>2&&arguments[2]!==undefined?arguments[2]:false;var output=arguments.length>3&&arguments[3]!==undefined?arguments[3]:[];var pos=chain.indexOf(".");if(pos===-1){if(chain==="*"||chain==="[]"){for(var key in base){if(Object.prototype.hasOwnProperty.call(base,key)){output.push({base:base,prop:key});}}}else {output.push({base:base,prop:chain});}return output;}var prop=chain.slice(0,pos);var shouldLookThrough=prop==="[]"&&Array.isArray(base)||prop==="*"&&base instanceof Object;if(shouldLookThrough){var nextProp=chain.slice(pos+1);var baseKeys=Object.keys(base);baseKeys.forEach(function(key){var item=base[key];getWildcardPropertyInChain(item,nextProp,lookThrough,output);});}if(Array.isArray(base)){base.forEach(function(key){var nextBase=key;if(nextBase!==undefined){getWildcardPropertyInChain(nextBase,chain,lookThrough,output);}});}var nextBase=base[prop];chain=chain.slice(pos+1);if(nextBase!==undefined){getWildcardPropertyInChain(nextBase,chain,lookThrough,output);}return output;}function shouldAbortInlineOrInjectedScript(stackMatch,stackTrace){var INLINE_SCRIPT_STRING="inlineScript";var INJECTED_SCRIPT_STRING="injectedScript";var INJECTED_SCRIPT_MARKER="<anonymous>";var isInlineScript=function isInlineScript(match){return match.includes(INLINE_SCRIPT_STRING);};var isInjectedScript=function isInjectedScript(match){return match.includes(INJECTED_SCRIPT_STRING);};if(!(isInlineScript(stackMatch)||isInjectedScript(stackMatch))){return false;}var documentURL=window.location.href;var pos=documentURL.indexOf("#");if(pos!==-1){documentURL=documentURL.slice(0,pos);}var stackSteps=stackTrace.split("\n").slice(2).map(function(line){return line.trim();});var stackLines=stackSteps.map(function(line){var stack;var getStackTraceValues=/(.*?@)?(\S+)(:\d+)(:\d+)\)?$/.exec(line);if(getStackTraceValues){var _stackURL,_stackURL2;var stackURL=getStackTraceValues[2];var stackLine=getStackTraceValues[3];var stackCol=getStackTraceValues[4];if((_stackURL=stackURL)!==null&&_stackURL!==void 0&&_stackURL.startsWith("(")){stackURL=stackURL.slice(1);}if((_stackURL2=stackURL)!==null&&_stackURL2!==void 0&&_stackURL2.startsWith(INJECTED_SCRIPT_MARKER)){var _stackFunction;stackURL=INJECTED_SCRIPT_STRING;var stackFunction=getStackTraceValues[1]!==undefined?getStackTraceValues[1].slice(0,-1):line.slice(0,getStackTraceValues.index).trim();if((_stackFunction=stackFunction)!==null&&_stackFunction!==void 0&&_stackFunction.startsWith("at")){stackFunction=stackFunction.slice(2).trim();}stack="".concat(stackFunction," ").concat(stackURL).concat(stackLine).concat(stackCol).trim();}else if(stackURL===documentURL){stack="".concat(INLINE_SCRIPT_STRING).concat(stackLine).concat(stackCol).trim();}else {stack="".concat(stackURL).concat(stackLine).concat(stackCol).trim();}}else {stack=line;}return stack;});if(stackLines){for(var index=0;index<stackLines.length;index+=1){if(isInlineScript(stackMatch)&&stackLines[index].startsWith(INLINE_SCRIPT_STRING)&&stackLines[index].match(toRegExp(stackMatch))){return true;}if(isInjectedScript(stackMatch)&&stackLines[index].startsWith(INJECTED_SCRIPT_STRING)&&stackLines[index].match(toRegExp(stackMatch))){return true;}}}return false;}function getNativeRegexpTest(){var descriptor=Object.getOwnPropertyDescriptor(RegExp.prototype,"test");var nativeRegexTest=descriptor===null||descriptor===void 0?void 0:descriptor.value;if(descriptor&&typeof descriptor.value==="function"){return nativeRegexTest;}throw new Error("RegExp.prototype.test is not a function");}function backupRegExpValues(){try{var arrayOfRegexpValues=[];for(var index=1;index<10;index+=1){var value="$".concat(index);if(!RegExp[value]){break;}arrayOfRegexpValues.push(RegExp[value]);}return arrayOfRegexpValues;}catch(error){return [];}}function restoreRegExpValues(array){if(!array.length){return;}try{var stringPattern="";if(array.length===1){stringPattern="(".concat(array[0],")");}else {stringPattern=array.reduce(function(accumulator,currentValue,currentIndex){if(currentIndex===1){return "(".concat(accumulator,"),(").concat(currentValue,")");}return "".concat(accumulator,",(").concat(currentValue,")");});}var regExpGroup=new RegExp(stringPattern);array.toString().replace(regExpGroup,"");}catch(error){var message="Failed to restore RegExp values: ".concat(error);console.log(message);}}var updatedArgs=args?[].concat(source).concat(args):[source];try{jsonPruneFetchResponse.apply(this,updatedArgs);if(source.uniqueId){Object.defineProperty(Window.prototype.toString,uniqueIdentifier,{value:flag,enumerable:false,writable:false,configurable:false});}}catch(e){console.log(e);}}function jsonPruneXhrResponse(source,args){var flag="done";var uniqueIdentifier=source.uniqueId+source.name+"_"+(Array.isArray(args)?args.join("_"):"");if(source.uniqueId){if(Window.prototype.toString[uniqueIdentifier]===flag){return;}}function jsonPruneXhrResponse(source,propsToRemove,obligatoryProps){var propsToMatch=arguments.length>3&&arguments[3]!==undefined?arguments[3]:"";var stack=arguments.length>4&&arguments[4]!==undefined?arguments[4]:"";if(typeof Proxy==="undefined"){return;}var shouldLog=!propsToRemove&&!obligatoryProps;var prunePaths=getPrunePath(propsToRemove);var requiredPaths=getPrunePath(obligatoryProps);var nativeParse=window.JSON.parse;var nativeStringify=window.JSON.stringify;var nativeOpen=window.XMLHttpRequest.prototype.open;var nativeSend=window.XMLHttpRequest.prototype.send;var setRequestHeaderWrapper=function setRequestHeaderWrapper(setRequestHeader,thisArgument,argsList){thisArgument.collectedHeaders.push(argsList);return Reflect.apply(setRequestHeader,thisArgument,argsList);};var setRequestHeaderHandler={apply:setRequestHeaderWrapper};var xhrData;var openWrapper=function openWrapper(target,thisArg,args){xhrData=getXhrData.apply(null,args);if(matchRequestProps(source,propsToMatch,xhrData)||shouldLog){thisArg.xhrShouldBePruned=true;thisArg.headersReceived=!!thisArg.headersReceived;}if(thisArg.xhrShouldBePruned&&!thisArg.headersReceived){thisArg.headersReceived=true;thisArg.collectedHeaders=[];thisArg.setRequestHeader=new Proxy(thisArg.setRequestHeader,setRequestHeaderHandler);}return Reflect.apply(target,thisArg,args);};var sendWrapper=function sendWrapper(target,thisArg,args){var stackTrace=new Error().stack||"";if(!thisArg.xhrShouldBePruned||stack&&!matchStackTrace(stack,stackTrace)){return Reflect.apply(target,thisArg,args);}var forgedRequest=new XMLHttpRequest();forgedRequest.addEventListener("readystatechange",function(){if(forgedRequest.readyState!==4){return;}var readyState=forgedRequest.readyState,response=forgedRequest.response,responseText=forgedRequest.responseText,responseURL=forgedRequest.responseURL,responseXML=forgedRequest.responseXML,status=forgedRequest.status,statusText=forgedRequest.statusText;var content=responseText||response;if(typeof content!=="string"&&typeof content!=="object"){return;}var modifiedContent;if(typeof content==="string"){try{var jsonContent=nativeParse(content);if(shouldLog){logMessage(source,"".concat(window.location.hostname,"\n").concat(nativeStringify(jsonContent,null,2),"\nStack trace:\n").concat(stackTrace),true);logMessage(source,jsonContent,true,false);modifiedContent=content;}else {modifiedContent=jsonPruner(source,jsonContent,prunePaths,requiredPaths,stack="",{nativeStringify:nativeStringify});try{var responseType=thisArg.responseType;switch(responseType){case"":case"text":modifiedContent=nativeStringify(modifiedContent);break;case"arraybuffer":modifiedContent=new TextEncoder().encode(nativeStringify(modifiedContent)).buffer;break;case"blob":modifiedContent=new Blob([nativeStringify(modifiedContent)]);break;default:break;}}catch(error){var message="Response body cannot be converted to reponse type: '".concat(content,"'");logMessage(source,message);modifiedContent=content;}}}catch(error){var _message="Response body cannot be converted to json: '".concat(content,"'");logMessage(source,_message);modifiedContent=content;}}Object.defineProperties(thisArg,{readyState:{value:readyState,writable:false},responseURL:{value:responseURL,writable:false},responseXML:{value:responseXML,writable:false},status:{value:status,writable:false},statusText:{value:statusText,writable:false},response:{value:modifiedContent,writable:false},responseText:{value:modifiedContent,writable:false}});setTimeout(function(){var stateEvent=new Event("readystatechange");thisArg.dispatchEvent(stateEvent);var loadEvent=new Event("load");thisArg.dispatchEvent(loadEvent);var loadEndEvent=new Event("loadend");thisArg.dispatchEvent(loadEndEvent);},1);hit(source);});nativeOpen.apply(forgedRequest,[xhrData.method,xhrData.url,Boolean(xhrData.async)]);thisArg.collectedHeaders.forEach(function(header){forgedRequest.setRequestHeader(header[0],header[1]);});thisArg.collectedHeaders=[];try{nativeSend.call(forgedRequest,args);}catch(_unused){return Reflect.apply(target,thisArg,args);}return undefined;};var openHandler={apply:openWrapper};var sendHandler={apply:sendWrapper};XMLHttpRequest.prototype.open=new Proxy(XMLHttpRequest.prototype.open,openHandler);XMLHttpRequest.prototype.send=new Proxy(XMLHttpRequest.prototype.send,sendHandler);}function hit(source){var ADGUARD_PREFIX="[AdGuard]";if(!source.verbose){return;}try{var trace=console.trace.bind(console);var label="".concat(ADGUARD_PREFIX," ");if(source.engine==="corelibs"){label+=source.ruleText;}else {if(source.domainName){label+="".concat(source.domainName);}if(source.args){label+="#%#//scriptlet('".concat(source.name,"', '").concat(source.args.join("', '"),"')");}else {label+="#%#//scriptlet('".concat(source.name,"')");}}if(trace){trace(label);}}catch(e){}if(typeof window.__debug==="function"){window.__debug(source);}}function logMessage(source,message){var forced=arguments.length>2&&arguments[2]!==undefined?arguments[2]:false;var convertMessageToString=arguments.length>3&&arguments[3]!==undefined?arguments[3]:true;var name=source.name,verbose=source.verbose;if(!forced&&!verbose){return;}var nativeConsole=console.log;if(!convertMessageToString){nativeConsole("".concat(name,":"),message);return;}nativeConsole("".concat(name,": ").concat(message));}function toRegExp(rawInput){var input=rawInput||"";var DEFAULT_VALUE=".?";var FORWARD_SLASH="/";if(input===""){return new RegExp(DEFAULT_VALUE);}var delimiterIndex=input.lastIndexOf(FORWARD_SLASH);var flagsPart=input.substring(delimiterIndex+1);var regExpPart=input.substring(0,delimiterIndex+1);var isValidRegExpFlag=function isValidRegExpFlag(flag){if(!flag){return false;}try{new RegExp("",flag);return true;}catch(ex){return false;}};var getRegExpFlags=function getRegExpFlags(regExpStr,flagsStr){if(regExpStr.startsWith(FORWARD_SLASH)&&regExpStr.endsWith(FORWARD_SLASH)&&!regExpStr.endsWith("\\/")&&isValidRegExpFlag(flagsStr)){return flagsStr;}return "";};var flags=getRegExpFlags(regExpPart,flagsPart);if(input.startsWith(FORWARD_SLASH)&&input.endsWith(FORWARD_SLASH)||flags){var regExpInput=flags?regExpPart:input;return new RegExp(regExpInput.slice(1,-1),flags);}var escaped=input.replace(/\\'/g,"'").replace(/\\"/g,'"').replace(/[.*+?^${}()|[\]\\]/g,"\\$&");return new RegExp(escaped);}function jsonPruner(source,root,prunePaths,requiredPaths,stack,nativeObjects){var nativeStringify=nativeObjects.nativeStringify;if(prunePaths.length===0&&requiredPaths.length===0){logMessage(source,"".concat(window.location.hostname,"\n").concat(nativeStringify(root,null,2),"\nStack trace:\n").concat(new Error().stack),true);if(root&&typeof root==="object"){logMessage(source,root,true,false);}return root;}try{if(isPruningNeeded(source,root,prunePaths,requiredPaths,stack,nativeObjects)===false){return root;}prunePaths.forEach(function(path){var ownerObjArr=getWildcardPropertyInChain(root,path,true);ownerObjArr.forEach(function(ownerObj){if(ownerObj!==undefined&&ownerObj.base){delete ownerObj.base[ownerObj.prop];hit(source);}});});}catch(e){logMessage(source,e);}return root;}function getPrunePath(props){var validPropsString=typeof props==="string"&&props!==undefined&&props!=="";return validPropsString?props.split(/ +/):[];}function matchRequestProps(source,propsToMatch,requestData){if(propsToMatch===""||propsToMatch==="*"){return true;}var isMatched;var parsedData=parseMatchProps(propsToMatch);if(!isValidParsedData(parsedData)){logMessage(source,"Invalid parameter: ".concat(propsToMatch));isMatched=false;}else {var matchData=getMatchPropsData(parsedData);var matchKeys=Object.keys(matchData);isMatched=matchKeys.every(function(matchKey){var matchValue=matchData[matchKey];var dataValue=requestData[matchKey];return Object.prototype.hasOwnProperty.call(requestData,matchKey)&&typeof dataValue==="string"&&(matchValue===null||matchValue===void 0?void 0:matchValue.test(dataValue));});}return isMatched;}function getXhrData(method,url,async,user,password){return {method:method,url:url,async:async,user:user,password:password};}function isPruningNeeded(source,root,prunePaths,requiredPaths,stack,nativeObjects){if(!root){return false;}var nativeStringify=nativeObjects.nativeStringify;var shouldProcess;if(prunePaths.length===0&&requiredPaths.length>0){var rootString=nativeStringify(root);var matchRegex=toRegExp(requiredPaths.join(""));var shouldLog=matchRegex.test(rootString);if(shouldLog){logMessage(source,"".concat(window.location.hostname,"\n").concat(nativeStringify(root,null,2),"\nStack trace:\n").concat(new Error().stack),true);if(root&&typeof root==="object"){logMessage(source,root,true,false);}shouldProcess=false;return shouldProcess;}}if(stack&&!matchStackTrace(stack,new Error().stack||"")){shouldProcess=false;return shouldProcess;}var wildcardSymbols=[".*.","*.",".*",".[].","[].",".[]"];var _loop=function _loop(){var requiredPath=requiredPaths[i];var lastNestedPropName=requiredPath.split(".").pop();var hasWildcard=wildcardSymbols.some(function(symbol){return requiredPath.includes(symbol);});var details=getWildcardPropertyInChain(root,requiredPath,hasWildcard);if(!details.length){shouldProcess=false;return {v:shouldProcess};}shouldProcess=!hasWildcard;for(var j=0;j<details.length;j+=1){var hasRequiredProp=typeof lastNestedPropName==="string"&&details[j].base[lastNestedPropName]!==undefined;if(hasWildcard){shouldProcess=hasRequiredProp||shouldProcess;}else {shouldProcess=hasRequiredProp&&shouldProcess;}}};for(var i=0;i<requiredPaths.length;i+=1){var _ret=_loop();if(typeof _ret==="object")return _ret.v;}return shouldProcess;}function matchStackTrace(stackMatch,stackTrace){if(!stackMatch||stackMatch===""){return true;}var regExpValues=backupRegExpValues();if(shouldAbortInlineOrInjectedScript(stackMatch,stackTrace)){if(regExpValues.length&&regExpValues[0]!==RegExp.$1){restoreRegExpValues(regExpValues);}return true;}var stackRegexp=toRegExp(stackMatch);var refinedStackTrace=stackTrace.split("\n").slice(2).map(function(line){return line.trim();}).join("\n");if(regExpValues.length&&regExpValues[0]!==RegExp.$1){restoreRegExpValues(regExpValues);}return getNativeRegexpTest().call(stackRegexp,refinedStackTrace);}function getMatchPropsData(data){var matchData={};var dataKeys=Object.keys(data);dataKeys.forEach(function(key){matchData[key]=toRegExp(data[key]);});return matchData;}function getRequestProps(){return ["url","method","headers","body","credentials","cache","redirect","referrer","referrerPolicy","integrity","keepalive","signal","mode"];}function isValidParsedData(data){return Object.values(data).every(function(value){return isValidStrPattern(value);});}function parseMatchProps(propsToMatchStr){var PROPS_DIVIDER=" ";var PAIRS_MARKER=":";var isRequestProp=function isRequestProp(prop){return getRequestProps().includes(prop);};var propsObj={};var props=propsToMatchStr.split(PROPS_DIVIDER);props.forEach(function(prop){var dividerInd=prop.indexOf(PAIRS_MARKER);var key=prop.slice(0,dividerInd);if(isRequestProp(key)){var value=prop.slice(dividerInd+1);propsObj[key]=value;}else {propsObj.url=prop;}});return propsObj;}function isValidStrPattern(input){var FORWARD_SLASH="/";var str=escapeRegExp(input);if(input[0]===FORWARD_SLASH&&input[input.length-1]===FORWARD_SLASH){str=input.slice(1,-1);}var isValid;try{isValid=new RegExp(str);isValid=true;}catch(e){isValid=false;}return isValid;}function escapeRegExp(str){return str.replace(/[.*+?^${}()|[\]\\]/g,"\\$&");}function getWildcardPropertyInChain(base,chain){var lookThrough=arguments.length>2&&arguments[2]!==undefined?arguments[2]:false;var output=arguments.length>3&&arguments[3]!==undefined?arguments[3]:[];var pos=chain.indexOf(".");if(pos===-1){if(chain==="*"||chain==="[]"){for(var key in base){if(Object.prototype.hasOwnProperty.call(base,key)){output.push({base:base,prop:key});}}}else {output.push({base:base,prop:chain});}return output;}var prop=chain.slice(0,pos);var shouldLookThrough=prop==="[]"&&Array.isArray(base)||prop==="*"&&base instanceof Object;if(shouldLookThrough){var nextProp=chain.slice(pos+1);var baseKeys=Object.keys(base);baseKeys.forEach(function(key){var item=base[key];getWildcardPropertyInChain(item,nextProp,lookThrough,output);});}if(Array.isArray(base)){base.forEach(function(key){var nextBase=key;if(nextBase!==undefined){getWildcardPropertyInChain(nextBase,chain,lookThrough,output);}});}var nextBase=base[prop];chain=chain.slice(pos+1);if(nextBase!==undefined){getWildcardPropertyInChain(nextBase,chain,lookThrough,output);}return output;}function shouldAbortInlineOrInjectedScript(stackMatch,stackTrace){var INLINE_SCRIPT_STRING="inlineScript";var INJECTED_SCRIPT_STRING="injectedScript";var INJECTED_SCRIPT_MARKER="<anonymous>";var isInlineScript=function isInlineScript(match){return match.includes(INLINE_SCRIPT_STRING);};var isInjectedScript=function isInjectedScript(match){return match.includes(INJECTED_SCRIPT_STRING);};if(!(isInlineScript(stackMatch)||isInjectedScript(stackMatch))){return false;}var documentURL=window.location.href;var pos=documentURL.indexOf("#");if(pos!==-1){documentURL=documentURL.slice(0,pos);}var stackSteps=stackTrace.split("\n").slice(2).map(function(line){return line.trim();});var stackLines=stackSteps.map(function(line){var stack;var getStackTraceValues=/(.*?@)?(\S+)(:\d+)(:\d+)\)?$/.exec(line);if(getStackTraceValues){var _stackURL,_stackURL2;var stackURL=getStackTraceValues[2];var stackLine=getStackTraceValues[3];var stackCol=getStackTraceValues[4];if((_stackURL=stackURL)!==null&&_stackURL!==void 0&&_stackURL.startsWith("(")){stackURL=stackURL.slice(1);}if((_stackURL2=stackURL)!==null&&_stackURL2!==void 0&&_stackURL2.startsWith(INJECTED_SCRIPT_MARKER)){var _stackFunction;stackURL=INJECTED_SCRIPT_STRING;var stackFunction=getStackTraceValues[1]!==undefined?getStackTraceValues[1].slice(0,-1):line.slice(0,getStackTraceValues.index).trim();if((_stackFunction=stackFunction)!==null&&_stackFunction!==void 0&&_stackFunction.startsWith("at")){stackFunction=stackFunction.slice(2).trim();}stack="".concat(stackFunction," ").concat(stackURL).concat(stackLine).concat(stackCol).trim();}else if(stackURL===documentURL){stack="".concat(INLINE_SCRIPT_STRING).concat(stackLine).concat(stackCol).trim();}else {stack="".concat(stackURL).concat(stackLine).concat(stackCol).trim();}}else {stack=line;}return stack;});if(stackLines){for(var index=0;index<stackLines.length;index+=1){if(isInlineScript(stackMatch)&&stackLines[index].startsWith(INLINE_SCRIPT_STRING)&&stackLines[index].match(toRegExp(stackMatch))){return true;}if(isInjectedScript(stackMatch)&&stackLines[index].startsWith(INJECTED_SCRIPT_STRING)&&stackLines[index].match(toRegExp(stackMatch))){return true;}}}return false;}function getNativeRegexpTest(){var descriptor=Object.getOwnPropertyDescriptor(RegExp.prototype,"test");var nativeRegexTest=descriptor===null||descriptor===void 0?void 0:descriptor.value;if(descriptor&&typeof descriptor.value==="function"){return nativeRegexTest;}throw new Error("RegExp.prototype.test is not a function");}function backupRegExpValues(){try{var arrayOfRegexpValues=[];for(var index=1;index<10;index+=1){var value="$".concat(index);if(!RegExp[value]){break;}arrayOfRegexpValues.push(RegExp[value]);}return arrayOfRegexpValues;}catch(error){return [];}}function restoreRegExpValues(array){if(!array.length){return;}try{var stringPattern="";if(array.length===1){stringPattern="(".concat(array[0],")");}else {stringPattern=array.reduce(function(accumulator,currentValue,currentIndex){if(currentIndex===1){return "(".concat(accumulator,"),(").concat(currentValue,")");}return "".concat(accumulator,",(").concat(currentValue,")");});}var regExpGroup=new RegExp(stringPattern);array.toString().replace(regExpGroup,"");}catch(error){var message="Failed to restore RegExp values: ".concat(error);console.log(message);}}var updatedArgs=args?[].concat(source).concat(args):[source];try{jsonPruneXhrResponse.apply(this,updatedArgs);if(source.uniqueId){Object.defineProperty(Window.prototype.toString,uniqueIdentifier,{value:flag,enumerable:false,writable:false,configurable:false});}}catch(e){console.log(e);}}function log(source,args){var flag="done";var uniqueIdentifier=source.uniqueId+source.name+"_"+(Array.isArray(args)?args.join("_"):"");if(source.uniqueId){if(Window.prototype.toString[uniqueIdentifier]===flag){return;}}function log(){for(var _len=arguments.length,args=new Array(_len),_key=0;_key<_len;_key++){args[_key]=arguments[_key];}console.log(args);}var updatedArgs=args?[].concat(source).concat(args):[source];try{log.apply(this,updatedArgs);if(source.uniqueId){Object.defineProperty(Window.prototype.toString,uniqueIdentifier,{value:flag,enumerable:false,writable:false,configurable:false});}}catch(e){console.log(e);}}function logAddEventListener(source,args){var flag="done";var uniqueIdentifier=source.uniqueId+source.name+"_"+(Array.isArray(args)?args.join("_"):"");if(source.uniqueId){if(Window.prototype.toString[uniqueIdentifier]===flag){return;}}function logAddEventListener(source){var nativeAddEventListener=window.EventTarget.prototype.addEventListener;function addEventListenerWrapper(type,listener){var _this$constructor;if(validateType(type)&&validateListener(listener)){var message='addEventListener("'.concat(type,'", ').concat(listenerToString(listener),")");logMessage(source,message,true);hit(source);}else {var _message="Invalid event type or listener passed to addEventListener:\n        type: ".concat(convertTypeToString(type),"\n        listener: ").concat(convertTypeToString(listener));logMessage(source,_message,true);}var context=this;if(this&&((_this$constructor=this.constructor)===null||_this$constructor===void 0?void 0:_this$constructor.name)==="Window"&&this!==window){context=window;}for(var _len=arguments.length,args=new Array(_len>2?_len-2:0),_key=2;_key<_len;_key++){args[_key-2]=arguments[_key];}return nativeAddEventListener.apply(context,[type,listener,...args]);}var descriptor={configurable:true,set:function set(){},get:function get(){return addEventListenerWrapper;}};Object.defineProperty(window.EventTarget.prototype,"addEventListener",descriptor);Object.defineProperty(window,"addEventListener",descriptor);Object.defineProperty(document,"addEventListener",descriptor);}function hit(source){var ADGUARD_PREFIX="[AdGuard]";if(!source.verbose){return;}try{var trace=console.trace.bind(console);var label="".concat(ADGUARD_PREFIX," ");if(source.engine==="corelibs"){label+=source.ruleText;}else {if(source.domainName){label+="".concat(source.domainName);}if(source.args){label+="#%#//scriptlet('".concat(source.name,"', '").concat(source.args.join("', '"),"')");}else {label+="#%#//scriptlet('".concat(source.name,"')");}}if(trace){trace(label);}}catch(e){}if(typeof window.__debug==="function"){window.__debug(source);}}function validateType(type){return typeof type!=="undefined";}function validateListener(listener){return typeof listener!=="undefined"&&(typeof listener==="function"||typeof listener==="object"&&listener!==null&&"handleEvent"in listener&&typeof listener.handleEvent==="function");}function listenerToString(listener){return typeof listener==="function"?listener.toString():listener.handleEvent.toString();}function convertTypeToString(value){var output;if(typeof value==="undefined"){output="undefined";}else if(typeof value==="object"){if(value===null){output="null";}else {output=objectToString(value);}}else {output=String(value);}return output;}function logMessage(source,message){var forced=arguments.length>2&&arguments[2]!==undefined?arguments[2]:false;var convertMessageToString=arguments.length>3&&arguments[3]!==undefined?arguments[3]:true;var name=source.name,verbose=source.verbose;if(!forced&&!verbose){return;}var nativeConsole=console.log;if(!convertMessageToString){nativeConsole("".concat(name,":"),message);return;}nativeConsole("".concat(name,": ").concat(message));}function objectToString(obj){if(!obj||typeof obj!=="object"){return String(obj);}if(isEmptyObject(obj)){return "{}";}return Object.entries(obj).map(function(pair){var key=pair[0];var value=pair[1];var recordValueStr=value;if(value instanceof Object){recordValueStr="{ ".concat(objectToString(value)," }");}return "".concat(key,':"').concat(recordValueStr,'"');}).join(" ");}function isEmptyObject(obj){return Object.keys(obj).length===0&&!obj.prototype;}var updatedArgs=args?[].concat(source).concat(args):[source];try{logAddEventListener.apply(this,updatedArgs);if(source.uniqueId){Object.defineProperty(Window.prototype.toString,uniqueIdentifier,{value:flag,enumerable:false,writable:false,configurable:false});}}catch(e){console.log(e);}}function logEval(source,args){var flag="done";var uniqueIdentifier=source.uniqueId+source.name+"_"+(Array.isArray(args)?args.join("_"):"");if(source.uniqueId){if(Window.prototype.toString[uniqueIdentifier]===flag){return;}}function logEval(source){var nativeEval=window.eval;function evalWrapper(str){hit(source);logMessage(source,'eval("'.concat(str,'")'),true);return nativeEval(str);}window.eval=evalWrapper;var nativeFunction=window.Function;function FunctionWrapper(){hit(source);for(var _len=arguments.length,args=new Array(_len),_key=0;_key<_len;_key++){args[_key]=arguments[_key];}logMessage(source,"new Function(".concat(args.join(", "),")"),true);return nativeFunction.apply(this,[...args]);}FunctionWrapper.prototype=Object.create(nativeFunction.prototype);FunctionWrapper.prototype.constructor=FunctionWrapper;window.Function=FunctionWrapper;}function hit(source){var ADGUARD_PREFIX="[AdGuard]";if(!source.verbose){return;}try{var trace=console.trace.bind(console);var label="".concat(ADGUARD_PREFIX," ");if(source.engine==="corelibs"){label+=source.ruleText;}else {if(source.domainName){label+="".concat(source.domainName);}if(source.args){label+="#%#//scriptlet('".concat(source.name,"', '").concat(source.args.join("', '"),"')");}else {label+="#%#//scriptlet('".concat(source.name,"')");}}if(trace){trace(label);}}catch(e){}if(typeof window.__debug==="function"){window.__debug(source);}}function logMessage(source,message){var forced=arguments.length>2&&arguments[2]!==undefined?arguments[2]:false;var convertMessageToString=arguments.length>3&&arguments[3]!==undefined?arguments[3]:true;var name=source.name,verbose=source.verbose;if(!forced&&!verbose){return;}var nativeConsole=console.log;if(!convertMessageToString){nativeConsole("".concat(name,":"),message);return;}nativeConsole("".concat(name,": ").concat(message));}var updatedArgs=args?[].concat(source).concat(args):[source];try{logEval.apply(this,updatedArgs);if(source.uniqueId){Object.defineProperty(Window.prototype.toString,uniqueIdentifier,{value:flag,enumerable:false,writable:false,configurable:false});}}catch(e){console.log(e);}}function logOnStacktrace(source,args){var flag="done";var uniqueIdentifier=source.uniqueId+source.name+"_"+(Array.isArray(args)?args.join("_"):"");if(source.uniqueId){if(Window.prototype.toString[uniqueIdentifier]===flag){return;}}function logOnStacktrace(source,property){if(!property){return;}var refineStackTrace=function refineStackTrace(stackString){var regExpValues=backupRegExpValues();var stackSteps=stackString.split("\n").slice(2).map(function(line){return line.replace(/ {4}at /,"");});var logInfoArray=stackSteps.map(function(line){var funcName;var funcFullPath;var reg=/\(([^\)]+)\)/;var regFirefox=/(.*?@)(\S+)(:\d+):\d+\)?$/;if(line.match(reg)){funcName=line.split(" ").slice(0,-1).join(" ");funcFullPath=line.match(reg)[1];}else if(line.match(regFirefox)){funcName=line.split("@").slice(0,-1).join(" ");funcFullPath=line.match(regFirefox)[2];}else {funcName="function name is not available";funcFullPath=line;}return [funcName,funcFullPath];});var logInfoObject={};logInfoArray.forEach(function(pair){logInfoObject[pair[0]]=pair[1];});if(regExpValues.length&&regExpValues[0]!==RegExp.$1){restoreRegExpValues(regExpValues);}return logInfoObject;};var setChainPropAccess=function setChainPropAccess(owner,property){var chainInfo=getPropertyInChain(owner,property);var base=chainInfo.base;var prop=chainInfo.prop,chain=chainInfo.chain;if(chain){var setter=function setter(a){base=a;if(a instanceof Object){setChainPropAccess(a,chain);}};Object.defineProperty(owner,prop,{get:function get(){return base;},set:setter});return;}var value=base[prop];setPropertyAccess(base,prop,{get(){hit(source);logMessage(source,"Get ".concat(prop),true);console.table(refineStackTrace(new Error().stack));return value;},set(newValue){hit(source);logMessage(source,"Set ".concat(prop),true);console.table(refineStackTrace(new Error().stack));value=newValue;}});};setChainPropAccess(window,property);}function getPropertyInChain(base,chain){var pos=chain.indexOf(".");if(pos===-1){return {base:base,prop:chain};}var prop=chain.slice(0,pos);if(base===null){return {base:base,prop:prop,chain:chain};}var nextBase=base[prop];chain=chain.slice(pos+1);if((base instanceof Object||typeof base==="object")&&isEmptyObject(base)){return {base:base,prop:prop,chain:chain};}if(nextBase===null){return {base:base,prop:prop,chain:chain};}if(nextBase!==undefined){return getPropertyInChain(nextBase,chain);}Object.defineProperty(base,prop,{configurable:true});return {base:base,prop:prop,chain:chain};}function setPropertyAccess(object,property,descriptor){var currentDescriptor=Object.getOwnPropertyDescriptor(object,property);if(currentDescriptor&&!currentDescriptor.configurable){return false;}Object.defineProperty(object,property,descriptor);return true;}function hit(source){var ADGUARD_PREFIX="[AdGuard]";if(!source.verbose){return;}try{var trace=console.trace.bind(console);var label="".concat(ADGUARD_PREFIX," ");if(source.engine==="corelibs"){label+=source.ruleText;}else {if(source.domainName){label+="".concat(source.domainName);}if(source.args){label+="#%#//scriptlet('".concat(source.name,"', '").concat(source.args.join("', '"),"')");}else {label+="#%#//scriptlet('".concat(source.name,"')");}}if(trace){trace(label);}}catch(e){}if(typeof window.__debug==="function"){window.__debug(source);}}function logMessage(source,message){var forced=arguments.length>2&&arguments[2]!==undefined?arguments[2]:false;var convertMessageToString=arguments.length>3&&arguments[3]!==undefined?arguments[3]:true;var name=source.name,verbose=source.verbose;if(!forced&&!verbose){return;}var nativeConsole=console.log;if(!convertMessageToString){nativeConsole("".concat(name,":"),message);return;}nativeConsole("".concat(name,": ").concat(message));}function isEmptyObject(obj){return Object.keys(obj).length===0&&!obj.prototype;}function backupRegExpValues(){try{var arrayOfRegexpValues=[];for(var index=1;index<10;index+=1){var value="$".concat(index);if(!RegExp[value]){break;}arrayOfRegexpValues.push(RegExp[value]);}return arrayOfRegexpValues;}catch(error){return [];}}function restoreRegExpValues(array){if(!array.length){return;}try{var stringPattern="";if(array.length===1){stringPattern="(".concat(array[0],")");}else {stringPattern=array.reduce(function(accumulator,currentValue,currentIndex){if(currentIndex===1){return "(".concat(accumulator,"),(").concat(currentValue,")");}return "".concat(accumulator,",(").concat(currentValue,")");});}var regExpGroup=new RegExp(stringPattern);array.toString().replace(regExpGroup,"");}catch(error){var message="Failed to restore RegExp values: ".concat(error);console.log(message);}}var updatedArgs=args?[].concat(source).concat(args):[source];try{logOnStacktrace.apply(this,updatedArgs);if(source.uniqueId){Object.defineProperty(Window.prototype.toString,uniqueIdentifier,{value:flag,enumerable:false,writable:false,configurable:false});}}catch(e){console.log(e);}}function m3uPrune(source,args){var flag="done";var uniqueIdentifier=source.uniqueId+source.name+"_"+(Array.isArray(args)?args.join("_"):"");if(source.uniqueId){if(Window.prototype.toString[uniqueIdentifier]===flag){return;}}function m3uPrune(source,propsToRemove){var urlToMatch=arguments.length>2&&arguments[2]!==undefined?arguments[2]:"";var verbose=arguments.length>3&&arguments[3]!==undefined?arguments[3]:false;if(typeof Reflect==="undefined"||typeof fetch==="undefined"||typeof Proxy==="undefined"||typeof Response==="undefined"){return;}var shouldPruneResponse=false;var shouldLogContent=verbose==="true";var urlMatchRegexp=toRegExp(urlToMatch);var SEGMENT_MARKER="#";var AD_MARKER={ASSET:"#EXT-X-ASSET:",CUE:"#EXT-X-CUE:",CUE_IN:"#EXT-X-CUE-IN",DISCONTINUITY:"#EXT-X-DISCONTINUITY",EXTINF:"#EXTINF",EXTM3U:"#EXTM3U",SCTE35:"#EXT-X-SCTE35:"};var COMCAST_AD_MARKER={AD:"-AD-",VAST:"-VAST-",VMAP_AD:"-VMAP-AD-",VMAP_AD_BREAK:"#EXT-X-VMAP-AD-BREAK:"};var TAGS_ALLOWLIST=["#EXT-X-TARGETDURATION","#EXT-X-MEDIA-SEQUENCE","#EXT-X-DISCONTINUITY-SEQUENCE","#EXT-X-ENDLIST","#EXT-X-PLAYLIST-TYPE","#EXT-X-I-FRAMES-ONLY","#EXT-X-MEDIA","#EXT-X-STREAM-INF","#EXT-X-I-FRAME-STREAM-INF","#EXT-X-SESSION-DATA","#EXT-X-SESSION-KEY","#EXT-X-INDEPENDENT-SEGMENTS","#EXT-X-START"];var isAllowedTag=function isAllowedTag(str){return TAGS_ALLOWLIST.some(function(el){return str.startsWith(el);});};var pruneExtinfFromVmapBlock=function pruneExtinfFromVmapBlock(lines,i){var array=lines.slice();var index=i;if(array[index].includes(AD_MARKER.EXTINF)){array[index]=undefined;index+=1;if(array[index].includes(AD_MARKER.DISCONTINUITY)){array[index]=undefined;index+=1;var prunedExtinf=pruneExtinfFromVmapBlock(array,index);array=prunedExtinf.array;index=prunedExtinf.index;}}return {array:array,index:index};};var pruneVmapBlock=function pruneVmapBlock(lines){var array=lines.slice();for(var i=0;i<array.length-1;i+=1){if(array[i].includes(COMCAST_AD_MARKER.VMAP_AD)||array[i].includes(COMCAST_AD_MARKER.VAST)||array[i].includes(COMCAST_AD_MARKER.AD)){array[i]=undefined;if(array[i+1].includes(AD_MARKER.EXTINF)){i+=1;var prunedExtinf=pruneExtinfFromVmapBlock(array,i);array=prunedExtinf.array;i=prunedExtinf.index-1;}}}return array;};var pruneSpliceoutBlock=function pruneSpliceoutBlock(line,index,array){if(!line.startsWith(AD_MARKER.CUE)){return line;}line=undefined;index+=1;if(array[index].startsWith(AD_MARKER.ASSET)){array[index]=undefined;index+=1;}if(array[index].startsWith(AD_MARKER.SCTE35)){array[index]=undefined;index+=1;}if(array[index].startsWith(AD_MARKER.CUE_IN)){array[index]=undefined;index+=1;}if(array[index].startsWith(AD_MARKER.SCTE35)){array[index]=undefined;}return line;};var removeM3ULineRegexp=toRegExp(propsToRemove);var pruneInfBlock=function pruneInfBlock(line,index,array){if(!line.startsWith(AD_MARKER.EXTINF)){return line;}if(!removeM3ULineRegexp.test(array[index+1])){return line;}if(!isAllowedTag(array[index])){array[index]=undefined;}index+=1;if(!isAllowedTag(array[index])){array[index]=undefined;}index+=1;if(array[index].startsWith(AD_MARKER.DISCONTINUITY)){array[index]=undefined;}return line;};var pruneSegments=function pruneSegments(lines){for(var i=0;i<lines.length-1;i+=1){var _lines$i;if((_lines$i=lines[i])!==null&&_lines$i!==void 0&&_lines$i.startsWith(SEGMENT_MARKER)&&removeM3ULineRegexp.test(lines[i])){var segmentName=lines[i].substring(0,lines[i].indexOf(":"));if(!segmentName){return lines;}lines[i]=undefined;i+=1;for(var j=i;j<lines.length;j+=1){if(!lines[j].includes(segmentName)&&!isAllowedTag(lines[j])){lines[j]=undefined;}else {i=j-1;break;}}}}return lines;};var isM3U=function isM3U(text){if(typeof text==="string"){var trimmedText=text.trim();return trimmedText.startsWith(AD_MARKER.EXTM3U)||trimmedText.startsWith(COMCAST_AD_MARKER.VMAP_AD_BREAK);}return false;};var isPruningNeeded=function isPruningNeeded(text,regexp){return isM3U(text)&&regexp.test(text);};var pruneM3U=function pruneM3U(text){if(shouldLogContent){logMessage(source,"Original M3U content:\n".concat(text));}var lines=text.split(/\r?\n/);if(text.includes(COMCAST_AD_MARKER.VMAP_AD_BREAK)){lines=pruneVmapBlock(lines);lines=lines.filter(function(l){return !!l;}).join("\n");if(shouldLogContent){logMessage(source,"Modified M3U content:\n".concat(lines));}return lines;}lines=pruneSegments(lines);lines=lines.map(function(line,index,array){if(typeof line==="undefined"){return line;}line=pruneSpliceoutBlock(line,index,array);if(typeof line!=="undefined"){line=pruneInfBlock(line,index,array);}return line;}).filter(function(l){return !!l;}).join("\n");if(shouldLogContent){logMessage(source,"Modified M3U content:\n".concat(lines));}return lines;};var nativeOpen=window.XMLHttpRequest.prototype.open;var nativeSend=window.XMLHttpRequest.prototype.send;var xhrData;var openWrapper=function openWrapper(target,thisArg,args){xhrData=getXhrData.apply(null,args);if(matchRequestProps(source,urlToMatch,xhrData)){thisArg.shouldBePruned=true;}if(thisArg.shouldBePruned){thisArg.collectedHeaders=[];var setRequestHeaderWrapper=function setRequestHeaderWrapper(target,thisArg,args){thisArg.collectedHeaders.push(args);return Reflect.apply(target,thisArg,args);};var setRequestHeaderHandler={apply:setRequestHeaderWrapper};thisArg.setRequestHeader=new Proxy(thisArg.setRequestHeader,setRequestHeaderHandler);}return Reflect.apply(target,thisArg,args);};var sendWrapper=function sendWrapper(target,thisArg,args){var allowedResponseTypeValues=["","text"];if(!thisArg.shouldBePruned||!allowedResponseTypeValues.includes(thisArg.responseType)){return Reflect.apply(target,thisArg,args);}var forgedRequest=new XMLHttpRequest();forgedRequest.addEventListener("readystatechange",function(){if(forgedRequest.readyState!==4){return;}var readyState=forgedRequest.readyState,response=forgedRequest.response,responseText=forgedRequest.responseText,responseURL=forgedRequest.responseURL,responseXML=forgedRequest.responseXML,status=forgedRequest.status,statusText=forgedRequest.statusText;var content=responseText||response;if(typeof content!=="string"){return;}if(!propsToRemove){if(isM3U(response)){var message="XMLHttpRequest.open() URL: ".concat(responseURL,"\nresponse: ").concat(response);logMessage(source,message);}}else {shouldPruneResponse=isPruningNeeded(response,removeM3ULineRegexp);}var responseContent=shouldPruneResponse?pruneM3U(response):response;Object.defineProperties(thisArg,{readyState:{value:readyState,writable:false},responseURL:{value:responseURL,writable:false},responseXML:{value:responseXML,writable:false},status:{value:status,writable:false},statusText:{value:statusText,writable:false},response:{value:responseContent,writable:false},responseText:{value:responseContent,writable:false}});setTimeout(function(){var stateEvent=new Event("readystatechange");thisArg.dispatchEvent(stateEvent);var loadEvent=new Event("load");thisArg.dispatchEvent(loadEvent);var loadEndEvent=new Event("loadend");thisArg.dispatchEvent(loadEndEvent);},1);hit(source);});nativeOpen.apply(forgedRequest,[xhrData.method,xhrData.url]);thisArg.collectedHeaders.forEach(function(header){var name=header[0];var value=header[1];forgedRequest.setRequestHeader(name,value);});thisArg.collectedHeaders=[];try{nativeSend.call(forgedRequest,args);}catch(_unused){return Reflect.apply(target,thisArg,args);}return undefined;};var openHandler={apply:openWrapper};var sendHandler={apply:sendWrapper};XMLHttpRequest.prototype.open=new Proxy(XMLHttpRequest.prototype.open,openHandler);XMLHttpRequest.prototype.send=new Proxy(XMLHttpRequest.prototype.send,sendHandler);var nativeFetch=window.fetch;var fetchWrapper=async function fetchWrapper(target,thisArg,args){var fetchURL=args[0]instanceof Request?args[0].url:args[0];if(typeof fetchURL!=="string"||fetchURL.length===0){return Reflect.apply(target,thisArg,args);}if(urlMatchRegexp.test(fetchURL)){var response=await nativeFetch(...args);var clonedResponse=response.clone();var responseText=await response.text();if(!propsToRemove&&isM3U(responseText)){var message="fetch URL: ".concat(fetchURL,"\nresponse text: ").concat(responseText);logMessage(source,message);return clonedResponse;}if(isPruningNeeded(responseText,removeM3ULineRegexp)){var prunedText=pruneM3U(responseText);hit(source);return new Response(prunedText,{status:response.status,statusText:response.statusText,headers:response.headers});}return clonedResponse;}return Reflect.apply(target,thisArg,args);};var fetchHandler={apply:fetchWrapper};window.fetch=new Proxy(window.fetch,fetchHandler);}function hit(source){var ADGUARD_PREFIX="[AdGuard]";if(!source.verbose){return;}try{var trace=console.trace.bind(console);var label="".concat(ADGUARD_PREFIX," ");if(source.engine==="corelibs"){label+=source.ruleText;}else {if(source.domainName){label+="".concat(source.domainName);}if(source.args){label+="#%#//scriptlet('".concat(source.name,"', '").concat(source.args.join("', '"),"')");}else {label+="#%#//scriptlet('".concat(source.name,"')");}}if(trace){trace(label);}}catch(e){}if(typeof window.__debug==="function"){window.__debug(source);}}function toRegExp(rawInput){var input=rawInput||"";var DEFAULT_VALUE=".?";var FORWARD_SLASH="/";if(input===""){return new RegExp(DEFAULT_VALUE);}var delimiterIndex=input.lastIndexOf(FORWARD_SLASH);var flagsPart=input.substring(delimiterIndex+1);var regExpPart=input.substring(0,delimiterIndex+1);var isValidRegExpFlag=function isValidRegExpFlag(flag){if(!flag){return false;}try{new RegExp("",flag);return true;}catch(ex){return false;}};var getRegExpFlags=function getRegExpFlags(regExpStr,flagsStr){if(regExpStr.startsWith(FORWARD_SLASH)&&regExpStr.endsWith(FORWARD_SLASH)&&!regExpStr.endsWith("\\/")&&isValidRegExpFlag(flagsStr)){return flagsStr;}return "";};var flags=getRegExpFlags(regExpPart,flagsPart);if(input.startsWith(FORWARD_SLASH)&&input.endsWith(FORWARD_SLASH)||flags){var regExpInput=flags?regExpPart:input;return new RegExp(regExpInput.slice(1,-1),flags);}var escaped=input.replace(/\\'/g,"'").replace(/\\"/g,'"').replace(/[.*+?^${}()|[\]\\]/g,"\\$&");return new RegExp(escaped);}function logMessage(source,message){var forced=arguments.length>2&&arguments[2]!==undefined?arguments[2]:false;var convertMessageToString=arguments.length>3&&arguments[3]!==undefined?arguments[3]:true;var name=source.name,verbose=source.verbose;if(!forced&&!verbose){return;}var nativeConsole=console.log;if(!convertMessageToString){nativeConsole("".concat(name,":"),message);return;}nativeConsole("".concat(name,": ").concat(message));}function getXhrData(method,url,async,user,password){return {method:method,url:url,async:async,user:user,password:password};}function matchRequestProps(source,propsToMatch,requestData){if(propsToMatch===""||propsToMatch==="*"){return true;}var isMatched;var parsedData=parseMatchProps(propsToMatch);if(!isValidParsedData(parsedData)){logMessage(source,"Invalid parameter: ".concat(propsToMatch));isMatched=false;}else {var matchData=getMatchPropsData(parsedData);var matchKeys=Object.keys(matchData);isMatched=matchKeys.every(function(matchKey){var matchValue=matchData[matchKey];var dataValue=requestData[matchKey];return Object.prototype.hasOwnProperty.call(requestData,matchKey)&&typeof dataValue==="string"&&(matchValue===null||matchValue===void 0?void 0:matchValue.test(dataValue));});}return isMatched;}function getMatchPropsData(data){var matchData={};var dataKeys=Object.keys(data);dataKeys.forEach(function(key){matchData[key]=toRegExp(data[key]);});return matchData;}function getRequestProps(){return ["url","method","headers","body","credentials","cache","redirect","referrer","referrerPolicy","integrity","keepalive","signal","mode"];}function isValidParsedData(data){return Object.values(data).every(function(value){return isValidStrPattern(value);});}function parseMatchProps(propsToMatchStr){var PROPS_DIVIDER=" ";var PAIRS_MARKER=":";var isRequestProp=function isRequestProp(prop){return getRequestProps().includes(prop);};var propsObj={};var props=propsToMatchStr.split(PROPS_DIVIDER);props.forEach(function(prop){var dividerInd=prop.indexOf(PAIRS_MARKER);var key=prop.slice(0,dividerInd);if(isRequestProp(key)){var value=prop.slice(dividerInd+1);propsObj[key]=value;}else {propsObj.url=prop;}});return propsObj;}function isValidStrPattern(input){var FORWARD_SLASH="/";var str=escapeRegExp(input);if(input[0]===FORWARD_SLASH&&input[input.length-1]===FORWARD_SLASH){str=input.slice(1,-1);}var isValid;try{isValid=new RegExp(str);isValid=true;}catch(e){isValid=false;}return isValid;}function escapeRegExp(str){return str.replace(/[.*+?^${}()|[\]\\]/g,"\\$&");}var updatedArgs=args?[].concat(source).concat(args):[source];try{m3uPrune.apply(this,updatedArgs);if(source.uniqueId){Object.defineProperty(Window.prototype.toString,uniqueIdentifier,{value:flag,enumerable:false,writable:false,configurable:false});}}catch(e){console.log(e);}}function metrikaYandexTag(source,args){var flag="done";var uniqueIdentifier=source.uniqueId+source.name+"_"+(Array.isArray(args)?args.join("_"):"");if(source.uniqueId){if(Window.prototype.toString[uniqueIdentifier]===flag){return;}}function metrikaYandexTag(source){var asyncCallbackFromOptions=function asyncCallbackFromOptions(id,param){var options=arguments.length>2&&arguments[2]!==undefined?arguments[2]:{};var callback=options.callback;var ctx=options.ctx;if(typeof callback==="function"){callback=ctx!==undefined?callback.bind(ctx):callback;setTimeout(function(){return callback();});}};var addFileExtension=noopFunc;var extLink=asyncCallbackFromOptions;var file=asyncCallbackFromOptions;var getClientID=function getClientID(id,cb){if(!cb){return;}setTimeout(cb(null));};var hitFunc=asyncCallbackFromOptions;var notBounce=asyncCallbackFromOptions;var params=noopFunc;var reachGoal=function reachGoal(id,target,params,callback,ctx){asyncCallbackFromOptions(null,null,{callback:callback,ctx:ctx});};var setUserID=noopFunc;var userParams=noopFunc;var destruct=noopFunc;var api={addFileExtension:addFileExtension,extLink:extLink,file:file,getClientID:getClientID,hit:hitFunc,notBounce:notBounce,params:params,reachGoal:reachGoal,setUserID:setUserID,userParams:userParams,destruct:destruct};function ym(id,funcName){for(var _len=arguments.length,args=new Array(_len>2?_len-2:0),_key=2;_key<_len;_key++){args[_key-2]=arguments[_key];}return api[funcName]&&api[funcName](id,...args);}function init(id){window["yaCounter".concat(id)]=api;document.dispatchEvent(new Event("yacounter".concat(id,"inited")));}if(typeof window.ym==="undefined"){window.ym=ym;ym.a=[];}else if(window.ym&&window.ym.a){ym.a=window.ym.a;window.ym=ym;window.ym.a.forEach(function(params){var id=params[0];init(id);});}hit(source);}function hit(source){var ADGUARD_PREFIX="[AdGuard]";if(!source.verbose){return;}try{var trace=console.trace.bind(console);var label="".concat(ADGUARD_PREFIX," ");if(source.engine==="corelibs"){label+=source.ruleText;}else {if(source.domainName){label+="".concat(source.domainName);}if(source.args){label+="#%#//scriptlet('".concat(source.name,"', '").concat(source.args.join("', '"),"')");}else {label+="#%#//scriptlet('".concat(source.name,"')");}}if(trace){trace(label);}}catch(e){}if(typeof window.__debug==="function"){window.__debug(source);}}function noopFunc(){}var updatedArgs=args?[].concat(source).concat(args):[source];try{metrikaYandexTag.apply(this,updatedArgs);if(source.uniqueId){Object.defineProperty(Window.prototype.toString,uniqueIdentifier,{value:flag,enumerable:false,writable:false,configurable:false});}}catch(e){console.log(e);}}function metrikaYandexWatch(source,args){var flag="done";var uniqueIdentifier=source.uniqueId+source.name+"_"+(Array.isArray(args)?args.join("_"):"");if(source.uniqueId){if(Window.prototype.toString[uniqueIdentifier]===flag){return;}}function metrikaYandexWatch(source){var cbName="yandex_metrika_callbacks";var asyncCallbackFromOptions=function asyncCallbackFromOptions(){var options=arguments.length>0&&arguments[0]!==undefined?arguments[0]:{};var callback=options.callback;var ctx=options.ctx;if(typeof callback==="function"){callback=ctx!==undefined?callback.bind(ctx):callback;setTimeout(function(){return callback();});}};function Metrika(){}Metrika.counters=noopArray;Metrika.prototype.addFileExtension=noopFunc;Metrika.prototype.getClientID=noopFunc;Metrika.prototype.setUserID=noopFunc;Metrika.prototype.userParams=noopFunc;Metrika.prototype.params=noopFunc;Metrika.prototype.counters=noopArray;Metrika.prototype.extLink=function(url,options){asyncCallbackFromOptions(options);};Metrika.prototype.file=function(url,options){asyncCallbackFromOptions(options);};Metrika.prototype.hit=function(url,options){asyncCallbackFromOptions(options);};Metrika.prototype.reachGoal=function(target,params,cb,ctx){asyncCallbackFromOptions({callback:cb,ctx:ctx});};Metrika.prototype.notBounce=asyncCallbackFromOptions;if(window.Ya){window.Ya.Metrika=Metrika;}else {window.Ya={Metrika:Metrika};}if(window[cbName]&&Array.isArray(window[cbName])){window[cbName].forEach(function(func){if(typeof func==="function"){func();}});}hit(source);}function hit(source){var ADGUARD_PREFIX="[AdGuard]";if(!source.verbose){return;}try{var trace=console.trace.bind(console);var label="".concat(ADGUARD_PREFIX," ");if(source.engine==="corelibs"){label+=source.ruleText;}else {if(source.domainName){label+="".concat(source.domainName);}if(source.args){label+="#%#//scriptlet('".concat(source.name,"', '").concat(source.args.join("', '"),"')");}else {label+="#%#//scriptlet('".concat(source.name,"')");}}if(trace){trace(label);}}catch(e){}if(typeof window.__debug==="function"){window.__debug(source);}}function noopFunc(){}function noopArray(){return [];}var updatedArgs=args?[].concat(source).concat(args):[source];try{metrikaYandexWatch.apply(this,updatedArgs);if(source.uniqueId){Object.defineProperty(Window.prototype.toString,uniqueIdentifier,{value:flag,enumerable:false,writable:false,configurable:false});}}catch(e){console.log(e);}}function noProtectedAudience(source,args){var flag="done";var uniqueIdentifier=source.uniqueId+source.name+"_"+(Array.isArray(args)?args.join("_"):"");if(source.uniqueId){if(Window.prototype.toString[uniqueIdentifier]===flag){return;}}function noProtectedAudience(source){if(Document instanceof Object===false){return;}var protectedAudienceMethods={joinAdInterestGroup:noopResolveVoid,runAdAuction:noopResolveNull,leaveAdInterestGroup:noopResolveVoid,clearOriginJoinedAdInterestGroups:noopResolveVoid,createAuctionNonce:noopStr,updateAdInterestGroups:noopFunc};for(var _i=0,_Object$keys=Object.keys(protectedAudienceMethods);_i<_Object$keys.length;_i++){var key=_Object$keys[_i];var methodName=key;var prototype=Navigator.prototype;if(!Object.prototype.hasOwnProperty.call(prototype,methodName)||prototype[methodName]instanceof Function===false){continue;}prototype[methodName]=protectedAudienceMethods[methodName];}hit(source);}function hit(source){var ADGUARD_PREFIX="[AdGuard]";if(!source.verbose){return;}try{var trace=console.trace.bind(console);var label="".concat(ADGUARD_PREFIX," ");if(source.engine==="corelibs"){label+=source.ruleText;}else {if(source.domainName){label+="".concat(source.domainName);}if(source.args){label+="#%#//scriptlet('".concat(source.name,"', '").concat(source.args.join("', '"),"')");}else {label+="#%#//scriptlet('".concat(source.name,"')");}}if(trace){trace(label);}}catch(e){}if(typeof window.__debug==="function"){window.__debug(source);}}function noopStr(){return "";}function noopFunc(){}function noopResolveVoid(){return Promise.resolve(undefined);}function noopResolveNull(){return Promise.resolve(null);}var updatedArgs=args?[].concat(source).concat(args):[source];try{noProtectedAudience.apply(this,updatedArgs);if(source.uniqueId){Object.defineProperty(Window.prototype.toString,uniqueIdentifier,{value:flag,enumerable:false,writable:false,configurable:false});}}catch(e){console.log(e);}}function noTopics(source,args){var flag="done";var uniqueIdentifier=source.uniqueId+source.name+"_"+(Array.isArray(args)?args.join("_"):"");if(source.uniqueId){if(Window.prototype.toString[uniqueIdentifier]===flag){return;}}function noTopics(source){var TOPICS_PROPERTY_NAME="browsingTopics";if(Document instanceof Object===false){return;}if(!Object.prototype.hasOwnProperty.call(Document.prototype,TOPICS_PROPERTY_NAME)||Document.prototype[TOPICS_PROPERTY_NAME]instanceof Function===false){return;}Document.prototype[TOPICS_PROPERTY_NAME]=function(){return noopPromiseResolve("[]");};hit(source);}function hit(source){var ADGUARD_PREFIX="[AdGuard]";if(!source.verbose){return;}try{var trace=console.trace.bind(console);var label="".concat(ADGUARD_PREFIX," ");if(source.engine==="corelibs"){label+=source.ruleText;}else {if(source.domainName){label+="".concat(source.domainName);}if(source.args){label+="#%#//scriptlet('".concat(source.name,"', '").concat(source.args.join("', '"),"')");}else {label+="#%#//scriptlet('".concat(source.name,"')");}}if(trace){trace(label);}}catch(e){}if(typeof window.__debug==="function"){window.__debug(source);}}function noopPromiseResolve(){var responseBody=arguments.length>0&&arguments[0]!==undefined?arguments[0]:"{}";var responseUrl=arguments.length>1&&arguments[1]!==undefined?arguments[1]:"";var responseType=arguments.length>2&&arguments[2]!==undefined?arguments[2]:"basic";if(typeof Response==="undefined"){return;}var response=new Response(responseBody,{status:200,statusText:"OK"});if(responseType==="opaque"){Object.defineProperties(response,{body:{value:null},status:{value:0},statusText:{value:""},url:{value:""},type:{value:responseType}});}else {Object.defineProperties(response,{url:{value:responseUrl},type:{value:responseType}});}return Promise.resolve(response);}var updatedArgs=args?[].concat(source).concat(args):[source];try{noTopics.apply(this,updatedArgs);if(source.uniqueId){Object.defineProperty(Window.prototype.toString,uniqueIdentifier,{value:flag,enumerable:false,writable:false,configurable:false});}}catch(e){console.log(e);}}function noeval(source,args){var flag="done";var uniqueIdentifier=source.uniqueId+source.name+"_"+(Array.isArray(args)?args.join("_"):"");if(source.uniqueId){if(Window.prototype.toString[uniqueIdentifier]===flag){return;}}function noeval(source){window.eval=function evalWrapper(s){hit(source);logMessage(source,"AdGuard has prevented eval:\n".concat(s),true);}.bind();}function hit(source){var ADGUARD_PREFIX="[AdGuard]";if(!source.verbose){return;}try{var trace=console.trace.bind(console);var label="".concat(ADGUARD_PREFIX," ");if(source.engine==="corelibs"){label+=source.ruleText;}else {if(source.domainName){label+="".concat(source.domainName);}if(source.args){label+="#%#//scriptlet('".concat(source.name,"', '").concat(source.args.join("', '"),"')");}else {label+="#%#//scriptlet('".concat(source.name,"')");}}if(trace){trace(label);}}catch(e){}if(typeof window.__debug==="function"){window.__debug(source);}}function logMessage(source,message){var forced=arguments.length>2&&arguments[2]!==undefined?arguments[2]:false;var convertMessageToString=arguments.length>3&&arguments[3]!==undefined?arguments[3]:true;var name=source.name,verbose=source.verbose;if(!forced&&!verbose){return;}var nativeConsole=console.log;if(!convertMessageToString){nativeConsole("".concat(name,":"),message);return;}nativeConsole("".concat(name,": ").concat(message));}var updatedArgs=args?[].concat(source).concat(args):[source];try{noeval.apply(this,updatedArgs);if(source.uniqueId){Object.defineProperty(Window.prototype.toString,uniqueIdentifier,{value:flag,enumerable:false,writable:false,configurable:false});}}catch(e){console.log(e);}}function nowebrtc(source,args){var flag="done";var uniqueIdentifier=source.uniqueId+source.name+"_"+(Array.isArray(args)?args.join("_"):"");if(source.uniqueId){if(Window.prototype.toString[uniqueIdentifier]===flag){return;}}function nowebrtc(source){var propertyName="";if(window.RTCPeerConnection){propertyName="RTCPeerConnection";}else if(window.webkitRTCPeerConnection){propertyName="webkitRTCPeerConnection";}if(propertyName===""){return;}var rtcReplacement=function rtcReplacement(config){var message="Document tried to create an RTCPeerConnection: ".concat(convertRtcConfigToString(config));logMessage(source,message);hit(source);};rtcReplacement.prototype={close:noopFunc,createDataChannel:noopFunc,createOffer:noopFunc,setRemoteDescription:noopFunc};var rtc=window[propertyName];window[propertyName]=rtcReplacement;if(rtc.prototype){rtc.prototype.createDataChannel=function(a,b){return {close:noopFunc,send:noopFunc};}.bind(null);}}function hit(source){var ADGUARD_PREFIX="[AdGuard]";if(!source.verbose){return;}try{var trace=console.trace.bind(console);var label="".concat(ADGUARD_PREFIX," ");if(source.engine==="corelibs"){label+=source.ruleText;}else {if(source.domainName){label+="".concat(source.domainName);}if(source.args){label+="#%#//scriptlet('".concat(source.name,"', '").concat(source.args.join("', '"),"')");}else {label+="#%#//scriptlet('".concat(source.name,"')");}}if(trace){trace(label);}}catch(e){}if(typeof window.__debug==="function"){window.__debug(source);}}function noopFunc(){}function logMessage(source,message){var forced=arguments.length>2&&arguments[2]!==undefined?arguments[2]:false;var convertMessageToString=arguments.length>3&&arguments[3]!==undefined?arguments[3]:true;var name=source.name,verbose=source.verbose;if(!forced&&!verbose){return;}var nativeConsole=console.log;if(!convertMessageToString){nativeConsole("".concat(name,":"),message);return;}nativeConsole("".concat(name,": ").concat(message));}function convertRtcConfigToString(config){var UNDEF_STR="undefined";var str=UNDEF_STR;if(config===null){str="null";}else if(config instanceof Object){var SERVERS_PROP_NAME="iceServers";var URLS_PROP_NAME="urls";if(Object.prototype.hasOwnProperty.call(config,SERVERS_PROP_NAME)&&config[SERVERS_PROP_NAME]&&Object.prototype.hasOwnProperty.call(config[SERVERS_PROP_NAME][0],URLS_PROP_NAME)&&!!config[SERVERS_PROP_NAME][0][URLS_PROP_NAME]){str=config[SERVERS_PROP_NAME][0][URLS_PROP_NAME].toString();}}return str;}var updatedArgs=args?[].concat(source).concat(args):[source];try{nowebrtc.apply(this,updatedArgs);if(source.uniqueId){Object.defineProperty(Window.prototype.toString,uniqueIdentifier,{value:flag,enumerable:false,writable:false,configurable:false});}}catch(e){console.log(e);}}function preventAddEventListener(source,args){var flag="done";var uniqueIdentifier=source.uniqueId+source.name+"_"+(Array.isArray(args)?args.join("_"):"");if(source.uniqueId){if(Window.prototype.toString[uniqueIdentifier]===flag){return;}}function preventAddEventListener(source,typeSearch,listenerSearch){var typeSearchRegexp=toRegExp(typeSearch);var listenerSearchRegexp=toRegExp(listenerSearch);var nativeAddEventListener=window.EventTarget.prototype.addEventListener;function addEventListenerWrapper(type,listener){var _this$constructor;var shouldPrevent=false;if(validateType(type)&&validateListener(listener)){shouldPrevent=typeSearchRegexp.test(type.toString())&&listenerSearchRegexp.test(listenerToString(listener));}if(shouldPrevent){hit(source);return undefined;}var context=this;if(this&&((_this$constructor=this.constructor)===null||_this$constructor===void 0?void 0:_this$constructor.name)==="Window"&&this!==window){context=window;}for(var _len=arguments.length,args=new Array(_len>2?_len-2:0),_key=2;_key<_len;_key++){args[_key-2]=arguments[_key];}return nativeAddEventListener.apply(context,[type,listener,...args]);}var descriptor={configurable:true,set:function set(){},get:function get(){return addEventListenerWrapper;}};Object.defineProperty(window.EventTarget.prototype,"addEventListener",descriptor);Object.defineProperty(window,"addEventListener",descriptor);Object.defineProperty(document,"addEventListener",descriptor);}function hit(source){var ADGUARD_PREFIX="[AdGuard]";if(!source.verbose){return;}try{var trace=console.trace.bind(console);var label="".concat(ADGUARD_PREFIX," ");if(source.engine==="corelibs"){label+=source.ruleText;}else {if(source.domainName){label+="".concat(source.domainName);}if(source.args){label+="#%#//scriptlet('".concat(source.name,"', '").concat(source.args.join("', '"),"')");}else {label+="#%#//scriptlet('".concat(source.name,"')");}}if(trace){trace(label);}}catch(e){}if(typeof window.__debug==="function"){window.__debug(source);}}function toRegExp(rawInput){var input=rawInput||"";var DEFAULT_VALUE=".?";var FORWARD_SLASH="/";if(input===""){return new RegExp(DEFAULT_VALUE);}var delimiterIndex=input.lastIndexOf(FORWARD_SLASH);var flagsPart=input.substring(delimiterIndex+1);var regExpPart=input.substring(0,delimiterIndex+1);var isValidRegExpFlag=function isValidRegExpFlag(flag){if(!flag){return false;}try{new RegExp("",flag);return true;}catch(ex){return false;}};var getRegExpFlags=function getRegExpFlags(regExpStr,flagsStr){if(regExpStr.startsWith(FORWARD_SLASH)&&regExpStr.endsWith(FORWARD_SLASH)&&!regExpStr.endsWith("\\/")&&isValidRegExpFlag(flagsStr)){return flagsStr;}return "";};var flags=getRegExpFlags(regExpPart,flagsPart);if(input.startsWith(FORWARD_SLASH)&&input.endsWith(FORWARD_SLASH)||flags){var regExpInput=flags?regExpPart:input;return new RegExp(regExpInput.slice(1,-1),flags);}var escaped=input.replace(/\\'/g,"'").replace(/\\"/g,'"').replace(/[.*+?^${}()|[\]\\]/g,"\\$&");return new RegExp(escaped);}function validateType(type){return typeof type!=="undefined";}function validateListener(listener){return typeof listener!=="undefined"&&(typeof listener==="function"||typeof listener==="object"&&listener!==null&&"handleEvent"in listener&&typeof listener.handleEvent==="function");}function listenerToString(listener){return typeof listener==="function"?listener.toString():listener.handleEvent.toString();}var updatedArgs=args?[].concat(source).concat(args):[source];try{preventAddEventListener.apply(this,updatedArgs);if(source.uniqueId){Object.defineProperty(Window.prototype.toString,uniqueIdentifier,{value:flag,enumerable:false,writable:false,configurable:false});}}catch(e){console.log(e);}}function preventAdfly(source,args){var flag="done";var uniqueIdentifier=source.uniqueId+source.name+"_"+(Array.isArray(args)?args.join("_"):"");if(source.uniqueId){if(Window.prototype.toString[uniqueIdentifier]===flag){return;}}function preventAdfly(source){var isDigit=function isDigit(data){return /^\d$/.test(data);};var handler=function handler(encodedURL){var evenChars="";var oddChars="";for(var i=0;i<encodedURL.length;i+=1){if(i%2===0){evenChars+=encodedURL.charAt(i);}else {oddChars=encodedURL.charAt(i)+oddChars;}}var data=(evenChars+oddChars).split("");for(var _i=0;_i<data.length;_i+=1){if(isDigit(data[_i])){for(var ii=_i+1;ii<data.length;ii+=1){if(isDigit(data[ii])){var temp=parseInt(data[_i],10)^parseInt(data[ii],10);if(temp<10){data[_i]=temp.toString();}_i=ii;break;}}}}data=data.join("");var decodedURL=window.atob(data).slice(16,-16);if(window.stop){window.stop();}window.onbeforeunload=null;window.location.href=decodedURL;};var val;var applyHandler=true;var result=setPropertyAccess(window,"ysmm",{configurable:false,set:function set(value){if(applyHandler){applyHandler=false;try{if(typeof value==="string"){handler(value);}}catch(err){}}val=value;},get:function get(){return val;}});if(result){hit(source);}else {logMessage(source,"Failed to set up prevent-adfly scriptlet");}}function setPropertyAccess(object,property,descriptor){var currentDescriptor=Object.getOwnPropertyDescriptor(object,property);if(currentDescriptor&&!currentDescriptor.configurable){return false;}Object.defineProperty(object,property,descriptor);return true;}function hit(source){var ADGUARD_PREFIX="[AdGuard]";if(!source.verbose){return;}try{var trace=console.trace.bind(console);var label="".concat(ADGUARD_PREFIX," ");if(source.engine==="corelibs"){label+=source.ruleText;}else {if(source.domainName){label+="".concat(source.domainName);}if(source.args){label+="#%#//scriptlet('".concat(source.name,"', '").concat(source.args.join("', '"),"')");}else {label+="#%#//scriptlet('".concat(source.name,"')");}}if(trace){trace(label);}}catch(e){}if(typeof window.__debug==="function"){window.__debug(source);}}function logMessage(source,message){var forced=arguments.length>2&&arguments[2]!==undefined?arguments[2]:false;var convertMessageToString=arguments.length>3&&arguments[3]!==undefined?arguments[3]:true;var name=source.name,verbose=source.verbose;if(!forced&&!verbose){return;}var nativeConsole=console.log;if(!convertMessageToString){nativeConsole("".concat(name,":"),message);return;}nativeConsole("".concat(name,": ").concat(message));}var updatedArgs=args?[].concat(source).concat(args):[source];try{preventAdfly.apply(this,updatedArgs);if(source.uniqueId){Object.defineProperty(Window.prototype.toString,uniqueIdentifier,{value:flag,enumerable:false,writable:false,configurable:false});}}catch(e){console.log(e);}}function preventBab(source,args){var flag="done";var uniqueIdentifier=source.uniqueId+source.name+"_"+(Array.isArray(args)?args.join("_"):"");if(source.uniqueId){if(Window.prototype.toString[uniqueIdentifier]===flag){return;}}function preventBab(source){var nativeSetTimeout=window.setTimeout;var babRegex=/\.bab_elementid.$/;var timeoutWrapper=function timeoutWrapper(callback){if(typeof callback!=="string"||!babRegex.test(callback)){for(var _len=arguments.length,args=new Array(_len>1?_len-1:0),_key=1;_key<_len;_key++){args[_key-1]=arguments[_key];}return nativeSetTimeout.apply(window,[callback,...args]);}hit(source);};window.setTimeout=timeoutWrapper;var signatures=[["blockadblock"],["babasbm"],[/getItem\('babn'\)/],["getElementById","String.fromCharCode","ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789","charAt","DOMContentLoaded","AdBlock","addEventListener","doScroll","fromCharCode","<<2|r>>4","sessionStorage","clientWidth","localStorage","Math","random"]];var check=function check(str){if(typeof str!=="string"){return false;}for(var i=0;i<signatures.length;i+=1){var tokens=signatures[i];var match=0;for(var j=0;j<tokens.length;j+=1){var token=tokens[j];var found=token instanceof RegExp?token.test(str):str.includes(token);if(found){match+=1;}}if(match/tokens.length>=.8){return true;}}return false;};var nativeEval=window.eval;var evalWrapper=function evalWrapper(str){if(!check(str)){return nativeEval(str);}hit(source);var bodyEl=document.body;if(bodyEl){bodyEl.style.removeProperty("visibility");}var el=document.getElementById("babasbmsgx");if(el){el.parentNode.removeChild(el);}};window.eval=evalWrapper.bind(window);}function hit(source){var ADGUARD_PREFIX="[AdGuard]";if(!source.verbose){return;}try{var trace=console.trace.bind(console);var label="".concat(ADGUARD_PREFIX," ");if(source.engine==="corelibs"){label+=source.ruleText;}else {if(source.domainName){label+="".concat(source.domainName);}if(source.args){label+="#%#//scriptlet('".concat(source.name,"', '").concat(source.args.join("', '"),"')");}else {label+="#%#//scriptlet('".concat(source.name,"')");}}if(trace){trace(label);}}catch(e){}if(typeof window.__debug==="function"){window.__debug(source);}}var updatedArgs=args?[].concat(source).concat(args):[source];try{preventBab.apply(this,updatedArgs);if(source.uniqueId){Object.defineProperty(Window.prototype.toString,uniqueIdentifier,{value:flag,enumerable:false,writable:false,configurable:false});}}catch(e){console.log(e);}}function preventElementSrcLoading(source,args){var flag="done";var uniqueIdentifier=source.uniqueId+source.name+"_"+(Array.isArray(args)?args.join("_"):"");if(source.uniqueId){if(Window.prototype.toString[uniqueIdentifier]===flag){return;}}function preventElementSrcLoading(source,tagName,match){if(typeof Proxy==="undefined"||typeof Reflect==="undefined"){return;}var srcMockData={script:"data:text/javascript;base64,KCk9Pnt9",img:"data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==",iframe:"data:text/html;base64, PGRpdj48L2Rpdj4=",link:"data:text/plain;base64,"};var instance;if(tagName==="script"){instance=HTMLScriptElement;}else if(tagName==="img"){instance=HTMLImageElement;}else if(tagName==="iframe"){instance=HTMLIFrameElement;}else if(tagName==="link"){instance=HTMLLinkElement;}else {return;}var hasTrustedTypes=window.trustedTypes&&typeof window.trustedTypes.createPolicy==="function";var policy;if(hasTrustedTypes){policy=window.trustedTypes.createPolicy("AGPolicy",{createScriptURL:function createScriptURL(arg){return arg;}});}var SOURCE_PROPERTY_NAME=tagName==="link"?"href":"src";var ONERROR_PROPERTY_NAME="onerror";var searchRegexp=toRegExp(match);var setMatchedAttribute=function setMatchedAttribute(elem){return elem.setAttribute(source.name,"matched");};var setAttributeWrapper=function setAttributeWrapper(target,thisArg,args){if(!args[0]||!args[1]){return Reflect.apply(target,thisArg,args);}var nodeName=thisArg.nodeName.toLowerCase();var attrName=args[0].toLowerCase();var attrValue=args[1];var isMatched=attrName===SOURCE_PROPERTY_NAME&&tagName.toLowerCase()===nodeName&&srcMockData[nodeName]&&searchRegexp.test(attrValue);if(!isMatched){return Reflect.apply(target,thisArg,args);}hit(source);setMatchedAttribute(thisArg);return Reflect.apply(target,thisArg,[attrName,srcMockData[nodeName]]);};var setAttributeHandler={apply:setAttributeWrapper};instance.prototype.setAttribute=new Proxy(Element.prototype.setAttribute,setAttributeHandler);var origSrcDescriptor=safeGetDescriptor(instance.prototype,SOURCE_PROPERTY_NAME);if(!origSrcDescriptor){return;}Object.defineProperty(instance.prototype,SOURCE_PROPERTY_NAME,{enumerable:true,configurable:true,get(){return origSrcDescriptor.get.call(this);},set(urlValue){var nodeName=this.nodeName.toLowerCase();var isMatched=tagName.toLowerCase()===nodeName&&srcMockData[nodeName]&&searchRegexp.test(urlValue);if(!isMatched){origSrcDescriptor.set.call(this,urlValue);return true;}if(policy&&urlValue instanceof TrustedScriptURL){var trustedSrc=policy.createScriptURL(urlValue);origSrcDescriptor.set.call(this,trustedSrc);hit(source);return;}setMatchedAttribute(this);origSrcDescriptor.set.call(this,srcMockData[nodeName]);hit(source);}});var origOnerrorDescriptor=safeGetDescriptor(HTMLElement.prototype,ONERROR_PROPERTY_NAME);if(!origOnerrorDescriptor){return;}Object.defineProperty(HTMLElement.prototype,ONERROR_PROPERTY_NAME,{enumerable:true,configurable:true,get(){return origOnerrorDescriptor.get.call(this);},set(cb){var isMatched=this.getAttribute(source.name)==="matched";if(!isMatched){origOnerrorDescriptor.set.call(this,cb);return true;}origOnerrorDescriptor.set.call(this,noopFunc);return true;}});var addEventListenerWrapper=function addEventListenerWrapper(target,thisArg,args){if(!args[0]||!args[1]||!thisArg){return Reflect.apply(target,thisArg,args);}var eventName=args[0];var isMatched=typeof thisArg.getAttribute==="function"&&thisArg.getAttribute(source.name)==="matched"&&eventName==="error";if(isMatched){return Reflect.apply(target,thisArg,[eventName,noopFunc]);}return Reflect.apply(target,thisArg,args);};var addEventListenerHandler={apply:addEventListenerWrapper};EventTarget.prototype.addEventListener=new Proxy(EventTarget.prototype.addEventListener,addEventListenerHandler);var preventInlineOnerror=function preventInlineOnerror(tagName,src){window.addEventListener("error",function(event){if(!event.target||!event.target.nodeName||event.target.nodeName.toLowerCase()!==tagName||!event.target.src||!src.test(event.target.src)){return;}hit(source);if(typeof event.target.onload==="function"){event.target.onerror=event.target.onload;return;}event.target.onerror=noopFunc;},true);};preventInlineOnerror(tagName,searchRegexp);}function hit(source){var ADGUARD_PREFIX="[AdGuard]";if(!source.verbose){return;}try{var trace=console.trace.bind(console);var label="".concat(ADGUARD_PREFIX," ");if(source.engine==="corelibs"){label+=source.ruleText;}else {if(source.domainName){label+="".concat(source.domainName);}if(source.args){label+="#%#//scriptlet('".concat(source.name,"', '").concat(source.args.join("', '"),"')");}else {label+="#%#//scriptlet('".concat(source.name,"')");}}if(trace){trace(label);}}catch(e){}if(typeof window.__debug==="function"){window.__debug(source);}}function toRegExp(rawInput){var input=rawInput||"";var DEFAULT_VALUE=".?";var FORWARD_SLASH="/";if(input===""){return new RegExp(DEFAULT_VALUE);}var delimiterIndex=input.lastIndexOf(FORWARD_SLASH);var flagsPart=input.substring(delimiterIndex+1);var regExpPart=input.substring(0,delimiterIndex+1);var isValidRegExpFlag=function isValidRegExpFlag(flag){if(!flag){return false;}try{new RegExp("",flag);return true;}catch(ex){return false;}};var getRegExpFlags=function getRegExpFlags(regExpStr,flagsStr){if(regExpStr.startsWith(FORWARD_SLASH)&&regExpStr.endsWith(FORWARD_SLASH)&&!regExpStr.endsWith("\\/")&&isValidRegExpFlag(flagsStr)){return flagsStr;}return "";};var flags=getRegExpFlags(regExpPart,flagsPart);if(input.startsWith(FORWARD_SLASH)&&input.endsWith(FORWARD_SLASH)||flags){var regExpInput=flags?regExpPart:input;return new RegExp(regExpInput.slice(1,-1),flags);}var escaped=input.replace(/\\'/g,"'").replace(/\\"/g,'"').replace(/[.*+?^${}()|[\]\\]/g,"\\$&");return new RegExp(escaped);}function safeGetDescriptor(obj,prop){var descriptor=Object.getOwnPropertyDescriptor(obj,prop);if(descriptor&&descriptor.configurable){return descriptor;}return null;}function noopFunc(){}var updatedArgs=args?[].concat(source).concat(args):[source];try{preventElementSrcLoading.apply(this,updatedArgs);if(source.uniqueId){Object.defineProperty(Window.prototype.toString,uniqueIdentifier,{value:flag,enumerable:false,writable:false,configurable:false});}}catch(e){console.log(e);}}function preventEvalIf(source,args){var flag="done";var uniqueIdentifier=source.uniqueId+source.name+"_"+(Array.isArray(args)?args.join("_"):"");if(source.uniqueId){if(Window.prototype.toString[uniqueIdentifier]===flag){return;}}function preventEvalIf(source,search){var searchRegexp=toRegExp(search);var nativeEval=window.eval;window.eval=function(payload){if(!searchRegexp.test(payload.toString())){return nativeEval.call(window,payload);}hit(source);return undefined;}.bind(window);}function toRegExp(rawInput){var input=rawInput||"";var DEFAULT_VALUE=".?";var FORWARD_SLASH="/";if(input===""){return new RegExp(DEFAULT_VALUE);}var delimiterIndex=input.lastIndexOf(FORWARD_SLASH);var flagsPart=input.substring(delimiterIndex+1);var regExpPart=input.substring(0,delimiterIndex+1);var isValidRegExpFlag=function isValidRegExpFlag(flag){if(!flag){return false;}try{new RegExp("",flag);return true;}catch(ex){return false;}};var getRegExpFlags=function getRegExpFlags(regExpStr,flagsStr){if(regExpStr.startsWith(FORWARD_SLASH)&&regExpStr.endsWith(FORWARD_SLASH)&&!regExpStr.endsWith("\\/")&&isValidRegExpFlag(flagsStr)){return flagsStr;}return "";};var flags=getRegExpFlags(regExpPart,flagsPart);if(input.startsWith(FORWARD_SLASH)&&input.endsWith(FORWARD_SLASH)||flags){var regExpInput=flags?regExpPart:input;return new RegExp(regExpInput.slice(1,-1),flags);}var escaped=input.replace(/\\'/g,"'").replace(/\\"/g,'"').replace(/[.*+?^${}()|[\]\\]/g,"\\$&");return new RegExp(escaped);}function hit(source){var ADGUARD_PREFIX="[AdGuard]";if(!source.verbose){return;}try{var trace=console.trace.bind(console);var label="".concat(ADGUARD_PREFIX," ");if(source.engine==="corelibs"){label+=source.ruleText;}else {if(source.domainName){label+="".concat(source.domainName);}if(source.args){label+="#%#//scriptlet('".concat(source.name,"', '").concat(source.args.join("', '"),"')");}else {label+="#%#//scriptlet('".concat(source.name,"')");}}if(trace){trace(label);}}catch(e){}if(typeof window.__debug==="function"){window.__debug(source);}}var updatedArgs=args?[].concat(source).concat(args):[source];try{preventEvalIf.apply(this,updatedArgs);if(source.uniqueId){Object.defineProperty(Window.prototype.toString,uniqueIdentifier,{value:flag,enumerable:false,writable:false,configurable:false});}}catch(e){console.log(e);}}function preventFab(source,args){var flag="done";var uniqueIdentifier=source.uniqueId+source.name+"_"+(Array.isArray(args)?args.join("_"):"");if(source.uniqueId){if(Window.prototype.toString[uniqueIdentifier]===flag){return;}}function preventFab(source){hit(source);var Fab=function Fab(){};Fab.prototype.check=noopFunc;Fab.prototype.clearEvent=noopFunc;Fab.prototype.emitEvent=noopFunc;Fab.prototype.on=function(a,b){if(!a){b();}return this;};Fab.prototype.onDetected=noopThis;Fab.prototype.onNotDetected=function(a){a();return this;};Fab.prototype.setOption=noopFunc;Fab.prototype.options={set:noopFunc,get:noopFunc};var fab=new Fab();var getSetFab={get(){return Fab;},set(){}};var getsetfab={get(){return fab;},set(){}};if(Object.prototype.hasOwnProperty.call(window,"FuckAdBlock")){window.FuckAdBlock=Fab;}else {Object.defineProperty(window,"FuckAdBlock",getSetFab);}if(Object.prototype.hasOwnProperty.call(window,"BlockAdBlock")){window.BlockAdBlock=Fab;}else {Object.defineProperty(window,"BlockAdBlock",getSetFab);}if(Object.prototype.hasOwnProperty.call(window,"SniffAdBlock")){window.SniffAdBlock=Fab;}else {Object.defineProperty(window,"SniffAdBlock",getSetFab);}if(Object.prototype.hasOwnProperty.call(window,"fuckAdBlock")){window.fuckAdBlock=fab;}else {Object.defineProperty(window,"fuckAdBlock",getsetfab);}if(Object.prototype.hasOwnProperty.call(window,"blockAdBlock")){window.blockAdBlock=fab;}else {Object.defineProperty(window,"blockAdBlock",getsetfab);}if(Object.prototype.hasOwnProperty.call(window,"sniffAdBlock")){window.sniffAdBlock=fab;}else {Object.defineProperty(window,"sniffAdBlock",getsetfab);}}function hit(source){var ADGUARD_PREFIX="[AdGuard]";if(!source.verbose){return;}try{var trace=console.trace.bind(console);var label="".concat(ADGUARD_PREFIX," ");if(source.engine==="corelibs"){label+=source.ruleText;}else {if(source.domainName){label+="".concat(source.domainName);}if(source.args){label+="#%#//scriptlet('".concat(source.name,"', '").concat(source.args.join("', '"),"')");}else {label+="#%#//scriptlet('".concat(source.name,"')");}}if(trace){trace(label);}}catch(e){}if(typeof window.__debug==="function"){window.__debug(source);}}function noopFunc(){}function noopThis(){return this;}var updatedArgs=args?[].concat(source).concat(args):[source];try{preventFab.apply(this,updatedArgs);if(source.uniqueId){Object.defineProperty(Window.prototype.toString,uniqueIdentifier,{value:flag,enumerable:false,writable:false,configurable:false});}}catch(e){console.log(e);}}function preventFetch(source,args){var flag="done";var uniqueIdentifier=source.uniqueId+source.name+"_"+(Array.isArray(args)?args.join("_"):"");if(source.uniqueId){if(Window.prototype.toString[uniqueIdentifier]===flag){return;}}function preventFetch(source,propsToMatch){var responseBody=arguments.length>2&&arguments[2]!==undefined?arguments[2]:"emptyObj";var responseType=arguments.length>3?arguments[3]:undefined;if(typeof fetch==="undefined"||typeof Proxy==="undefined"||typeof Response==="undefined"){return;}var nativeRequestClone=Request.prototype.clone;var strResponseBody;if(responseBody===""||responseBody==="emptyObj"){strResponseBody="{}";}else if(responseBody==="emptyArr"){strResponseBody="[]";}else if(responseBody==="emptyStr"){strResponseBody="";}else {logMessage(source,"Invalid responseBody parameter: '".concat(responseBody,"'"));return;}var isResponseTypeSpecified=typeof responseType!=="undefined";var isResponseTypeSupported=function isResponseTypeSupported(responseType){var SUPPORTED_TYPES=["basic","cors","opaque"];return SUPPORTED_TYPES.includes(responseType);};if(isResponseTypeSpecified&&!isResponseTypeSupported(responseType)){logMessage(source,"Invalid responseType parameter: '".concat(responseType,"'"));return;}var getResponseType=function getResponseType(request){try{var mode=request.mode;if(mode===undefined||mode==="cors"||mode==="no-cors"){var fetchURL=new URL(request.url);if(fetchURL.origin===document.location.origin){return "basic";}return mode==="no-cors"?"opaque":"cors";}}catch(error){logMessage(source,"Could not determine response type: ".concat(error));}return undefined;};var handlerWrapper=async function handlerWrapper(target,thisArg,args){var shouldPrevent=false;var fetchData=getFetchData(args,nativeRequestClone);if(typeof propsToMatch==="undefined"){logMessage(source,"fetch( ".concat(objectToString(fetchData)," )"),true);hit(source);return Reflect.apply(target,thisArg,args);}shouldPrevent=matchRequestProps(source,propsToMatch,fetchData);if(shouldPrevent){hit(source);var finalResponseType;try{finalResponseType=responseType||getResponseType(fetchData);var origResponse=await Reflect.apply(target,thisArg,args);if(!origResponse.ok){return noopPromiseResolve(strResponseBody,fetchData.url,finalResponseType);}return modifyResponse(origResponse,{body:strResponseBody,type:finalResponseType});}catch(ex){return noopPromiseResolve(strResponseBody,fetchData.url,finalResponseType);}}return Reflect.apply(target,thisArg,args);};var fetchHandler={apply:handlerWrapper};fetch=new Proxy(fetch,fetchHandler);}function hit(source){var ADGUARD_PREFIX="[AdGuard]";if(!source.verbose){return;}try{var trace=console.trace.bind(console);var label="".concat(ADGUARD_PREFIX," ");if(source.engine==="corelibs"){label+=source.ruleText;}else {if(source.domainName){label+="".concat(source.domainName);}if(source.args){label+="#%#//scriptlet('".concat(source.name,"', '").concat(source.args.join("', '"),"')");}else {label+="#%#//scriptlet('".concat(source.name,"')");}}if(trace){trace(label);}}catch(e){}if(typeof window.__debug==="function"){window.__debug(source);}}function getFetchData(args,nativeRequestClone){var fetchPropsObj={};var resource=args[0];var fetchUrl;var fetchInit;if(resource instanceof Request){var realData=nativeRequestClone.call(resource);var requestData=getRequestData(realData);fetchUrl=requestData.url;fetchInit=requestData;}else {fetchUrl=resource;fetchInit=args[1];}fetchPropsObj.url=fetchUrl;if(fetchInit instanceof Object){var props=Object.keys(fetchInit);props.forEach(function(prop){fetchPropsObj[prop]=fetchInit[prop];});}return fetchPropsObj;}function objectToString(obj){if(!obj||typeof obj!=="object"){return String(obj);}if(isEmptyObject(obj)){return "{}";}return Object.entries(obj).map(function(pair){var key=pair[0];var value=pair[1];var recordValueStr=value;if(value instanceof Object){recordValueStr="{ ".concat(objectToString(value)," }");}return "".concat(key,':"').concat(recordValueStr,'"');}).join(" ");}function matchRequestProps(source,propsToMatch,requestData){if(propsToMatch===""||propsToMatch==="*"){return true;}var isMatched;var parsedData=parseMatchProps(propsToMatch);if(!isValidParsedData(parsedData)){logMessage(source,"Invalid parameter: ".concat(propsToMatch));isMatched=false;}else {var matchData=getMatchPropsData(parsedData);var matchKeys=Object.keys(matchData);isMatched=matchKeys.every(function(matchKey){var matchValue=matchData[matchKey];var dataValue=requestData[matchKey];return Object.prototype.hasOwnProperty.call(requestData,matchKey)&&typeof dataValue==="string"&&(matchValue===null||matchValue===void 0?void 0:matchValue.test(dataValue));});}return isMatched;}function logMessage(source,message){var forced=arguments.length>2&&arguments[2]!==undefined?arguments[2]:false;var convertMessageToString=arguments.length>3&&arguments[3]!==undefined?arguments[3]:true;var name=source.name,verbose=source.verbose;if(!forced&&!verbose){return;}var nativeConsole=console.log;if(!convertMessageToString){nativeConsole("".concat(name,":"),message);return;}nativeConsole("".concat(name,": ").concat(message));}function noopPromiseResolve(){var responseBody=arguments.length>0&&arguments[0]!==undefined?arguments[0]:"{}";var responseUrl=arguments.length>1&&arguments[1]!==undefined?arguments[1]:"";var responseType=arguments.length>2&&arguments[2]!==undefined?arguments[2]:"basic";if(typeof Response==="undefined"){return;}var response=new Response(responseBody,{status:200,statusText:"OK"});if(responseType==="opaque"){Object.defineProperties(response,{body:{value:null},status:{value:0},statusText:{value:""},url:{value:""},type:{value:responseType}});}else {Object.defineProperties(response,{url:{value:responseUrl},type:{value:responseType}});}return Promise.resolve(response);}function modifyResponse(origResponse){var _origResponse$headers;var replacement=arguments.length>1&&arguments[1]!==undefined?arguments[1]:{body:"{}"};var headers={};origResponse===null||origResponse===void 0?void 0:(_origResponse$headers=origResponse.headers)===null||_origResponse$headers===void 0?void 0:_origResponse$headers.forEach(function(value,key){headers[key]=value;});var modifiedResponse=new Response(replacement.body,{status:origResponse.status,statusText:origResponse.statusText,headers:headers});Object.defineProperties(modifiedResponse,{url:{value:origResponse.url},type:{value:replacement.type||origResponse.type}});return modifiedResponse;}function toRegExp(rawInput){var input=rawInput||"";var DEFAULT_VALUE=".?";var FORWARD_SLASH="/";if(input===""){return new RegExp(DEFAULT_VALUE);}var delimiterIndex=input.lastIndexOf(FORWARD_SLASH);var flagsPart=input.substring(delimiterIndex+1);var regExpPart=input.substring(0,delimiterIndex+1);var isValidRegExpFlag=function isValidRegExpFlag(flag){if(!flag){return false;}try{new RegExp("",flag);return true;}catch(ex){return false;}};var getRegExpFlags=function getRegExpFlags(regExpStr,flagsStr){if(regExpStr.startsWith(FORWARD_SLASH)&&regExpStr.endsWith(FORWARD_SLASH)&&!regExpStr.endsWith("\\/")&&isValidRegExpFlag(flagsStr)){return flagsStr;}return "";};var flags=getRegExpFlags(regExpPart,flagsPart);if(input.startsWith(FORWARD_SLASH)&&input.endsWith(FORWARD_SLASH)||flags){var regExpInput=flags?regExpPart:input;return new RegExp(regExpInput.slice(1,-1),flags);}var escaped=input.replace(/\\'/g,"'").replace(/\\"/g,'"').replace(/[.*+?^${}()|[\]\\]/g,"\\$&");return new RegExp(escaped);}function isValidStrPattern(input){var FORWARD_SLASH="/";var str=escapeRegExp(input);if(input[0]===FORWARD_SLASH&&input[input.length-1]===FORWARD_SLASH){str=input.slice(1,-1);}var isValid;try{isValid=new RegExp(str);isValid=true;}catch(e){isValid=false;}return isValid;}function escapeRegExp(str){return str.replace(/[.*+?^${}()|[\]\\]/g,"\\$&");}function isEmptyObject(obj){return Object.keys(obj).length===0&&!obj.prototype;}function getRequestData(request){var requestInitOptions=getRequestProps();var entries=requestInitOptions.map(function(key){var value=request[key];return [key,value];});return Object.fromEntries(entries);}function getRequestProps(){return ["url","method","headers","body","credentials","cache","redirect","referrer","referrerPolicy","integrity","keepalive","signal","mode"];}function parseMatchProps(propsToMatchStr){var PROPS_DIVIDER=" ";var PAIRS_MARKER=":";var isRequestProp=function isRequestProp(prop){return getRequestProps().includes(prop);};var propsObj={};var props=propsToMatchStr.split(PROPS_DIVIDER);props.forEach(function(prop){var dividerInd=prop.indexOf(PAIRS_MARKER);var key=prop.slice(0,dividerInd);if(isRequestProp(key)){var value=prop.slice(dividerInd+1);propsObj[key]=value;}else {propsObj.url=prop;}});return propsObj;}function isValidParsedData(data){return Object.values(data).every(function(value){return isValidStrPattern(value);});}function getMatchPropsData(data){var matchData={};var dataKeys=Object.keys(data);dataKeys.forEach(function(key){matchData[key]=toRegExp(data[key]);});return matchData;}var updatedArgs=args?[].concat(source).concat(args):[source];try{preventFetch.apply(this,updatedArgs);if(source.uniqueId){Object.defineProperty(Window.prototype.toString,uniqueIdentifier,{value:flag,enumerable:false,writable:false,configurable:false});}}catch(e){console.log(e);}}function preventPopadsNet(source,args){var flag="done";var uniqueIdentifier=source.uniqueId+source.name+"_"+(Array.isArray(args)?args.join("_"):"");if(source.uniqueId){if(Window.prototype.toString[uniqueIdentifier]===flag){return;}}function preventPopadsNet(source){var rid=randomId();var throwError=function throwError(){throw new ReferenceError(rid);};delete window.PopAds;delete window.popns;Object.defineProperties(window,{PopAds:{set:throwError},popns:{set:throwError}});window.onerror=createOnErrorHandler(rid).bind();hit(source);}function createOnErrorHandler(rid){var nativeOnError=window.onerror;return function onError(error){if(typeof error==="string"&&error.includes(rid)){return true;}if(nativeOnError instanceof Function){for(var _len=arguments.length,args=new Array(_len>1?_len-1:0),_key=1;_key<_len;_key++){args[_key-1]=arguments[_key];}return nativeOnError.apply(window,[error,...args]);}return false;};}function randomId(){return Math.random().toString(36).slice(2,9);}function hit(source){var ADGUARD_PREFIX="[AdGuard]";if(!source.verbose){return;}try{var trace=console.trace.bind(console);var label="".concat(ADGUARD_PREFIX," ");if(source.engine==="corelibs"){label+=source.ruleText;}else {if(source.domainName){label+="".concat(source.domainName);}if(source.args){label+="#%#//scriptlet('".concat(source.name,"', '").concat(source.args.join("', '"),"')");}else {label+="#%#//scriptlet('".concat(source.name,"')");}}if(trace){trace(label);}}catch(e){}if(typeof window.__debug==="function"){window.__debug(source);}}var updatedArgs=args?[].concat(source).concat(args):[source];try{preventPopadsNet.apply(this,updatedArgs);if(source.uniqueId){Object.defineProperty(Window.prototype.toString,uniqueIdentifier,{value:flag,enumerable:false,writable:false,configurable:false});}}catch(e){console.log(e);}}function preventRefresh(source,args){var flag="done";var uniqueIdentifier=source.uniqueId+source.name+"_"+(Array.isArray(args)?args.join("_"):"");if(source.uniqueId){if(Window.prototype.toString[uniqueIdentifier]===flag){return;}}function preventRefresh(source,delaySec){var getMetaElements=function getMetaElements(){var metaNodes=[];try{metaNodes=document.querySelectorAll('meta[http-equiv="refresh" i][content]');}catch(e){try{metaNodes=document.querySelectorAll('meta[http-equiv="refresh"][content]');}catch(e){logMessage(source,e);}}return Array.from(metaNodes);};var getMetaContentDelay=function getMetaContentDelay(metaElements){var delays=metaElements.map(function(meta){var contentString=meta.getAttribute("content");if(contentString.length===0){return null;}var contentDelay;var limiterIndex=contentString.indexOf(";");if(limiterIndex!==-1){var delaySubstring=contentString.substring(0,limiterIndex);contentDelay=getNumberFromString(delaySubstring);}else {contentDelay=getNumberFromString(contentString);}return contentDelay;}).filter(function(delay){return delay!==null;});if(!delays.length){return null;}var minDelay=delays.reduce(function(a,b){return Math.min(a,b);});return minDelay;};var stop=function stop(){var metaElements=getMetaElements();if(metaElements.length===0){return;}var secondsToRun=getNumberFromString(delaySec);if(secondsToRun===null){secondsToRun=getMetaContentDelay(metaElements);}if(secondsToRun===null){return;}var delayMs=secondsToRun*1e3;setTimeout(function(){window.stop();hit(source);},delayMs);};if(document.readyState==="loading"){document.addEventListener("DOMContentLoaded",stop,{once:true});}else {stop();}}function hit(source){var ADGUARD_PREFIX="[AdGuard]";if(!source.verbose){return;}try{var trace=console.trace.bind(console);var label="".concat(ADGUARD_PREFIX," ");if(source.engine==="corelibs"){label+=source.ruleText;}else {if(source.domainName){label+="".concat(source.domainName);}if(source.args){label+="#%#//scriptlet('".concat(source.name,"', '").concat(source.args.join("', '"),"')");}else {label+="#%#//scriptlet('".concat(source.name,"')");}}if(trace){trace(label);}}catch(e){}if(typeof window.__debug==="function"){window.__debug(source);}}function getNumberFromString(rawString){var parsedDelay=parseInt(rawString,10);var validDelay=nativeIsNaN(parsedDelay)?null:parsedDelay;return validDelay;}function logMessage(source,message){var forced=arguments.length>2&&arguments[2]!==undefined?arguments[2]:false;var convertMessageToString=arguments.length>3&&arguments[3]!==undefined?arguments[3]:true;var name=source.name,verbose=source.verbose;if(!forced&&!verbose){return;}var nativeConsole=console.log;if(!convertMessageToString){nativeConsole("".concat(name,":"),message);return;}nativeConsole("".concat(name,": ").concat(message));}function nativeIsNaN(num){var native=Number.isNaN||window.isNaN;return native(num);}var updatedArgs=args?[].concat(source).concat(args):[source];try{preventRefresh.apply(this,updatedArgs);if(source.uniqueId){Object.defineProperty(Window.prototype.toString,uniqueIdentifier,{value:flag,enumerable:false,writable:false,configurable:false});}}catch(e){console.log(e);}}function preventRequestAnimationFrame(source,args){var flag="done";var uniqueIdentifier=source.uniqueId+source.name+"_"+(Array.isArray(args)?args.join("_"):"");if(source.uniqueId){if(Window.prototype.toString[uniqueIdentifier]===flag){return;}}function preventRequestAnimationFrame(source,match){var nativeRequestAnimationFrame=window.requestAnimationFrame;var shouldLog=typeof match==="undefined";var _parseMatchArg=parseMatchArg(match),isInvertedMatch=_parseMatchArg.isInvertedMatch,matchRegexp=_parseMatchArg.matchRegexp;var rafWrapper=function rafWrapper(callback){var shouldPrevent=false;if(shouldLog){hit(source);logMessage(source,"requestAnimationFrame(".concat(String(callback),")"),true);}else if(isValidCallback(callback)&&isValidStrPattern(match)){shouldPrevent=matchRegexp.test(callback.toString())!==isInvertedMatch;}if(shouldPrevent){hit(source);return nativeRequestAnimationFrame(noopFunc);}for(var _len=arguments.length,args=new Array(_len>1?_len-1:0),_key=1;_key<_len;_key++){args[_key-1]=arguments[_key];}return nativeRequestAnimationFrame.apply(window,[callback,...args]);};window.requestAnimationFrame=rafWrapper;}function hit(source){var ADGUARD_PREFIX="[AdGuard]";if(!source.verbose){return;}try{var trace=console.trace.bind(console);var label="".concat(ADGUARD_PREFIX," ");if(source.engine==="corelibs"){label+=source.ruleText;}else {if(source.domainName){label+="".concat(source.domainName);}if(source.args){label+="#%#//scriptlet('".concat(source.name,"', '").concat(source.args.join("', '"),"')");}else {label+="#%#//scriptlet('".concat(source.name,"')");}}if(trace){trace(label);}}catch(e){}if(typeof window.__debug==="function"){window.__debug(source);}}function noopFunc(){}function parseMatchArg(match){var INVERT_MARKER="!";var isInvertedMatch=match?match===null||match===void 0?void 0:match.startsWith(INVERT_MARKER):false;var matchValue=isInvertedMatch?match.slice(1):match;var matchRegexp=toRegExp(matchValue);return {isInvertedMatch:isInvertedMatch,matchRegexp:matchRegexp,matchValue:matchValue};}function isValidStrPattern(input){var FORWARD_SLASH="/";var str=escapeRegExp(input);if(input[0]===FORWARD_SLASH&&input[input.length-1]===FORWARD_SLASH){str=input.slice(1,-1);}var isValid;try{isValid=new RegExp(str);isValid=true;}catch(e){isValid=false;}return isValid;}function isValidCallback(callback){return callback instanceof Function||typeof callback==="string";}function logMessage(source,message){var forced=arguments.length>2&&arguments[2]!==undefined?arguments[2]:false;var convertMessageToString=arguments.length>3&&arguments[3]!==undefined?arguments[3]:true;var name=source.name,verbose=source.verbose;if(!forced&&!verbose){return;}var nativeConsole=console.log;if(!convertMessageToString){nativeConsole("".concat(name,":"),message);return;}nativeConsole("".concat(name,": ").concat(message));}function escapeRegExp(str){return str.replace(/[.*+?^${}()|[\]\\]/g,"\\$&");}function toRegExp(rawInput){var input=rawInput||"";var DEFAULT_VALUE=".?";var FORWARD_SLASH="/";if(input===""){return new RegExp(DEFAULT_VALUE);}var delimiterIndex=input.lastIndexOf(FORWARD_SLASH);var flagsPart=input.substring(delimiterIndex+1);var regExpPart=input.substring(0,delimiterIndex+1);var isValidRegExpFlag=function isValidRegExpFlag(flag){if(!flag){return false;}try{new RegExp("",flag);return true;}catch(ex){return false;}};var getRegExpFlags=function getRegExpFlags(regExpStr,flagsStr){if(regExpStr.startsWith(FORWARD_SLASH)&&regExpStr.endsWith(FORWARD_SLASH)&&!regExpStr.endsWith("\\/")&&isValidRegExpFlag(flagsStr)){return flagsStr;}return "";};var flags=getRegExpFlags(regExpPart,flagsPart);if(input.startsWith(FORWARD_SLASH)&&input.endsWith(FORWARD_SLASH)||flags){var regExpInput=flags?regExpPart:input;return new RegExp(regExpInput.slice(1,-1),flags);}var escaped=input.replace(/\\'/g,"'").replace(/\\"/g,'"').replace(/[.*+?^${}()|[\]\\]/g,"\\$&");return new RegExp(escaped);}var updatedArgs=args?[].concat(source).concat(args):[source];try{preventRequestAnimationFrame.apply(this,updatedArgs);if(source.uniqueId){Object.defineProperty(Window.prototype.toString,uniqueIdentifier,{value:flag,enumerable:false,writable:false,configurable:false});}}catch(e){console.log(e);}}function preventSetInterval(source,args){var flag="done";var uniqueIdentifier=source.uniqueId+source.name+"_"+(Array.isArray(args)?args.join("_"):"");if(source.uniqueId){if(Window.prototype.toString[uniqueIdentifier]===flag){return;}}function preventSetInterval(source,matchCallback,matchDelay){var shouldLog=typeof matchCallback==="undefined"&&typeof matchDelay==="undefined";var handlerWrapper=function handlerWrapper(target,thisArg,args){var callback=args[0];var delay=args[1];var shouldPrevent=false;if(shouldLog){hit(source);logMessage(source,"setInterval(".concat(String(callback),", ").concat(delay,")"),true);}else {shouldPrevent=isPreventionNeeded({callback:callback,delay:delay,matchCallback:matchCallback,matchDelay:matchDelay});}if(shouldPrevent){hit(source);args[0]=noopFunc;}return target.apply(thisArg,args);};var setIntervalHandler={apply:handlerWrapper};window.setInterval=new Proxy(window.setInterval,setIntervalHandler);}function hit(source){var ADGUARD_PREFIX="[AdGuard]";if(!source.verbose){return;}try{var trace=console.trace.bind(console);var label="".concat(ADGUARD_PREFIX," ");if(source.engine==="corelibs"){label+=source.ruleText;}else {if(source.domainName){label+="".concat(source.domainName);}if(source.args){label+="#%#//scriptlet('".concat(source.name,"', '").concat(source.args.join("', '"),"')");}else {label+="#%#//scriptlet('".concat(source.name,"')");}}if(trace){trace(label);}}catch(e){}if(typeof window.__debug==="function"){window.__debug(source);}}function noopFunc(){}function isPreventionNeeded(_ref){var callback=_ref.callback,delay=_ref.delay,matchCallback=_ref.matchCallback,matchDelay=_ref.matchDelay;if(!isValidCallback(callback)){return false;}if(!isValidMatchStr(matchCallback)||matchDelay&&!isValidMatchNumber(matchDelay)){return false;}var _parseMatchArg=parseMatchArg(matchCallback),isInvertedMatch=_parseMatchArg.isInvertedMatch,matchRegexp=_parseMatchArg.matchRegexp;var _parseDelayArg=parseDelayArg(matchDelay),isInvertedDelayMatch=_parseDelayArg.isInvertedDelayMatch,delayMatch=_parseDelayArg.delayMatch;var parsedDelay=parseRawDelay(delay);var shouldPrevent=false;var callbackStr=String(callback);if(delayMatch===null){shouldPrevent=matchRegexp.test(callbackStr)!==isInvertedMatch;}else if(!matchCallback){shouldPrevent=parsedDelay===delayMatch!==isInvertedDelayMatch;}else {shouldPrevent=matchRegexp.test(callbackStr)!==isInvertedMatch&&parsedDelay===delayMatch!==isInvertedDelayMatch;}return shouldPrevent;}function logMessage(source,message){var forced=arguments.length>2&&arguments[2]!==undefined?arguments[2]:false;var convertMessageToString=arguments.length>3&&arguments[3]!==undefined?arguments[3]:true;var name=source.name,verbose=source.verbose;if(!forced&&!verbose){return;}var nativeConsole=console.log;if(!convertMessageToString){nativeConsole("".concat(name,":"),message);return;}nativeConsole("".concat(name,": ").concat(message));}function toRegExp(rawInput){var input=rawInput||"";var DEFAULT_VALUE=".?";var FORWARD_SLASH="/";if(input===""){return new RegExp(DEFAULT_VALUE);}var delimiterIndex=input.lastIndexOf(FORWARD_SLASH);var flagsPart=input.substring(delimiterIndex+1);var regExpPart=input.substring(0,delimiterIndex+1);var isValidRegExpFlag=function isValidRegExpFlag(flag){if(!flag){return false;}try{new RegExp("",flag);return true;}catch(ex){return false;}};var getRegExpFlags=function getRegExpFlags(regExpStr,flagsStr){if(regExpStr.startsWith(FORWARD_SLASH)&&regExpStr.endsWith(FORWARD_SLASH)&&!regExpStr.endsWith("\\/")&&isValidRegExpFlag(flagsStr)){return flagsStr;}return "";};var flags=getRegExpFlags(regExpPart,flagsPart);if(input.startsWith(FORWARD_SLASH)&&input.endsWith(FORWARD_SLASH)||flags){var regExpInput=flags?regExpPart:input;return new RegExp(regExpInput.slice(1,-1),flags);}var escaped=input.replace(/\\'/g,"'").replace(/\\"/g,'"').replace(/[.*+?^${}()|[\]\\]/g,"\\$&");return new RegExp(escaped);}function nativeIsNaN(num){var native=Number.isNaN||window.isNaN;return native(num);}function parseMatchArg(match){var INVERT_MARKER="!";var isInvertedMatch=match?match===null||match===void 0?void 0:match.startsWith(INVERT_MARKER):false;var matchValue=isInvertedMatch?match.slice(1):match;var matchRegexp=toRegExp(matchValue);return {isInvertedMatch:isInvertedMatch,matchRegexp:matchRegexp,matchValue:matchValue};}function parseDelayArg(delay){var INVERT_MARKER="!";var isInvertedDelayMatch=delay===null||delay===void 0?void 0:delay.startsWith(INVERT_MARKER);var delayValue=isInvertedDelayMatch?delay.slice(1):delay;var parsedDelay=parseInt(delayValue,10);var delayMatch=nativeIsNaN(parsedDelay)?null:parsedDelay;return {isInvertedDelayMatch:isInvertedDelayMatch,delayMatch:delayMatch};}function isValidCallback(callback){return callback instanceof Function||typeof callback==="string";}function isValidMatchStr(match){var INVERT_MARKER="!";var str=match;if(match!==null&&match!==void 0&&match.startsWith(INVERT_MARKER)){str=match.slice(1);}return isValidStrPattern(str);}function isValidStrPattern(input){var FORWARD_SLASH="/";var str=escapeRegExp(input);if(input[0]===FORWARD_SLASH&&input[input.length-1]===FORWARD_SLASH){str=input.slice(1,-1);}var isValid;try{isValid=new RegExp(str);isValid=true;}catch(e){isValid=false;}return isValid;}function escapeRegExp(str){return str.replace(/[.*+?^${}()|[\]\\]/g,"\\$&");}function nativeIsFinite(num){var native=Number.isFinite||window.isFinite;return native(num);}function isValidMatchNumber(match){var INVERT_MARKER="!";var str=match;if(match!==null&&match!==void 0&&match.startsWith(INVERT_MARKER)){str=match.slice(1);}var num=parseFloat(str);return !nativeIsNaN(num)&&nativeIsFinite(num);}function parseRawDelay(delay){var parsedDelay=Math.floor(parseInt(delay,10));return typeof parsedDelay==="number"&&!nativeIsNaN(parsedDelay)?parsedDelay:delay;}var updatedArgs=args?[].concat(source).concat(args):[source];try{preventSetInterval.apply(this,updatedArgs);if(source.uniqueId){Object.defineProperty(Window.prototype.toString,uniqueIdentifier,{value:flag,enumerable:false,writable:false,configurable:false});}}catch(e){console.log(e);}}function preventSetTimeout(source,args){var flag="done";var uniqueIdentifier=source.uniqueId+source.name+"_"+(Array.isArray(args)?args.join("_"):"");if(source.uniqueId){if(Window.prototype.toString[uniqueIdentifier]===flag){return;}}function preventSetTimeout(source,matchCallback,matchDelay){var shouldLog=typeof matchCallback==="undefined"&&typeof matchDelay==="undefined";var handlerWrapper=function handlerWrapper(target,thisArg,args){var callback=args[0];var delay=args[1];var shouldPrevent=false;if(shouldLog){hit(source);logMessage(source,"setTimeout(".concat(String(callback),", ").concat(delay,")"),true);}else {shouldPrevent=isPreventionNeeded({callback:callback,delay:delay,matchCallback:matchCallback,matchDelay:matchDelay});}if(shouldPrevent){hit(source);args[0]=noopFunc;}return target.apply(thisArg,args);};var setTimeoutHandler={apply:handlerWrapper};window.setTimeout=new Proxy(window.setTimeout,setTimeoutHandler);}function hit(source){var ADGUARD_PREFIX="[AdGuard]";if(!source.verbose){return;}try{var trace=console.trace.bind(console);var label="".concat(ADGUARD_PREFIX," ");if(source.engine==="corelibs"){label+=source.ruleText;}else {if(source.domainName){label+="".concat(source.domainName);}if(source.args){label+="#%#//scriptlet('".concat(source.name,"', '").concat(source.args.join("', '"),"')");}else {label+="#%#//scriptlet('".concat(source.name,"')");}}if(trace){trace(label);}}catch(e){}if(typeof window.__debug==="function"){window.__debug(source);}}function noopFunc(){}function isPreventionNeeded(_ref){var callback=_ref.callback,delay=_ref.delay,matchCallback=_ref.matchCallback,matchDelay=_ref.matchDelay;if(!isValidCallback(callback)){return false;}if(!isValidMatchStr(matchCallback)||matchDelay&&!isValidMatchNumber(matchDelay)){return false;}var _parseMatchArg=parseMatchArg(matchCallback),isInvertedMatch=_parseMatchArg.isInvertedMatch,matchRegexp=_parseMatchArg.matchRegexp;var _parseDelayArg=parseDelayArg(matchDelay),isInvertedDelayMatch=_parseDelayArg.isInvertedDelayMatch,delayMatch=_parseDelayArg.delayMatch;var parsedDelay=parseRawDelay(delay);var shouldPrevent=false;var callbackStr=String(callback);if(delayMatch===null){shouldPrevent=matchRegexp.test(callbackStr)!==isInvertedMatch;}else if(!matchCallback){shouldPrevent=parsedDelay===delayMatch!==isInvertedDelayMatch;}else {shouldPrevent=matchRegexp.test(callbackStr)!==isInvertedMatch&&parsedDelay===delayMatch!==isInvertedDelayMatch;}return shouldPrevent;}function logMessage(source,message){var forced=arguments.length>2&&arguments[2]!==undefined?arguments[2]:false;var convertMessageToString=arguments.length>3&&arguments[3]!==undefined?arguments[3]:true;var name=source.name,verbose=source.verbose;if(!forced&&!verbose){return;}var nativeConsole=console.log;if(!convertMessageToString){nativeConsole("".concat(name,":"),message);return;}nativeConsole("".concat(name,": ").concat(message));}function parseMatchArg(match){var INVERT_MARKER="!";var isInvertedMatch=match?match===null||match===void 0?void 0:match.startsWith(INVERT_MARKER):false;var matchValue=isInvertedMatch?match.slice(1):match;var matchRegexp=toRegExp(matchValue);return {isInvertedMatch:isInvertedMatch,matchRegexp:matchRegexp,matchValue:matchValue};}function parseDelayArg(delay){var INVERT_MARKER="!";var isInvertedDelayMatch=delay===null||delay===void 0?void 0:delay.startsWith(INVERT_MARKER);var delayValue=isInvertedDelayMatch?delay.slice(1):delay;var parsedDelay=parseInt(delayValue,10);var delayMatch=nativeIsNaN(parsedDelay)?null:parsedDelay;return {isInvertedDelayMatch:isInvertedDelayMatch,delayMatch:delayMatch};}function toRegExp(rawInput){var input=rawInput||"";var DEFAULT_VALUE=".?";var FORWARD_SLASH="/";if(input===""){return new RegExp(DEFAULT_VALUE);}var delimiterIndex=input.lastIndexOf(FORWARD_SLASH);var flagsPart=input.substring(delimiterIndex+1);var regExpPart=input.substring(0,delimiterIndex+1);var isValidRegExpFlag=function isValidRegExpFlag(flag){if(!flag){return false;}try{new RegExp("",flag);return true;}catch(ex){return false;}};var getRegExpFlags=function getRegExpFlags(regExpStr,flagsStr){if(regExpStr.startsWith(FORWARD_SLASH)&&regExpStr.endsWith(FORWARD_SLASH)&&!regExpStr.endsWith("\\/")&&isValidRegExpFlag(flagsStr)){return flagsStr;}return "";};var flags=getRegExpFlags(regExpPart,flagsPart);if(input.startsWith(FORWARD_SLASH)&&input.endsWith(FORWARD_SLASH)||flags){var regExpInput=flags?regExpPart:input;return new RegExp(regExpInput.slice(1,-1),flags);}var escaped=input.replace(/\\'/g,"'").replace(/\\"/g,'"').replace(/[.*+?^${}()|[\]\\]/g,"\\$&");return new RegExp(escaped);}function nativeIsNaN(num){var native=Number.isNaN||window.isNaN;return native(num);}function isValidCallback(callback){return callback instanceof Function||typeof callback==="string";}function isValidMatchStr(match){var INVERT_MARKER="!";var str=match;if(match!==null&&match!==void 0&&match.startsWith(INVERT_MARKER)){str=match.slice(1);}return isValidStrPattern(str);}function escapeRegExp(str){return str.replace(/[.*+?^${}()|[\]\\]/g,"\\$&");}function isValidStrPattern(input){var FORWARD_SLASH="/";var str=escapeRegExp(input);if(input[0]===FORWARD_SLASH&&input[input.length-1]===FORWARD_SLASH){str=input.slice(1,-1);}var isValid;try{isValid=new RegExp(str);isValid=true;}catch(e){isValid=false;}return isValid;}function nativeIsFinite(num){var native=Number.isFinite||window.isFinite;return native(num);}function isValidMatchNumber(match){var INVERT_MARKER="!";var str=match;if(match!==null&&match!==void 0&&match.startsWith(INVERT_MARKER)){str=match.slice(1);}var num=parseFloat(str);return !nativeIsNaN(num)&&nativeIsFinite(num);}function parseRawDelay(delay){var parsedDelay=Math.floor(parseInt(delay,10));return typeof parsedDelay==="number"&&!nativeIsNaN(parsedDelay)?parsedDelay:delay;}var updatedArgs=args?[].concat(source).concat(args):[source];try{preventSetTimeout.apply(this,updatedArgs);if(source.uniqueId){Object.defineProperty(Window.prototype.toString,uniqueIdentifier,{value:flag,enumerable:false,writable:false,configurable:false});}}catch(e){console.log(e);}}function preventWindowOpen(source,args){var flag="done";var uniqueIdentifier=source.uniqueId+source.name+"_"+(Array.isArray(args)?args.join("_"):"");if(source.uniqueId){if(Window.prototype.toString[uniqueIdentifier]===flag){return;}}function preventWindowOpen(source){var match=arguments.length>1&&arguments[1]!==undefined?arguments[1]:"*";var delay=arguments.length>2?arguments[2]:undefined;var replacement=arguments.length>3?arguments[3]:undefined;var nativeOpen=window.open;var isNewSyntax=match!=="0"&&match!=="1";var oldOpenWrapper=function oldOpenWrapper(str){match=Number(match)>0;for(var _len=arguments.length,args=new Array(_len>1?_len-1:0),_key=1;_key<_len;_key++){args[_key-1]=arguments[_key];}if(!isValidStrPattern(delay)){logMessage(source,"Invalid parameter: ".concat(delay));return nativeOpen.apply(window,[str,...args]);}var searchRegexp=toRegExp(delay);if(match!==searchRegexp.test(str)){return nativeOpen.apply(window,[str,...args]);}hit(source);return handleOldReplacement(replacement);};var newOpenWrapper=function newOpenWrapper(url){var shouldLog=replacement&&replacement.includes("log");for(var _len2=arguments.length,args=new Array(_len2>1?_len2-1:0),_key2=1;_key2<_len2;_key2++){args[_key2-1]=arguments[_key2];}if(shouldLog){var argsStr=args&&args.length>0?", ".concat(args.join(", ")):"";var message="".concat(url).concat(argsStr);logMessage(source,message,true);hit(source);}var shouldPrevent=false;if(match==="*"){shouldPrevent=true;}else if(isValidMatchStr(match)){var _parseMatchArg=parseMatchArg(match),isInvertedMatch=_parseMatchArg.isInvertedMatch,matchRegexp=_parseMatchArg.matchRegexp;shouldPrevent=matchRegexp.test(url)!==isInvertedMatch;}else {logMessage(source,"Invalid parameter: ".concat(match));shouldPrevent=false;}if(shouldPrevent){var parsedDelay=parseInt(delay,10);var result;if(nativeIsNaN(parsedDelay)){result=noopNull();}else {var decoyArgs={replacement:replacement,url:url,delay:parsedDelay};var decoy=createDecoy(decoyArgs);var popup=decoy.contentWindow;if(typeof popup==="object"&&popup!==null){Object.defineProperty(popup,"closed",{value:false});Object.defineProperty(popup,"opener",{value:window});Object.defineProperty(popup,"frameElement",{value:null});}else {var nativeGetter=decoy.contentWindow&&decoy.contentWindow.get;Object.defineProperty(decoy,"contentWindow",{get:getPreventGetter(nativeGetter)});popup=decoy.contentWindow;}result=popup;}hit(source);return result;}return nativeOpen.apply(window,[url,...args]);};window.open=isNewSyntax?newOpenWrapper:oldOpenWrapper;window.open.toString=nativeOpen.toString.bind(nativeOpen);}function hit(source){var ADGUARD_PREFIX="[AdGuard]";if(!source.verbose){return;}try{var trace=console.trace.bind(console);var label="".concat(ADGUARD_PREFIX," ");if(source.engine==="corelibs"){label+=source.ruleText;}else {if(source.domainName){label+="".concat(source.domainName);}if(source.args){label+="#%#//scriptlet('".concat(source.name,"', '").concat(source.args.join("', '"),"')");}else {label+="#%#//scriptlet('".concat(source.name,"')");}}if(trace){trace(label);}}catch(e){}if(typeof window.__debug==="function"){window.__debug(source);}}function isValidStrPattern(input){var FORWARD_SLASH="/";var str=escapeRegExp(input);if(input[0]===FORWARD_SLASH&&input[input.length-1]===FORWARD_SLASH){str=input.slice(1,-1);}var isValid;try{isValid=new RegExp(str);isValid=true;}catch(e){isValid=false;}return isValid;}function escapeRegExp(str){return str.replace(/[.*+?^${}()|[\]\\]/g,"\\$&");}function isValidMatchStr(match){var INVERT_MARKER="!";var str=match;if(match!==null&&match!==void 0&&match.startsWith(INVERT_MARKER)){str=match.slice(1);}return isValidStrPattern(str);}function toRegExp(rawInput){var input=rawInput||"";var DEFAULT_VALUE=".?";var FORWARD_SLASH="/";if(input===""){return new RegExp(DEFAULT_VALUE);}var delimiterIndex=input.lastIndexOf(FORWARD_SLASH);var flagsPart=input.substring(delimiterIndex+1);var regExpPart=input.substring(0,delimiterIndex+1);var isValidRegExpFlag=function isValidRegExpFlag(flag){if(!flag){return false;}try{new RegExp("",flag);return true;}catch(ex){return false;}};var getRegExpFlags=function getRegExpFlags(regExpStr,flagsStr){if(regExpStr.startsWith(FORWARD_SLASH)&&regExpStr.endsWith(FORWARD_SLASH)&&!regExpStr.endsWith("\\/")&&isValidRegExpFlag(flagsStr)){return flagsStr;}return "";};var flags=getRegExpFlags(regExpPart,flagsPart);if(input.startsWith(FORWARD_SLASH)&&input.endsWith(FORWARD_SLASH)||flags){var regExpInput=flags?regExpPart:input;return new RegExp(regExpInput.slice(1,-1),flags);}var escaped=input.replace(/\\'/g,"'").replace(/\\"/g,'"').replace(/[.*+?^${}()|[\]\\]/g,"\\$&");return new RegExp(escaped);}function nativeIsNaN(num){var native=Number.isNaN||window.isNaN;return native(num);}function parseMatchArg(match){var INVERT_MARKER="!";var isInvertedMatch=match?match===null||match===void 0?void 0:match.startsWith(INVERT_MARKER):false;var matchValue=isInvertedMatch?match.slice(1):match;var matchRegexp=toRegExp(matchValue);return {isInvertedMatch:isInvertedMatch,matchRegexp:matchRegexp,matchValue:matchValue};}function handleOldReplacement(replacement){var result;if(!replacement){result=noopFunc;}else if(replacement==="trueFunc"){result=trueFunc;}else if(replacement.includes("=")){var isProp=replacement.startsWith("{")&&replacement.endsWith("}");if(isProp){var propertyPart=replacement.slice(1,-1);var propertyName=substringBefore(propertyPart,"=");var propertyValue=substringAfter(propertyPart,"=");if(propertyValue==="noopFunc"){result={};result[propertyName]=noopFunc;}}}return result;}function createDecoy(args){var UrlPropNameOf=function(UrlPropNameOf){UrlPropNameOf["Object"]="data";UrlPropNameOf["Iframe"]="src";return UrlPropNameOf;}({});var replacement=args.replacement,url=args.url,delay=args.delay;var tag;if(replacement==="obj"){tag="object";}else {tag="iframe";}var decoy=document.createElement(tag);if(decoy instanceof HTMLObjectElement){decoy[UrlPropNameOf.Object]=url;}else if(decoy instanceof HTMLIFrameElement){decoy[UrlPropNameOf.Iframe]=url;}decoy.style.setProperty("height","1px","important");decoy.style.setProperty("position","fixed","important");decoy.style.setProperty("top","-1px","important");decoy.style.setProperty("width","1px","important");document.body.appendChild(decoy);setTimeout(function(){return decoy.remove();},delay*1e3);return decoy;}function getPreventGetter(nativeGetter){var preventGetter=function preventGetter(target,prop){if(prop&&prop==="closed"){return false;}if(typeof nativeGetter==="function"){return noopFunc;}return prop&&target[prop];};return preventGetter;}function noopNull(){return null;}function logMessage(source,message){var forced=arguments.length>2&&arguments[2]!==undefined?arguments[2]:false;var convertMessageToString=arguments.length>3&&arguments[3]!==undefined?arguments[3]:true;var name=source.name,verbose=source.verbose;if(!forced&&!verbose){return;}var nativeConsole=console.log;if(!convertMessageToString){nativeConsole("".concat(name,":"),message);return;}nativeConsole("".concat(name,": ").concat(message));}function noopFunc(){}function trueFunc(){return true;}function substringBefore(str,separator){if(!str||!separator){return str;}var index=str.indexOf(separator);return index<0?str:str.substring(0,index);}function substringAfter(str,separator){if(!str){return str;}var index=str.indexOf(separator);return index<0?"":str.substring(index+separator.length);}var updatedArgs=args?[].concat(source).concat(args):[source];try{preventWindowOpen.apply(this,updatedArgs);if(source.uniqueId){Object.defineProperty(Window.prototype.toString,uniqueIdentifier,{value:flag,enumerable:false,writable:false,configurable:false});}}catch(e){console.log(e);}}function preventXHR(source,args){var flag="done";var uniqueIdentifier=source.uniqueId+source.name+"_"+(Array.isArray(args)?args.join("_"):"");if(source.uniqueId){if(Window.prototype.toString[uniqueIdentifier]===flag){return;}}function preventXHR(source,propsToMatch,customResponseText){if(typeof Proxy==="undefined"){return;}var nativeOpen=window.XMLHttpRequest.prototype.open;var nativeSend=window.XMLHttpRequest.prototype.send;var nativeGetResponseHeader=window.XMLHttpRequest.prototype.getResponseHeader;var nativeGetAllResponseHeaders=window.XMLHttpRequest.prototype.getAllResponseHeaders;var xhrData;var modifiedResponse="";var modifiedResponseText="";var openWrapper=function openWrapper(target,thisArg,args){xhrData=getXhrData.apply(null,args);if(typeof propsToMatch==="undefined"){logMessage(source,"xhr( ".concat(objectToString(xhrData)," )"),true);hit(source);}else if(matchRequestProps(source,propsToMatch,xhrData)){thisArg.shouldBePrevented=true;thisArg.xhrData=xhrData;}if(thisArg.shouldBePrevented){thisArg.collectedHeaders=[];var setRequestHeaderWrapper=function setRequestHeaderWrapper(target,thisArg,args){thisArg.collectedHeaders.push(args);return Reflect.apply(target,thisArg,args);};var setRequestHeaderHandler={apply:setRequestHeaderWrapper};thisArg.setRequestHeader=new Proxy(thisArg.setRequestHeader,setRequestHeaderHandler);}return Reflect.apply(target,thisArg,args);};var sendWrapper=function sendWrapper(target,thisArg,args){if(!thisArg.shouldBePrevented){return Reflect.apply(target,thisArg,args);}if(thisArg.responseType==="blob"){modifiedResponse=new Blob();}if(thisArg.responseType==="arraybuffer"){modifiedResponse=new ArrayBuffer();}if(customResponseText){var randomText=generateRandomResponse(customResponseText);if(randomText){modifiedResponseText=randomText;}else {logMessage(source,"Invalid randomize parameter: '".concat(customResponseText,"'"));}}var forgedRequest=new XMLHttpRequest();forgedRequest.addEventListener("readystatechange",function(){if(forgedRequest.readyState!==4){return;}var readyState=forgedRequest.readyState,responseURL=forgedRequest.responseURL,responseXML=forgedRequest.responseXML,statusText=forgedRequest.statusText;Object.defineProperties(thisArg,{readyState:{value:readyState,writable:false},statusText:{value:statusText,writable:false},responseURL:{value:responseURL||thisArg.xhrData.url,writable:false},responseXML:{value:responseXML,writable:false},status:{value:200,writable:false},response:{value:modifiedResponse,writable:false},responseText:{value:modifiedResponseText,writable:false}});setTimeout(function(){var stateEvent=new Event("readystatechange");thisArg.dispatchEvent(stateEvent);var loadEvent=new Event("load");thisArg.dispatchEvent(loadEvent);var loadEndEvent=new Event("loadend");thisArg.dispatchEvent(loadEndEvent);},1);hit(source);});nativeOpen.apply(forgedRequest,[thisArg.xhrData.method,thisArg.xhrData.url]);thisArg.collectedHeaders.forEach(function(header){var name=header[0];var value=header[1];forgedRequest.setRequestHeader(name,value);});try{nativeSend.call(forgedRequest,args);}catch(_unused){return Reflect.apply(target,thisArg,args);}return undefined;};var getHeaderWrapper=function getHeaderWrapper(target,thisArg,args){if(!thisArg.shouldBePrevented){return nativeGetResponseHeader.apply(thisArg,args);}if(!thisArg.collectedHeaders.length){return null;}var searchHeaderName=args[0].toLowerCase();var matchedHeader=thisArg.collectedHeaders.find(function(header){var headerName=header[0].toLowerCase();return headerName===searchHeaderName;});return matchedHeader?matchedHeader[1]:null;};var getAllHeadersWrapper=function getAllHeadersWrapper(target,thisArg){if(!thisArg.shouldBePrevented){return nativeGetAllResponseHeaders.call(thisArg);}if(!thisArg.collectedHeaders.length){return "";}var allHeadersStr=thisArg.collectedHeaders.map(function(header){var headerName=header[0];var headerValue=header[1];return "".concat(headerName.toLowerCase(),": ").concat(headerValue);}).join("\r\n");return allHeadersStr;};var openHandler={apply:openWrapper};var sendHandler={apply:sendWrapper};var getHeaderHandler={apply:getHeaderWrapper};var getAllHeadersHandler={apply:getAllHeadersWrapper};XMLHttpRequest.prototype.open=new Proxy(XMLHttpRequest.prototype.open,openHandler);XMLHttpRequest.prototype.send=new Proxy(XMLHttpRequest.prototype.send,sendHandler);XMLHttpRequest.prototype.getResponseHeader=new Proxy(XMLHttpRequest.prototype.getResponseHeader,getHeaderHandler);XMLHttpRequest.prototype.getAllResponseHeaders=new Proxy(XMLHttpRequest.prototype.getAllResponseHeaders,getAllHeadersHandler);}function hit(source){var ADGUARD_PREFIX="[AdGuard]";if(!source.verbose){return;}try{var trace=console.trace.bind(console);var label="".concat(ADGUARD_PREFIX," ");if(source.engine==="corelibs"){label+=source.ruleText;}else {if(source.domainName){label+="".concat(source.domainName);}if(source.args){label+="#%#//scriptlet('".concat(source.name,"', '").concat(source.args.join("', '"),"')");}else {label+="#%#//scriptlet('".concat(source.name,"')");}}if(trace){trace(label);}}catch(e){}if(typeof window.__debug==="function"){window.__debug(source);}}function objectToString(obj){if(!obj||typeof obj!=="object"){return String(obj);}if(isEmptyObject(obj)){return "{}";}return Object.entries(obj).map(function(pair){var key=pair[0];var value=pair[1];var recordValueStr=value;if(value instanceof Object){recordValueStr="{ ".concat(objectToString(value)," }");}return "".concat(key,':"').concat(recordValueStr,'"');}).join(" ");}function generateRandomResponse(customResponseText){var customResponse=customResponseText;if(customResponse==="true"){customResponse=Math.random().toString(36).slice(-10);return customResponse;}customResponse=customResponse.replace("length:","");var rangeRegex=/^\d+-\d+$/;if(!rangeRegex.test(customResponse)){return null;}var rangeMin=getNumberFromString(customResponse.split("-")[0]);var rangeMax=getNumberFromString(customResponse.split("-")[1]);if(!nativeIsFinite(rangeMin)||!nativeIsFinite(rangeMax)){return null;}if(rangeMin>rangeMax){var temp=rangeMin;rangeMin=rangeMax;rangeMax=temp;}var LENGTH_RANGE_LIMIT=500*1e3;if(rangeMax>LENGTH_RANGE_LIMIT){return null;}var length=getRandomIntInclusive(rangeMin,rangeMax);customResponse=getRandomStrByLength(length);return customResponse;}function matchRequestProps(source,propsToMatch,requestData){if(propsToMatch===""||propsToMatch==="*"){return true;}var isMatched;var parsedData=parseMatchProps(propsToMatch);if(!isValidParsedData(parsedData)){logMessage(source,"Invalid parameter: ".concat(propsToMatch));isMatched=false;}else {var matchData=getMatchPropsData(parsedData);var matchKeys=Object.keys(matchData);isMatched=matchKeys.every(function(matchKey){var matchValue=matchData[matchKey];var dataValue=requestData[matchKey];return Object.prototype.hasOwnProperty.call(requestData,matchKey)&&typeof dataValue==="string"&&(matchValue===null||matchValue===void 0?void 0:matchValue.test(dataValue));});}return isMatched;}function getXhrData(method,url,async,user,password){return {method:method,url:url,async:async,user:user,password:password};}function logMessage(source,message){var forced=arguments.length>2&&arguments[2]!==undefined?arguments[2]:false;var convertMessageToString=arguments.length>3&&arguments[3]!==undefined?arguments[3]:true;var name=source.name,verbose=source.verbose;if(!forced&&!verbose){return;}var nativeConsole=console.log;if(!convertMessageToString){nativeConsole("".concat(name,":"),message);return;}nativeConsole("".concat(name,": ").concat(message));}function toRegExp(rawInput){var input=rawInput||"";var DEFAULT_VALUE=".?";var FORWARD_SLASH="/";if(input===""){return new RegExp(DEFAULT_VALUE);}var delimiterIndex=input.lastIndexOf(FORWARD_SLASH);var flagsPart=input.substring(delimiterIndex+1);var regExpPart=input.substring(0,delimiterIndex+1);var isValidRegExpFlag=function isValidRegExpFlag(flag){if(!flag){return false;}try{new RegExp("",flag);return true;}catch(ex){return false;}};var getRegExpFlags=function getRegExpFlags(regExpStr,flagsStr){if(regExpStr.startsWith(FORWARD_SLASH)&&regExpStr.endsWith(FORWARD_SLASH)&&!regExpStr.endsWith("\\/")&&isValidRegExpFlag(flagsStr)){return flagsStr;}return "";};var flags=getRegExpFlags(regExpPart,flagsPart);if(input.startsWith(FORWARD_SLASH)&&input.endsWith(FORWARD_SLASH)||flags){var regExpInput=flags?regExpPart:input;return new RegExp(regExpInput.slice(1,-1),flags);}var escaped=input.replace(/\\'/g,"'").replace(/\\"/g,'"').replace(/[.*+?^${}()|[\]\\]/g,"\\$&");return new RegExp(escaped);}function isValidStrPattern(input){var FORWARD_SLASH="/";var str=escapeRegExp(input);if(input[0]===FORWARD_SLASH&&input[input.length-1]===FORWARD_SLASH){str=input.slice(1,-1);}var isValid;try{isValid=new RegExp(str);isValid=true;}catch(e){isValid=false;}return isValid;}function escapeRegExp(str){return str.replace(/[.*+?^${}()|[\]\\]/g,"\\$&");}function isEmptyObject(obj){return Object.keys(obj).length===0&&!obj.prototype;}function getNumberFromString(rawString){var parsedDelay=parseInt(rawString,10);var validDelay=nativeIsNaN(parsedDelay)?null:parsedDelay;return validDelay;}function nativeIsFinite(num){var native=Number.isFinite||window.isFinite;return native(num);}function nativeIsNaN(num){var native=Number.isNaN||window.isNaN;return native(num);}function parseMatchProps(propsToMatchStr){var PROPS_DIVIDER=" ";var PAIRS_MARKER=":";var isRequestProp=function isRequestProp(prop){return getRequestProps().includes(prop);};var propsObj={};var props=propsToMatchStr.split(PROPS_DIVIDER);props.forEach(function(prop){var dividerInd=prop.indexOf(PAIRS_MARKER);var key=prop.slice(0,dividerInd);if(isRequestProp(key)){var value=prop.slice(dividerInd+1);propsObj[key]=value;}else {propsObj.url=prop;}});return propsObj;}function isValidParsedData(data){return Object.values(data).every(function(value){return isValidStrPattern(value);});}function getMatchPropsData(data){var matchData={};var dataKeys=Object.keys(data);dataKeys.forEach(function(key){matchData[key]=toRegExp(data[key]);});return matchData;}function getRequestProps(){return ["url","method","headers","body","credentials","cache","redirect","referrer","referrerPolicy","integrity","keepalive","signal","mode"];}function getRandomIntInclusive(min,max){min=Math.ceil(min);max=Math.floor(max);return Math.floor(Math.random()*(max-min+1)+min);}function getRandomStrByLength(length){var result="";var characters="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789!@#$%^&*()_+=~";var charactersLength=characters.length;for(var i=0;i<length;i+=1){result+=characters.charAt(Math.floor(Math.random()*charactersLength));}return result;}var updatedArgs=args?[].concat(source).concat(args):[source];try{preventXHR.apply(this,updatedArgs);if(source.uniqueId){Object.defineProperty(Window.prototype.toString,uniqueIdentifier,{value:flag,enumerable:false,writable:false,configurable:false});}}catch(e){console.log(e);}}function removeAttr(source,args){var flag="done";var uniqueIdentifier=source.uniqueId+source.name+"_"+(Array.isArray(args)?args.join("_"):"");if(source.uniqueId){if(Window.prototype.toString[uniqueIdentifier]===flag){return;}}function removeAttr(source,attrs,selector){var applying=arguments.length>3&&arguments[3]!==undefined?arguments[3]:"asap stay";if(!attrs){return;}attrs=attrs.split(/\s*\|\s*/);if(!selector){selector="[".concat(attrs.join("],["),"]");}var rmattr=function rmattr(){var nodes=[];try{nodes=[].slice.call(document.querySelectorAll(selector));}catch(e){logMessage(source,"Invalid selector arg: '".concat(selector,"'"));}var removed=false;nodes.forEach(function(node){attrs.forEach(function(attr){node.removeAttribute(attr);removed=true;});});if(removed){hit(source);}};var flags=parseFlags(applying);var run=function run(){rmattr();if(!flags.hasFlag(flags.STAY)){return;}observeDOMChanges(rmattr,true);};if(flags.hasFlag(flags.ASAP)){if(document.readyState==="loading"){window.addEventListener("DOMContentLoaded",rmattr,{once:true});}else {rmattr();}}if(document.readyState!=="complete"&&flags.hasFlag(flags.COMPLETE)){window.addEventListener("load",run,{once:true});}else if(flags.hasFlag(flags.STAY)){if(!applying.includes(" ")){rmattr();}observeDOMChanges(rmattr,true);}}function hit(source){var ADGUARD_PREFIX="[AdGuard]";if(!source.verbose){return;}try{var trace=console.trace.bind(console);var label="".concat(ADGUARD_PREFIX," ");if(source.engine==="corelibs"){label+=source.ruleText;}else {if(source.domainName){label+="".concat(source.domainName);}if(source.args){label+="#%#//scriptlet('".concat(source.name,"', '").concat(source.args.join("', '"),"')");}else {label+="#%#//scriptlet('".concat(source.name,"')");}}if(trace){trace(label);}}catch(e){}if(typeof window.__debug==="function"){window.__debug(source);}}function observeDOMChanges(callback){var observeAttrs=arguments.length>1&&arguments[1]!==undefined?arguments[1]:false;var attrsToObserve=arguments.length>2&&arguments[2]!==undefined?arguments[2]:[];var THROTTLE_DELAY_MS=20;var observer=new MutationObserver(throttle(callbackWrapper,THROTTLE_DELAY_MS));var connect=function connect(){if(attrsToObserve.length>0){observer.observe(document.documentElement,{childList:true,subtree:true,attributes:observeAttrs,attributeFilter:attrsToObserve});}else {observer.observe(document.documentElement,{childList:true,subtree:true,attributes:observeAttrs});}};var disconnect=function disconnect(){observer.disconnect();};function callbackWrapper(){disconnect();callback();connect();}connect();}function parseFlags(flags){var FLAGS_DIVIDER=" ";var ASAP_FLAG="asap";var COMPLETE_FLAG="complete";var STAY_FLAG="stay";var VALID_FLAGS=new Set([ASAP_FLAG,COMPLETE_FLAG,STAY_FLAG]);var passedFlags=new Set(flags.trim().split(FLAGS_DIVIDER).filter(function(flag){return VALID_FLAGS.has(flag);}));return {ASAP:ASAP_FLAG,COMPLETE:COMPLETE_FLAG,STAY:STAY_FLAG,hasFlag:function hasFlag(flag){return passedFlags.has(flag);}};}function logMessage(source,message){var forced=arguments.length>2&&arguments[2]!==undefined?arguments[2]:false;var convertMessageToString=arguments.length>3&&arguments[3]!==undefined?arguments[3]:true;var name=source.name,verbose=source.verbose;if(!forced&&!verbose){return;}var nativeConsole=console.log;if(!convertMessageToString){nativeConsole("".concat(name,":"),message);return;}nativeConsole("".concat(name,": ").concat(message));}function throttle(cb,delay){var wait=false;var savedArgs;var wrapper=function wrapper(){for(var _len=arguments.length,args=new Array(_len),_key=0;_key<_len;_key++){args[_key]=arguments[_key];}if(wait){savedArgs=args;return;}cb(...args);wait=true;setTimeout(function(){wait=false;if(savedArgs){wrapper(...savedArgs);savedArgs=null;}},delay);};return wrapper;}var updatedArgs=args?[].concat(source).concat(args):[source];try{removeAttr.apply(this,updatedArgs);if(source.uniqueId){Object.defineProperty(Window.prototype.toString,uniqueIdentifier,{value:flag,enumerable:false,writable:false,configurable:false});}}catch(e){console.log(e);}}function removeClass(source,args){var flag="done";var uniqueIdentifier=source.uniqueId+source.name+"_"+(Array.isArray(args)?args.join("_"):"");if(source.uniqueId){if(Window.prototype.toString[uniqueIdentifier]===flag){return;}}function removeClass(source,classNames,selector){var applying=arguments.length>3&&arguments[3]!==undefined?arguments[3]:"asap stay";if(!classNames){return;}classNames=classNames.split(/\s*\|\s*/);var selectors=[];if(!selector){selectors=classNames.map(function(className){return ".".concat(className);});}var removeClassHandler=function removeClassHandler(){var nodes=new Set();if(selector){var foundNodes=[];try{foundNodes=[].slice.call(document.querySelectorAll(selector));}catch(e){logMessage(source,"Invalid selector arg: '".concat(selector,"'"));}foundNodes.forEach(function(n){return nodes.add(n);});}else if(selectors.length>0){selectors.forEach(function(s){var elements=document.querySelectorAll(s);for(var i=0;i<elements.length;i+=1){var element=elements[i];nodes.add(element);}});}var removed=false;nodes.forEach(function(node){classNames.forEach(function(className){if(node.classList.contains(className)){node.classList.remove(className);removed=true;}});});if(removed){hit(source);}};var CLASS_ATTR_NAME=["class"];var flags=parseFlags(applying);var run=function run(){removeClassHandler();if(!flags.hasFlag(flags.STAY)){return;}observeDOMChanges(removeClassHandler,true,CLASS_ATTR_NAME);};if(flags.hasFlag(flags.ASAP)){if(document.readyState==="loading"){window.addEventListener("DOMContentLoaded",removeClassHandler,{once:true});}else {removeClassHandler();}}if(document.readyState!=="complete"&&flags.hasFlag(flags.COMPLETE)){window.addEventListener("load",run,{once:true});}else if(flags.hasFlag(flags.STAY)){if(!applying.includes(" ")){removeClassHandler();}observeDOMChanges(removeClassHandler,true,CLASS_ATTR_NAME);}}function hit(source){var ADGUARD_PREFIX="[AdGuard]";if(!source.verbose){return;}try{var trace=console.trace.bind(console);var label="".concat(ADGUARD_PREFIX," ");if(source.engine==="corelibs"){label+=source.ruleText;}else {if(source.domainName){label+="".concat(source.domainName);}if(source.args){label+="#%#//scriptlet('".concat(source.name,"', '").concat(source.args.join("', '"),"')");}else {label+="#%#//scriptlet('".concat(source.name,"')");}}if(trace){trace(label);}}catch(e){}if(typeof window.__debug==="function"){window.__debug(source);}}function logMessage(source,message){var forced=arguments.length>2&&arguments[2]!==undefined?arguments[2]:false;var convertMessageToString=arguments.length>3&&arguments[3]!==undefined?arguments[3]:true;var name=source.name,verbose=source.verbose;if(!forced&&!verbose){return;}var nativeConsole=console.log;if(!convertMessageToString){nativeConsole("".concat(name,":"),message);return;}nativeConsole("".concat(name,": ").concat(message));}function observeDOMChanges(callback){var observeAttrs=arguments.length>1&&arguments[1]!==undefined?arguments[1]:false;var attrsToObserve=arguments.length>2&&arguments[2]!==undefined?arguments[2]:[];var THROTTLE_DELAY_MS=20;var observer=new MutationObserver(throttle(callbackWrapper,THROTTLE_DELAY_MS));var connect=function connect(){if(attrsToObserve.length>0){observer.observe(document.documentElement,{childList:true,subtree:true,attributes:observeAttrs,attributeFilter:attrsToObserve});}else {observer.observe(document.documentElement,{childList:true,subtree:true,attributes:observeAttrs});}};var disconnect=function disconnect(){observer.disconnect();};function callbackWrapper(){disconnect();callback();connect();}connect();}function parseFlags(flags){var FLAGS_DIVIDER=" ";var ASAP_FLAG="asap";var COMPLETE_FLAG="complete";var STAY_FLAG="stay";var VALID_FLAGS=new Set([ASAP_FLAG,COMPLETE_FLAG,STAY_FLAG]);var passedFlags=new Set(flags.trim().split(FLAGS_DIVIDER).filter(function(flag){return VALID_FLAGS.has(flag);}));return {ASAP:ASAP_FLAG,COMPLETE:COMPLETE_FLAG,STAY:STAY_FLAG,hasFlag:function hasFlag(flag){return passedFlags.has(flag);}};}function throttle(cb,delay){var wait=false;var savedArgs;var wrapper=function wrapper(){for(var _len=arguments.length,args=new Array(_len),_key=0;_key<_len;_key++){args[_key]=arguments[_key];}if(wait){savedArgs=args;return;}cb(...args);wait=true;setTimeout(function(){wait=false;if(savedArgs){wrapper(...savedArgs);savedArgs=null;}},delay);};return wrapper;}var updatedArgs=args?[].concat(source).concat(args):[source];try{removeClass.apply(this,updatedArgs);if(source.uniqueId){Object.defineProperty(Window.prototype.toString,uniqueIdentifier,{value:flag,enumerable:false,writable:false,configurable:false});}}catch(e){console.log(e);}}function removeCookie(source,args){var flag="done";var uniqueIdentifier=source.uniqueId+source.name+"_"+(Array.isArray(args)?args.join("_"):"");if(source.uniqueId){if(Window.prototype.toString[uniqueIdentifier]===flag){return;}}function removeCookie(source,match){var matchRegexp=toRegExp(match);var removeCookieFromHost=function removeCookieFromHost(cookieName,hostName){var cookieSpec="".concat(cookieName,"=");var domain1="; domain=".concat(hostName);var domain2="; domain=.".concat(hostName);var path="; path=/";var expiration="; expires=Thu, 01 Jan 1970 00:00:00 GMT";document.cookie=cookieSpec+expiration;document.cookie=cookieSpec+domain1+expiration;document.cookie=cookieSpec+domain2+expiration;document.cookie=cookieSpec+path+expiration;document.cookie=cookieSpec+domain1+path+expiration;document.cookie=cookieSpec+domain2+path+expiration;hit(source);};var rmCookie=function rmCookie(){document.cookie.split(";").forEach(function(cookieStr){var pos=cookieStr.indexOf("=");if(pos===-1){return;}var cookieName=cookieStr.slice(0,pos).trim();if(!matchRegexp.test(cookieName)){return;}var hostParts=document.location.hostname.split(".");for(var i=0;i<=hostParts.length-1;i+=1){var hostName=hostParts.slice(i).join(".");if(hostName){removeCookieFromHost(cookieName,hostName);}}});};rmCookie();window.addEventListener("beforeunload",rmCookie);}function toRegExp(rawInput){var input=rawInput||"";var DEFAULT_VALUE=".?";var FORWARD_SLASH="/";if(input===""){return new RegExp(DEFAULT_VALUE);}var delimiterIndex=input.lastIndexOf(FORWARD_SLASH);var flagsPart=input.substring(delimiterIndex+1);var regExpPart=input.substring(0,delimiterIndex+1);var isValidRegExpFlag=function isValidRegExpFlag(flag){if(!flag){return false;}try{new RegExp("",flag);return true;}catch(ex){return false;}};var getRegExpFlags=function getRegExpFlags(regExpStr,flagsStr){if(regExpStr.startsWith(FORWARD_SLASH)&&regExpStr.endsWith(FORWARD_SLASH)&&!regExpStr.endsWith("\\/")&&isValidRegExpFlag(flagsStr)){return flagsStr;}return "";};var flags=getRegExpFlags(regExpPart,flagsPart);if(input.startsWith(FORWARD_SLASH)&&input.endsWith(FORWARD_SLASH)||flags){var regExpInput=flags?regExpPart:input;return new RegExp(regExpInput.slice(1,-1),flags);}var escaped=input.replace(/\\'/g,"'").replace(/\\"/g,'"').replace(/[.*+?^${}()|[\]\\]/g,"\\$&");return new RegExp(escaped);}function hit(source){var ADGUARD_PREFIX="[AdGuard]";if(!source.verbose){return;}try{var trace=console.trace.bind(console);var label="".concat(ADGUARD_PREFIX," ");if(source.engine==="corelibs"){label+=source.ruleText;}else {if(source.domainName){label+="".concat(source.domainName);}if(source.args){label+="#%#//scriptlet('".concat(source.name,"', '").concat(source.args.join("', '"),"')");}else {label+="#%#//scriptlet('".concat(source.name,"')");}}if(trace){trace(label);}}catch(e){}if(typeof window.__debug==="function"){window.__debug(source);}}var updatedArgs=args?[].concat(source).concat(args):[source];try{removeCookie.apply(this,updatedArgs);if(source.uniqueId){Object.defineProperty(Window.prototype.toString,uniqueIdentifier,{value:flag,enumerable:false,writable:false,configurable:false});}}catch(e){console.log(e);}}function removeInShadowDom(source,args){var flag="done";var uniqueIdentifier=source.uniqueId+source.name+"_"+(Array.isArray(args)?args.join("_"):"");if(source.uniqueId){if(Window.prototype.toString[uniqueIdentifier]===flag){return;}}function removeInShadowDom(source,selector,baseSelector){if(!Element.prototype.attachShadow){return;}var removeElement=function removeElement(targetElement){targetElement.remove();};var removeHandler=function removeHandler(){var hostElements=!baseSelector?findHostElements(document.documentElement):document.querySelectorAll(baseSelector);var _loop=function _loop(){var isRemoved=false;var _pierceShadowDom=pierceShadowDom(selector,hostElements),targets=_pierceShadowDom.targets,innerHosts=_pierceShadowDom.innerHosts;targets.forEach(function(targetEl){removeElement(targetEl);isRemoved=true;});if(isRemoved){hit(source);}hostElements=innerHosts;};while(hostElements.length!==0){_loop();}};removeHandler();observeDOMChanges(removeHandler,true);}function hit(source){var ADGUARD_PREFIX="[AdGuard]";if(!source.verbose){return;}try{var trace=console.trace.bind(console);var label="".concat(ADGUARD_PREFIX," ");if(source.engine==="corelibs"){label+=source.ruleText;}else {if(source.domainName){label+="".concat(source.domainName);}if(source.args){label+="#%#//scriptlet('".concat(source.name,"', '").concat(source.args.join("', '"),"')");}else {label+="#%#//scriptlet('".concat(source.name,"')");}}if(trace){trace(label);}}catch(e){}if(typeof window.__debug==="function"){window.__debug(source);}}function observeDOMChanges(callback){var observeAttrs=arguments.length>1&&arguments[1]!==undefined?arguments[1]:false;var attrsToObserve=arguments.length>2&&arguments[2]!==undefined?arguments[2]:[];var THROTTLE_DELAY_MS=20;var observer=new MutationObserver(throttle(callbackWrapper,THROTTLE_DELAY_MS));var connect=function connect(){if(attrsToObserve.length>0){observer.observe(document.documentElement,{childList:true,subtree:true,attributes:observeAttrs,attributeFilter:attrsToObserve});}else {observer.observe(document.documentElement,{childList:true,subtree:true,attributes:observeAttrs});}};var disconnect=function disconnect(){observer.disconnect();};function callbackWrapper(){disconnect();callback();connect();}connect();}function findHostElements(rootElement){var hosts=[];if(rootElement){var domElems=rootElement.querySelectorAll("*");domElems.forEach(function(el){if(el.shadowRoot){hosts.push(el);}});}return hosts;}function pierceShadowDom(selector,hostElements){var targets=[];var innerHostsAcc=[];hostElements.forEach(function(host){var simpleElems=host.querySelectorAll(selector);targets=targets.concat([].slice.call(simpleElems));var shadowRootElem=host.shadowRoot;var shadowChildren=shadowRootElem.querySelectorAll(selector);targets=targets.concat([].slice.call(shadowChildren));innerHostsAcc.push(findHostElements(shadowRootElem));});var innerHosts=flatten(innerHostsAcc);return {targets:targets,innerHosts:innerHosts};}function flatten(input){var stack=[];input.forEach(function(el){return stack.push(el);});var res=[];while(stack.length){var next=stack.pop();if(Array.isArray(next)){next.forEach(function(el){return stack.push(el);});}else {res.push(next);}}return res.reverse();}function throttle(cb,delay){var wait=false;var savedArgs;var wrapper=function wrapper(){for(var _len=arguments.length,args=new Array(_len),_key=0;_key<_len;_key++){args[_key]=arguments[_key];}if(wait){savedArgs=args;return;}cb(...args);wait=true;setTimeout(function(){wait=false;if(savedArgs){wrapper(...savedArgs);savedArgs=null;}},delay);};return wrapper;}var updatedArgs=args?[].concat(source).concat(args):[source];try{removeInShadowDom.apply(this,updatedArgs);if(source.uniqueId){Object.defineProperty(Window.prototype.toString,uniqueIdentifier,{value:flag,enumerable:false,writable:false,configurable:false});}}catch(e){console.log(e);}}function removeNodeText(source,args){var flag="done";var uniqueIdentifier=source.uniqueId+source.name+"_"+(Array.isArray(args)?args.join("_"):"");if(source.uniqueId){if(Window.prototype.toString[uniqueIdentifier]===flag){return;}}function removeNodeText(source,nodeName,textMatch){var _parseNodeTextParams=parseNodeTextParams(nodeName,textMatch),selector=_parseNodeTextParams.selector,nodeNameMatch=_parseNodeTextParams.nodeNameMatch,textContentMatch=_parseNodeTextParams.textContentMatch;var handleNodes=function handleNodes(nodes){return nodes.forEach(function(node){var shouldReplace=isTargetNode(node,nodeNameMatch,textContentMatch);if(shouldReplace){var ALL_TEXT_PATTERN=/^[\s\S]*$/;var REPLACEMENT="";replaceNodeText(source,node,ALL_TEXT_PATTERN,REPLACEMENT);}});};if(document.documentElement){handleExistingNodes(selector,handleNodes);}observeDocumentWithTimeout(function(mutations){return handleMutations(mutations,handleNodes);});}function observeDocumentWithTimeout(callback){var options=arguments.length>1&&arguments[1]!==undefined?arguments[1]:{subtree:true,childList:true};var timeout=arguments.length>2&&arguments[2]!==undefined?arguments[2]:1e4;var documentObserver=new MutationObserver(function(mutations,observer){observer.disconnect();callback(mutations,observer);observer.observe(document.documentElement,options);});documentObserver.observe(document.documentElement,options);if(typeof timeout==="number"){setTimeout(function(){return documentObserver.disconnect();},timeout);}}function handleExistingNodes(selector,handler){var nodeList=document.querySelectorAll(selector);var nodes=nodeListToArray(nodeList);handler(nodes);}function handleMutations(mutations,handler){var addedNodes=getAddedNodes(mutations);handler(addedNodes);}function replaceNodeText(source,node,pattern,replacement){var textContent=node.textContent;if(textContent){node.textContent=textContent.replace(pattern,replacement);hit(source);}}function isTargetNode(node,nodeNameMatch,textContentMatch){var nodeName=node.nodeName,textContent=node.textContent;var nodeNameLowerCase=nodeName.toLowerCase();return textContent!==null&&textContent!==""&&(nodeNameMatch instanceof RegExp?nodeNameMatch.test(nodeNameLowerCase):nodeNameMatch===nodeNameLowerCase)&&(textContentMatch instanceof RegExp?textContentMatch.test(textContent):textContent.includes(textContentMatch));}function parseNodeTextParams(nodeName,textMatch){var pattern=arguments.length>2&&arguments[2]!==undefined?arguments[2]:null;var REGEXP_START_MARKER="/";var isStringNameMatch=!(nodeName.startsWith(REGEXP_START_MARKER)&&nodeName.endsWith(REGEXP_START_MARKER));var selector=isStringNameMatch?nodeName:"*";var nodeNameMatch=isStringNameMatch?nodeName:toRegExp(nodeName);var textContentMatch=!textMatch.startsWith(REGEXP_START_MARKER)?textMatch:toRegExp(textMatch);var patternMatch;if(pattern){patternMatch=!pattern.startsWith(REGEXP_START_MARKER)?pattern:toRegExp(pattern);}return {selector:selector,nodeNameMatch:nodeNameMatch,textContentMatch:textContentMatch,patternMatch:patternMatch};}function hit(source){var ADGUARD_PREFIX="[AdGuard]";if(!source.verbose){return;}try{var trace=console.trace.bind(console);var label="".concat(ADGUARD_PREFIX," ");if(source.engine==="corelibs"){label+=source.ruleText;}else {if(source.domainName){label+="".concat(source.domainName);}if(source.args){label+="#%#//scriptlet('".concat(source.name,"', '").concat(source.args.join("', '"),"')");}else {label+="#%#//scriptlet('".concat(source.name,"')");}}if(trace){trace(label);}}catch(e){}if(typeof window.__debug==="function"){window.__debug(source);}}function nodeListToArray(nodeList){var nodes=[];for(var i=0;i<nodeList.length;i+=1){nodes.push(nodeList[i]);}return nodes;}function getAddedNodes(mutations){var nodes=[];for(var i=0;i<mutations.length;i+=1){var addedNodes=mutations[i].addedNodes;for(var j=0;j<addedNodes.length;j+=1){nodes.push(addedNodes[j]);}}return nodes;}function toRegExp(rawInput){var input=rawInput||"";var DEFAULT_VALUE=".?";var FORWARD_SLASH="/";if(input===""){return new RegExp(DEFAULT_VALUE);}var delimiterIndex=input.lastIndexOf(FORWARD_SLASH);var flagsPart=input.substring(delimiterIndex+1);var regExpPart=input.substring(0,delimiterIndex+1);var isValidRegExpFlag=function isValidRegExpFlag(flag){if(!flag){return false;}try{new RegExp("",flag);return true;}catch(ex){return false;}};var getRegExpFlags=function getRegExpFlags(regExpStr,flagsStr){if(regExpStr.startsWith(FORWARD_SLASH)&&regExpStr.endsWith(FORWARD_SLASH)&&!regExpStr.endsWith("\\/")&&isValidRegExpFlag(flagsStr)){return flagsStr;}return "";};var flags=getRegExpFlags(regExpPart,flagsPart);if(input.startsWith(FORWARD_SLASH)&&input.endsWith(FORWARD_SLASH)||flags){var regExpInput=flags?regExpPart:input;return new RegExp(regExpInput.slice(1,-1),flags);}var escaped=input.replace(/\\'/g,"'").replace(/\\"/g,'"').replace(/[.*+?^${}()|[\]\\]/g,"\\$&");return new RegExp(escaped);}var updatedArgs=args?[].concat(source).concat(args):[source];try{removeNodeText.apply(this,updatedArgs);if(source.uniqueId){Object.defineProperty(Window.prototype.toString,uniqueIdentifier,{value:flag,enumerable:false,writable:false,configurable:false});}}catch(e){console.log(e);}}function setAttr(source,args){var flag="done";var uniqueIdentifier=source.uniqueId+source.name+"_"+(Array.isArray(args)?args.join("_"):"");if(source.uniqueId){if(Window.prototype.toString[uniqueIdentifier]===flag){return;}}function setAttr(source,selector,attr){var value=arguments.length>3&&arguments[3]!==undefined?arguments[3]:"";if(!selector||!attr){return;}var allowedValues=["true","false"];var shouldCopyValue=value.startsWith("[")&&value.endsWith("]");var isValidValue=value.length===0||!nativeIsNaN(parseInt(value,10))&&parseInt(value,10)>=0&&parseInt(value,10)<=32767||allowedValues.includes(value.toLowerCase());if(!shouldCopyValue&&!isValidValue){logMessage(source,"Invalid attribute value provided: '".concat(convertTypeToString(value),"'"));return;}var attributeHandler;if(shouldCopyValue){attributeHandler=function attributeHandler(elem,attr,value){var valueToCopy=elem.getAttribute(value.slice(1,-1));if(valueToCopy===null){logMessage(source,"No element attribute found to copy value from: ".concat(value));}elem.setAttribute(attr,valueToCopy);};}setAttributeBySelector(source,selector,attr,value,attributeHandler);observeDOMChanges(function(){return setAttributeBySelector(source,selector,attr,value,attributeHandler);},true);}function setAttributeBySelector(source,selector,attribute,value){var attributeSetter=arguments.length>4&&arguments[4]!==undefined?arguments[4]:defaultAttributeSetter;var elements;try{elements=document.querySelectorAll(selector);}catch(_unused){logMessage(source,'Failed to find elements matching selector "'.concat(selector,'"'));return;}if(!elements||elements.length===0){return;}try{elements.forEach(function(elem){return attributeSetter(elem,attribute,value);});hit(source);}catch(_unused2){logMessage(source,"Failed to set [".concat(attribute,'="').concat(value,'"] to each of selected elements.'));}}function observeDOMChanges(callback){var observeAttrs=arguments.length>1&&arguments[1]!==undefined?arguments[1]:false;var attrsToObserve=arguments.length>2&&arguments[2]!==undefined?arguments[2]:[];var THROTTLE_DELAY_MS=20;var observer=new MutationObserver(throttle(callbackWrapper,THROTTLE_DELAY_MS));var connect=function connect(){if(attrsToObserve.length>0){observer.observe(document.documentElement,{childList:true,subtree:true,attributes:observeAttrs,attributeFilter:attrsToObserve});}else {observer.observe(document.documentElement,{childList:true,subtree:true,attributes:observeAttrs});}};var disconnect=function disconnect(){observer.disconnect();};function callbackWrapper(){disconnect();callback();connect();}connect();}function nativeIsNaN(num){var native=Number.isNaN||window.isNaN;return native(num);}function convertTypeToString(value){var output;if(typeof value==="undefined"){output="undefined";}else if(typeof value==="object"){if(value===null){output="null";}else {output=objectToString(value);}}else {output=String(value);}return output;}function defaultAttributeSetter(elem,attribute,value){return elem.setAttribute(attribute,value);}function logMessage(source,message){var forced=arguments.length>2&&arguments[2]!==undefined?arguments[2]:false;var convertMessageToString=arguments.length>3&&arguments[3]!==undefined?arguments[3]:true;var name=source.name,verbose=source.verbose;if(!forced&&!verbose){return;}var nativeConsole=console.log;if(!convertMessageToString){nativeConsole("".concat(name,":"),message);return;}nativeConsole("".concat(name,": ").concat(message));}function throttle(cb,delay){var wait=false;var savedArgs;var wrapper=function wrapper(){for(var _len=arguments.length,args=new Array(_len),_key=0;_key<_len;_key++){args[_key]=arguments[_key];}if(wait){savedArgs=args;return;}cb(...args);wait=true;setTimeout(function(){wait=false;if(savedArgs){wrapper(...savedArgs);savedArgs=null;}},delay);};return wrapper;}function hit(source){var ADGUARD_PREFIX="[AdGuard]";if(!source.verbose){return;}try{var trace=console.trace.bind(console);var label="".concat(ADGUARD_PREFIX," ");if(source.engine==="corelibs"){label+=source.ruleText;}else {if(source.domainName){label+="".concat(source.domainName);}if(source.args){label+="#%#//scriptlet('".concat(source.name,"', '").concat(source.args.join("', '"),"')");}else {label+="#%#//scriptlet('".concat(source.name,"')");}}if(trace){trace(label);}}catch(e){}if(typeof window.__debug==="function"){window.__debug(source);}}var updatedArgs=args?[].concat(source).concat(args):[source];try{setAttr.apply(this,updatedArgs);if(source.uniqueId){Object.defineProperty(Window.prototype.toString,uniqueIdentifier,{value:flag,enumerable:false,writable:false,configurable:false});}}catch(e){console.log(e);}}function setConstant(source,args){var flag="done";var uniqueIdentifier=source.uniqueId+source.name+"_"+(Array.isArray(args)?args.join("_"):"");if(source.uniqueId){if(Window.prototype.toString[uniqueIdentifier]===flag){return;}}function setConstant(source,property,value){var stack=arguments.length>3&&arguments[3]!==undefined?arguments[3]:"";var valueWrapper=arguments.length>4&&arguments[4]!==undefined?arguments[4]:"";var setProxyTrap=arguments.length>5&&arguments[5]!==undefined?arguments[5]:false;var uboAliases=["set-constant.js","ubo-set-constant.js","set.js","ubo-set.js","ubo-set-constant","ubo-set"];if(uboAliases.includes(source.name)){if(stack.length!==1&&!getNumberFromString(stack)){valueWrapper=stack;}stack=undefined;}if(!property||!matchStackTrace(stack,new Error().stack)){return;}var isProxyTrapSet=false;var emptyArr=noopArray();var emptyObj=noopObject();var constantValue;if(value==="undefined"){constantValue=undefined;}else if(value==="false"){constantValue=false;}else if(value==="true"){constantValue=true;}else if(value==="null"){constantValue=null;}else if(value==="emptyArr"){constantValue=emptyArr;}else if(value==="emptyObj"){constantValue=emptyObj;}else if(value==="noopFunc"){constantValue=noopFunc;}else if(value==="noopCallbackFunc"){constantValue=noopCallbackFunc;}else if(value==="trueFunc"){constantValue=trueFunc;}else if(value==="falseFunc"){constantValue=falseFunc;}else if(value==="throwFunc"){constantValue=throwFunc;}else if(value==="noopPromiseResolve"){constantValue=noopPromiseResolve;}else if(value==="noopPromiseReject"){constantValue=noopPromiseReject;}else if(/^\d+$/.test(value)){constantValue=parseFloat(value);if(nativeIsNaN(constantValue)){return;}if(Math.abs(constantValue)>32767){return;}}else if(value==="-1"){constantValue=-1;}else if(value===""){constantValue="";}else if(value==="yes"){constantValue="yes";}else if(value==="no"){constantValue="no";}else {return;}var valueWrapperNames=["asFunction","asCallback","asResolved","asRejected"];if(valueWrapperNames.includes(valueWrapper)){var valueWrappersMap={asFunction(v){return function(){return v;};},asCallback(v){return function(){return function(){return v;};};},asResolved(v){return Promise.resolve(v);},asRejected(v){return Promise.reject(v);}};constantValue=valueWrappersMap[valueWrapper](constantValue);}var canceled=false;var mustCancel=function mustCancel(value){if(canceled){return canceled;}canceled=value!==undefined&&constantValue!==undefined&&typeof value!==typeof constantValue&&value!==null;return canceled;};var trapProp=function trapProp(base,prop,configurable,handler){if(!handler.init(base[prop])){return false;}var origDescriptor=Object.getOwnPropertyDescriptor(base,prop);var prevSetter;if(origDescriptor instanceof Object){if(!origDescriptor.configurable){var message="Property '".concat(prop,"' is not configurable");logMessage(source,message);return false;}if(base[prop]){base[prop]=constantValue;}if(origDescriptor.set instanceof Function){prevSetter=origDescriptor.set;}}Object.defineProperty(base,prop,{configurable:configurable,get(){return handler.get();},set(a){if(prevSetter!==undefined){prevSetter(a);}if(a instanceof Object){var propertiesToCheck=property.split(".").slice(1);if(setProxyTrap&&!isProxyTrapSet){isProxyTrapSet=true;a=new Proxy(a,{get:function get(target,propertyKey,val){propertiesToCheck.reduce(function(object,currentProp,index,array){var currentObj=object===null||object===void 0?void 0:object[currentProp];if(index===array.length-1&&currentObj!==constantValue){object[currentProp]=constantValue;}return currentObj||object;},target);return Reflect.get(target,propertyKey,val);}});}}handler.set(a);}});return true;};var setChainPropAccess=function setChainPropAccess(owner,property){var chainInfo=getPropertyInChain(owner,property);var base=chainInfo.base;var prop=chainInfo.prop,chain=chainInfo.chain;var inChainPropHandler={factValue:undefined,init(a){this.factValue=a;return true;},get(){return this.factValue;},set(a){if(this.factValue===a){return;}this.factValue=a;if(a instanceof Object){setChainPropAccess(a,chain);}}};var endPropHandler={init(a){if(mustCancel(a)){return false;}return true;},get(){return constantValue;},set(a){if(!mustCancel(a)){return;}constantValue=a;}};if(!chain){var isTrapped=trapProp(base,prop,false,endPropHandler);if(isTrapped){hit(source);}return;}if(base!==undefined&&base[prop]===null){trapProp(base,prop,true,inChainPropHandler);return;}if((base instanceof Object||typeof base==="object")&&isEmptyObject(base)){trapProp(base,prop,true,inChainPropHandler);}var propValue=owner[prop];if(propValue instanceof Object||typeof propValue==="object"&&propValue!==null){setChainPropAccess(propValue,chain);}trapProp(base,prop,true,inChainPropHandler);};setChainPropAccess(window,property);}function hit(source){var ADGUARD_PREFIX="[AdGuard]";if(!source.verbose){return;}try{var trace=console.trace.bind(console);var label="".concat(ADGUARD_PREFIX," ");if(source.engine==="corelibs"){label+=source.ruleText;}else {if(source.domainName){label+="".concat(source.domainName);}if(source.args){label+="#%#//scriptlet('".concat(source.name,"', '").concat(source.args.join("', '"),"')");}else {label+="#%#//scriptlet('".concat(source.name,"')");}}if(trace){trace(label);}}catch(e){}if(typeof window.__debug==="function"){window.__debug(source);}}function logMessage(source,message){var forced=arguments.length>2&&arguments[2]!==undefined?arguments[2]:false;var convertMessageToString=arguments.length>3&&arguments[3]!==undefined?arguments[3]:true;var name=source.name,verbose=source.verbose;if(!forced&&!verbose){return;}var nativeConsole=console.log;if(!convertMessageToString){nativeConsole("".concat(name,":"),message);return;}nativeConsole("".concat(name,": ").concat(message));}function getNumberFromString(rawString){var parsedDelay=parseInt(rawString,10);var validDelay=nativeIsNaN(parsedDelay)?null:parsedDelay;return validDelay;}function noopArray(){return [];}function noopObject(){return {};}function noopFunc(){}function noopCallbackFunc(){return noopFunc;}function trueFunc(){return true;}function falseFunc(){return false;}function throwFunc(){throw new Error();}function noopPromiseReject(){return Promise.reject();}function noopPromiseResolve(){var responseBody=arguments.length>0&&arguments[0]!==undefined?arguments[0]:"{}";var responseUrl=arguments.length>1&&arguments[1]!==undefined?arguments[1]:"";var responseType=arguments.length>2&&arguments[2]!==undefined?arguments[2]:"basic";if(typeof Response==="undefined"){return;}var response=new Response(responseBody,{status:200,statusText:"OK"});if(responseType==="opaque"){Object.defineProperties(response,{body:{value:null},status:{value:0},statusText:{value:""},url:{value:""},type:{value:responseType}});}else {Object.defineProperties(response,{url:{value:responseUrl},type:{value:responseType}});}return Promise.resolve(response);}function getPropertyInChain(base,chain){var pos=chain.indexOf(".");if(pos===-1){return {base:base,prop:chain};}var prop=chain.slice(0,pos);if(base===null){return {base:base,prop:prop,chain:chain};}var nextBase=base[prop];chain=chain.slice(pos+1);if((base instanceof Object||typeof base==="object")&&isEmptyObject(base)){return {base:base,prop:prop,chain:chain};}if(nextBase===null){return {base:base,prop:prop,chain:chain};}if(nextBase!==undefined){return getPropertyInChain(nextBase,chain);}Object.defineProperty(base,prop,{configurable:true});return {base:base,prop:prop,chain:chain};}function matchStackTrace(stackMatch,stackTrace){if(!stackMatch||stackMatch===""){return true;}var regExpValues=backupRegExpValues();if(shouldAbortInlineOrInjectedScript(stackMatch,stackTrace)){if(regExpValues.length&&regExpValues[0]!==RegExp.$1){restoreRegExpValues(regExpValues);}return true;}var stackRegexp=toRegExp(stackMatch);var refinedStackTrace=stackTrace.split("\n").slice(2).map(function(line){return line.trim();}).join("\n");if(regExpValues.length&&regExpValues[0]!==RegExp.$1){restoreRegExpValues(regExpValues);}return getNativeRegexpTest().call(stackRegexp,refinedStackTrace);}function nativeIsNaN(num){var native=Number.isNaN||window.isNaN;return native(num);}function isEmptyObject(obj){return Object.keys(obj).length===0&&!obj.prototype;}function shouldAbortInlineOrInjectedScript(stackMatch,stackTrace){var INLINE_SCRIPT_STRING="inlineScript";var INJECTED_SCRIPT_STRING="injectedScript";var INJECTED_SCRIPT_MARKER="<anonymous>";var isInlineScript=function isInlineScript(match){return match.includes(INLINE_SCRIPT_STRING);};var isInjectedScript=function isInjectedScript(match){return match.includes(INJECTED_SCRIPT_STRING);};if(!(isInlineScript(stackMatch)||isInjectedScript(stackMatch))){return false;}var documentURL=window.location.href;var pos=documentURL.indexOf("#");if(pos!==-1){documentURL=documentURL.slice(0,pos);}var stackSteps=stackTrace.split("\n").slice(2).map(function(line){return line.trim();});var stackLines=stackSteps.map(function(line){var stack;var getStackTraceValues=/(.*?@)?(\S+)(:\d+)(:\d+)\)?$/.exec(line);if(getStackTraceValues){var _stackURL,_stackURL2;var stackURL=getStackTraceValues[2];var stackLine=getStackTraceValues[3];var stackCol=getStackTraceValues[4];if((_stackURL=stackURL)!==null&&_stackURL!==void 0&&_stackURL.startsWith("(")){stackURL=stackURL.slice(1);}if((_stackURL2=stackURL)!==null&&_stackURL2!==void 0&&_stackURL2.startsWith(INJECTED_SCRIPT_MARKER)){var _stackFunction;stackURL=INJECTED_SCRIPT_STRING;var stackFunction=getStackTraceValues[1]!==undefined?getStackTraceValues[1].slice(0,-1):line.slice(0,getStackTraceValues.index).trim();if((_stackFunction=stackFunction)!==null&&_stackFunction!==void 0&&_stackFunction.startsWith("at")){stackFunction=stackFunction.slice(2).trim();}stack="".concat(stackFunction," ").concat(stackURL).concat(stackLine).concat(stackCol).trim();}else if(stackURL===documentURL){stack="".concat(INLINE_SCRIPT_STRING).concat(stackLine).concat(stackCol).trim();}else {stack="".concat(stackURL).concat(stackLine).concat(stackCol).trim();}}else {stack=line;}return stack;});if(stackLines){for(var index=0;index<stackLines.length;index+=1){if(isInlineScript(stackMatch)&&stackLines[index].startsWith(INLINE_SCRIPT_STRING)&&stackLines[index].match(toRegExp(stackMatch))){return true;}if(isInjectedScript(stackMatch)&&stackLines[index].startsWith(INJECTED_SCRIPT_STRING)&&stackLines[index].match(toRegExp(stackMatch))){return true;}}}return false;}function getNativeRegexpTest(){var descriptor=Object.getOwnPropertyDescriptor(RegExp.prototype,"test");var nativeRegexTest=descriptor===null||descriptor===void 0?void 0:descriptor.value;if(descriptor&&typeof descriptor.value==="function"){return nativeRegexTest;}throw new Error("RegExp.prototype.test is not a function");}function toRegExp(rawInput){var input=rawInput||"";var DEFAULT_VALUE=".?";var FORWARD_SLASH="/";if(input===""){return new RegExp(DEFAULT_VALUE);}var delimiterIndex=input.lastIndexOf(FORWARD_SLASH);var flagsPart=input.substring(delimiterIndex+1);var regExpPart=input.substring(0,delimiterIndex+1);var isValidRegExpFlag=function isValidRegExpFlag(flag){if(!flag){return false;}try{new RegExp("",flag);return true;}catch(ex){return false;}};var getRegExpFlags=function getRegExpFlags(regExpStr,flagsStr){if(regExpStr.startsWith(FORWARD_SLASH)&&regExpStr.endsWith(FORWARD_SLASH)&&!regExpStr.endsWith("\\/")&&isValidRegExpFlag(flagsStr)){return flagsStr;}return "";};var flags=getRegExpFlags(regExpPart,flagsPart);if(input.startsWith(FORWARD_SLASH)&&input.endsWith(FORWARD_SLASH)||flags){var regExpInput=flags?regExpPart:input;return new RegExp(regExpInput.slice(1,-1),flags);}var escaped=input.replace(/\\'/g,"'").replace(/\\"/g,'"').replace(/[.*+?^${}()|[\]\\]/g,"\\$&");return new RegExp(escaped);}function backupRegExpValues(){try{var arrayOfRegexpValues=[];for(var index=1;index<10;index+=1){var value="$".concat(index);if(!RegExp[value]){break;}arrayOfRegexpValues.push(RegExp[value]);}return arrayOfRegexpValues;}catch(error){return [];}}function restoreRegExpValues(array){if(!array.length){return;}try{var stringPattern="";if(array.length===1){stringPattern="(".concat(array[0],")");}else {stringPattern=array.reduce(function(accumulator,currentValue,currentIndex){if(currentIndex===1){return "(".concat(accumulator,"),(").concat(currentValue,")");}return "".concat(accumulator,",(").concat(currentValue,")");});}var regExpGroup=new RegExp(stringPattern);array.toString().replace(regExpGroup,"");}catch(error){var message="Failed to restore RegExp values: ".concat(error);console.log(message);}}var updatedArgs=args?[].concat(source).concat(args):[source];try{setConstant.apply(this,updatedArgs);if(source.uniqueId){Object.defineProperty(Window.prototype.toString,uniqueIdentifier,{value:flag,enumerable:false,writable:false,configurable:false});}}catch(e){console.log(e);}}function setCookie(source,args){var flag="done";var uniqueIdentifier=source.uniqueId+source.name+"_"+(Array.isArray(args)?args.join("_"):"");if(source.uniqueId){if(Window.prototype.toString[uniqueIdentifier]===flag){return;}}function setCookie(source,name,value){var path=arguments.length>3&&arguments[3]!==undefined?arguments[3]:"/";var domain=arguments.length>4&&arguments[4]!==undefined?arguments[4]:"";var validValue=getLimitedCookieValue(value);if(validValue===null){logMessage(source,"Invalid cookie value: '".concat(validValue,"'"));return;}if(!isValidCookiePath(path)){logMessage(source,"Invalid cookie path: '".concat(path,"'"));return;}if(!document.location.origin.includes(domain)){logMessage(source,"Cookie domain not matched by origin: '".concat(domain,"'"));return;}var cookieToSet=serializeCookie(name,validValue,path,domain);if(!cookieToSet){logMessage(source,"Invalid cookie name or value");return;}hit(source);document.cookie=cookieToSet;}function hit(source){var ADGUARD_PREFIX="[AdGuard]";if(!source.verbose){return;}try{var trace=console.trace.bind(console);var label="".concat(ADGUARD_PREFIX," ");if(source.engine==="corelibs"){label+=source.ruleText;}else {if(source.domainName){label+="".concat(source.domainName);}if(source.args){label+="#%#//scriptlet('".concat(source.name,"', '").concat(source.args.join("', '"),"')");}else {label+="#%#//scriptlet('".concat(source.name,"')");}}if(trace){trace(label);}}catch(e){}if(typeof window.__debug==="function"){window.__debug(source);}}function logMessage(source,message){var forced=arguments.length>2&&arguments[2]!==undefined?arguments[2]:false;var convertMessageToString=arguments.length>3&&arguments[3]!==undefined?arguments[3]:true;var name=source.name,verbose=source.verbose;if(!forced&&!verbose){return;}var nativeConsole=console.log;if(!convertMessageToString){nativeConsole("".concat(name,":"),message);return;}nativeConsole("".concat(name,": ").concat(message));}function nativeIsNaN(num){var native=Number.isNaN||window.isNaN;return native(num);}function getLimitedCookieValue(value){if(!value){return null;}var allowedCookieValues=new Set(["true","t","false","f","yes","y","no","n","ok","on","off","accept","accepted","notaccepted","reject","rejected","allow","allowed","disallow","deny","enable","enabled","disable","disabled","necessary","required","hide","hidden","essential","nonessential","checked","unchecked"]);var validValue;if(allowedCookieValues.has(value.toLowerCase())){validValue=value;}else if(/^\d+$/.test(value)){validValue=parseFloat(value);if(nativeIsNaN(validValue)){return null;}if(Math.abs(validValue)<0||Math.abs(validValue)>32767){return null;}}else {return null;}return validValue;}function serializeCookie(name,rawValue,rawPath){var domainValue=arguments.length>3&&arguments[3]!==undefined?arguments[3]:"";var shouldEncodeValue=arguments.length>4&&arguments[4]!==undefined?arguments[4]:true;var HOST_PREFIX="__Host-";var SECURE_PREFIX="__Secure-";var COOKIE_BREAKER=";";if(!shouldEncodeValue&&"".concat(rawValue).includes(COOKIE_BREAKER)||name.includes(COOKIE_BREAKER)){return null;}var value=shouldEncodeValue?encodeURIComponent(rawValue):rawValue;var resultCookie="".concat(name,"=").concat(value);if(name.startsWith(HOST_PREFIX)){resultCookie+="; path=/; secure";if(domainValue){console.debug('Domain value: "'.concat(domainValue,'" has been ignored, because is not allowed for __Host- prefixed cookies'));}return resultCookie;}var path=getCookiePath(rawPath);if(path){resultCookie+="; ".concat(path);}if(name.startsWith(SECURE_PREFIX)){resultCookie+="; secure";}if(domainValue){resultCookie+="; domain=".concat(domainValue);}return resultCookie;}function isValidCookiePath(rawPath){return rawPath==="/"||rawPath==="none";}function getCookiePath(rawPath){if(rawPath==="/"){return "path=/";}return "";}var updatedArgs=args?[].concat(source).concat(args):[source];try{setCookie.apply(this,updatedArgs);if(source.uniqueId){Object.defineProperty(Window.prototype.toString,uniqueIdentifier,{value:flag,enumerable:false,writable:false,configurable:false});}}catch(e){console.log(e);}}function setCookieReload(source,args){var flag="done";var uniqueIdentifier=source.uniqueId+source.name+"_"+(Array.isArray(args)?args.join("_"):"");if(source.uniqueId){if(Window.prototype.toString[uniqueIdentifier]===flag){return;}}function setCookieReload(source,name,value){var path=arguments.length>3&&arguments[3]!==undefined?arguments[3]:"/";var domain=arguments.length>4&&arguments[4]!==undefined?arguments[4]:"";if(isCookieSetWithValue(document.cookie,name,value)){return;}var validValue=getLimitedCookieValue(value);if(validValue===null){logMessage(source,"Invalid cookie value: '".concat(value,"'"));return;}if(!isValidCookiePath(path)){logMessage(source,"Invalid cookie path: '".concat(path,"'"));return;}if(!document.location.origin.includes(domain)){logMessage(source,"Cookie domain not matched by origin: '".concat(domain,"'"));return;}var cookieToSet=serializeCookie(name,validValue,path,domain);if(!cookieToSet){logMessage(source,"Invalid cookie name or value");return;}document.cookie=cookieToSet;hit(source);if(isCookieSetWithValue(document.cookie,name,value)){window.location.reload();}}function hit(source){var ADGUARD_PREFIX="[AdGuard]";if(!source.verbose){return;}try{var trace=console.trace.bind(console);var label="".concat(ADGUARD_PREFIX," ");if(source.engine==="corelibs"){label+=source.ruleText;}else {if(source.domainName){label+="".concat(source.domainName);}if(source.args){label+="#%#//scriptlet('".concat(source.name,"', '").concat(source.args.join("', '"),"')");}else {label+="#%#//scriptlet('".concat(source.name,"')");}}if(trace){trace(label);}}catch(e){}if(typeof window.__debug==="function"){window.__debug(source);}}function logMessage(source,message){var forced=arguments.length>2&&arguments[2]!==undefined?arguments[2]:false;var convertMessageToString=arguments.length>3&&arguments[3]!==undefined?arguments[3]:true;var name=source.name,verbose=source.verbose;if(!forced&&!verbose){return;}var nativeConsole=console.log;if(!convertMessageToString){nativeConsole("".concat(name,":"),message);return;}nativeConsole("".concat(name,": ").concat(message));}function nativeIsNaN(num){var native=Number.isNaN||window.isNaN;return native(num);}function isCookieSetWithValue(cookieString,name,value){return cookieString.split(";").some(function(cookieStr){var pos=cookieStr.indexOf("=");if(pos===-1){return false;}var cookieName=cookieStr.slice(0,pos).trim();var cookieValue=cookieStr.slice(pos+1).trim();return name===cookieName&&value===cookieValue;});}function getLimitedCookieValue(value){if(!value){return null;}var allowedCookieValues=new Set(["true","t","false","f","yes","y","no","n","ok","on","off","accept","accepted","notaccepted","reject","rejected","allow","allowed","disallow","deny","enable","enabled","disable","disabled","necessary","required","hide","hidden","essential","nonessential","checked","unchecked"]);var validValue;if(allowedCookieValues.has(value.toLowerCase())){validValue=value;}else if(/^\d+$/.test(value)){validValue=parseFloat(value);if(nativeIsNaN(validValue)){return null;}if(Math.abs(validValue)<0||Math.abs(validValue)>32767){return null;}}else {return null;}return validValue;}function serializeCookie(name,rawValue,rawPath){var domainValue=arguments.length>3&&arguments[3]!==undefined?arguments[3]:"";var shouldEncodeValue=arguments.length>4&&arguments[4]!==undefined?arguments[4]:true;var HOST_PREFIX="__Host-";var SECURE_PREFIX="__Secure-";var COOKIE_BREAKER=";";if(!shouldEncodeValue&&"".concat(rawValue).includes(COOKIE_BREAKER)||name.includes(COOKIE_BREAKER)){return null;}var value=shouldEncodeValue?encodeURIComponent(rawValue):rawValue;var resultCookie="".concat(name,"=").concat(value);if(name.startsWith(HOST_PREFIX)){resultCookie+="; path=/; secure";if(domainValue){console.debug('Domain value: "'.concat(domainValue,'" has been ignored, because is not allowed for __Host- prefixed cookies'));}return resultCookie;}var path=getCookiePath(rawPath);if(path){resultCookie+="; ".concat(path);}if(name.startsWith(SECURE_PREFIX)){resultCookie+="; secure";}if(domainValue){resultCookie+="; domain=".concat(domainValue);}return resultCookie;}function isValidCookiePath(rawPath){return rawPath==="/"||rawPath==="none";}function getCookiePath(rawPath){if(rawPath==="/"){return "path=/";}return "";}var updatedArgs=args?[].concat(source).concat(args):[source];try{setCookieReload.apply(this,updatedArgs);if(source.uniqueId){Object.defineProperty(Window.prototype.toString,uniqueIdentifier,{value:flag,enumerable:false,writable:false,configurable:false});}}catch(e){console.log(e);}}function setLocalStorageItem(source,args){var flag="done";var uniqueIdentifier=source.uniqueId+source.name+"_"+(Array.isArray(args)?args.join("_"):"");if(source.uniqueId){if(Window.prototype.toString[uniqueIdentifier]===flag){return;}}function setLocalStorageItem(source,key,value){if(typeof key==="undefined"){logMessage(source,"Item key should be specified.");return;}var validValue;try{validValue=getLimitedStorageItemValue(value);}catch(_unused){logMessage(source,"Invalid storage item value: '".concat(value,"'"));return;}var _window=window,localStorage=_window.localStorage;if(validValue==="$remove$"){removeStorageItem(source,localStorage,key);}else {setStorageItem(source,localStorage,key,validValue);}hit(source);}function hit(source){var ADGUARD_PREFIX="[AdGuard]";if(!source.verbose){return;}try{var trace=console.trace.bind(console);var label="".concat(ADGUARD_PREFIX," ");if(source.engine==="corelibs"){label+=source.ruleText;}else {if(source.domainName){label+="".concat(source.domainName);}if(source.args){label+="#%#//scriptlet('".concat(source.name,"', '").concat(source.args.join("', '"),"')");}else {label+="#%#//scriptlet('".concat(source.name,"')");}}if(trace){trace(label);}}catch(e){}if(typeof window.__debug==="function"){window.__debug(source);}}function logMessage(source,message){var forced=arguments.length>2&&arguments[2]!==undefined?arguments[2]:false;var convertMessageToString=arguments.length>3&&arguments[3]!==undefined?arguments[3]:true;var name=source.name,verbose=source.verbose;if(!forced&&!verbose){return;}var nativeConsole=console.log;if(!convertMessageToString){nativeConsole("".concat(name,":"),message);return;}nativeConsole("".concat(name,": ").concat(message));}function nativeIsNaN(num){var native=Number.isNaN||window.isNaN;return native(num);}function setStorageItem(source,storage,key,value){try{storage.setItem(key,value);}catch(e){var message="Unable to set sessionStorage item due to: ".concat(e.message);logMessage(source,message);}}function removeStorageItem(source,storage,key){try{if(key.startsWith("/")&&(key.endsWith("/")||key.endsWith("/i"))&&isValidStrPattern(key)){var regExpKey=toRegExp(key);var storageKeys=Object.keys(storage);storageKeys.forEach(function(storageKey){if(regExpKey.test(storageKey)){storage.removeItem(storageKey);}});}else {storage.removeItem(key);}}catch(e){var message="Unable to remove storage item due to: ".concat(e.message);logMessage(source,message);}}function getLimitedStorageItemValue(value){if(typeof value!=="string"){throw new Error("Invalid value");}var allowedStorageValues=new Set(["undefined","false","true","null","","yes","no","on","off","accept","accepted","reject","rejected","allowed","denied"]);var validValue;if(allowedStorageValues.has(value.toLowerCase())){validValue=value;}else if(value==="emptyArr"){validValue="[]";}else if(value==="emptyObj"){validValue="{}";}else if(/^\d+$/.test(value)){validValue=parseFloat(value);if(nativeIsNaN(validValue)){throw new Error("Invalid value");}if(Math.abs(validValue)>32767){throw new Error("Invalid value");}}else if(value==="$remove$"){validValue="$remove$";}else {throw new Error("Invalid value");}return validValue;}function isValidStrPattern(input){var FORWARD_SLASH="/";var str=escapeRegExp(input);if(input[0]===FORWARD_SLASH&&input[input.length-1]===FORWARD_SLASH){str=input.slice(1,-1);}var isValid;try{isValid=new RegExp(str);isValid=true;}catch(e){isValid=false;}return isValid;}function toRegExp(rawInput){var input=rawInput||"";var DEFAULT_VALUE=".?";var FORWARD_SLASH="/";if(input===""){return new RegExp(DEFAULT_VALUE);}var delimiterIndex=input.lastIndexOf(FORWARD_SLASH);var flagsPart=input.substring(delimiterIndex+1);var regExpPart=input.substring(0,delimiterIndex+1);var isValidRegExpFlag=function isValidRegExpFlag(flag){if(!flag){return false;}try{new RegExp("",flag);return true;}catch(ex){return false;}};var getRegExpFlags=function getRegExpFlags(regExpStr,flagsStr){if(regExpStr.startsWith(FORWARD_SLASH)&&regExpStr.endsWith(FORWARD_SLASH)&&!regExpStr.endsWith("\\/")&&isValidRegExpFlag(flagsStr)){return flagsStr;}return "";};var flags=getRegExpFlags(regExpPart,flagsPart);if(input.startsWith(FORWARD_SLASH)&&input.endsWith(FORWARD_SLASH)||flags){var regExpInput=flags?regExpPart:input;return new RegExp(regExpInput.slice(1,-1),flags);}var escaped=input.replace(/\\'/g,"'").replace(/\\"/g,'"').replace(/[.*+?^${}()|[\]\\]/g,"\\$&");return new RegExp(escaped);}function escapeRegExp(str){return str.replace(/[.*+?^${}()|[\]\\]/g,"\\$&");}var updatedArgs=args?[].concat(source).concat(args):[source];try{setLocalStorageItem.apply(this,updatedArgs);if(source.uniqueId){Object.defineProperty(Window.prototype.toString,uniqueIdentifier,{value:flag,enumerable:false,writable:false,configurable:false});}}catch(e){console.log(e);}}function setPopadsDummy(source,args){var flag="done";var uniqueIdentifier=source.uniqueId+source.name+"_"+(Array.isArray(args)?args.join("_"):"");if(source.uniqueId){if(Window.prototype.toString[uniqueIdentifier]===flag){return;}}function setPopadsDummy(source){delete window.PopAds;delete window.popns;Object.defineProperties(window,{PopAds:{get:function get(){hit(source);return {};}},popns:{get:function get(){hit(source);return {};}}});}function hit(source){var ADGUARD_PREFIX="[AdGuard]";if(!source.verbose){return;}try{var trace=console.trace.bind(console);var label="".concat(ADGUARD_PREFIX," ");if(source.engine==="corelibs"){label+=source.ruleText;}else {if(source.domainName){label+="".concat(source.domainName);}if(source.args){label+="#%#//scriptlet('".concat(source.name,"', '").concat(source.args.join("', '"),"')");}else {label+="#%#//scriptlet('".concat(source.name,"')");}}if(trace){trace(label);}}catch(e){}if(typeof window.__debug==="function"){window.__debug(source);}}var updatedArgs=args?[].concat(source).concat(args):[source];try{setPopadsDummy.apply(this,updatedArgs);if(source.uniqueId){Object.defineProperty(Window.prototype.toString,uniqueIdentifier,{value:flag,enumerable:false,writable:false,configurable:false});}}catch(e){console.log(e);}}function setSessionStorageItem(source,args){var flag="done";var uniqueIdentifier=source.uniqueId+source.name+"_"+(Array.isArray(args)?args.join("_"):"");if(source.uniqueId){if(Window.prototype.toString[uniqueIdentifier]===flag){return;}}function setSessionStorageItem(source,key,value){if(typeof key==="undefined"){logMessage(source,"Item key should be specified.");return;}var validValue;try{validValue=getLimitedStorageItemValue(value);}catch(_unused){logMessage(source,"Invalid storage item value: '".concat(value,"'"));return;}var _window=window,sessionStorage=_window.sessionStorage;if(validValue==="$remove$"){removeStorageItem(source,sessionStorage,key);}else {setStorageItem(source,sessionStorage,key,validValue);}hit(source);}function hit(source){var ADGUARD_PREFIX="[AdGuard]";if(!source.verbose){return;}try{var trace=console.trace.bind(console);var label="".concat(ADGUARD_PREFIX," ");if(source.engine==="corelibs"){label+=source.ruleText;}else {if(source.domainName){label+="".concat(source.domainName);}if(source.args){label+="#%#//scriptlet('".concat(source.name,"', '").concat(source.args.join("', '"),"')");}else {label+="#%#//scriptlet('".concat(source.name,"')");}}if(trace){trace(label);}}catch(e){}if(typeof window.__debug==="function"){window.__debug(source);}}function logMessage(source,message){var forced=arguments.length>2&&arguments[2]!==undefined?arguments[2]:false;var convertMessageToString=arguments.length>3&&arguments[3]!==undefined?arguments[3]:true;var name=source.name,verbose=source.verbose;if(!forced&&!verbose){return;}var nativeConsole=console.log;if(!convertMessageToString){nativeConsole("".concat(name,":"),message);return;}nativeConsole("".concat(name,": ").concat(message));}function nativeIsNaN(num){var native=Number.isNaN||window.isNaN;return native(num);}function setStorageItem(source,storage,key,value){try{storage.setItem(key,value);}catch(e){var message="Unable to set sessionStorage item due to: ".concat(e.message);logMessage(source,message);}}function removeStorageItem(source,storage,key){try{if(key.startsWith("/")&&(key.endsWith("/")||key.endsWith("/i"))&&isValidStrPattern(key)){var regExpKey=toRegExp(key);var storageKeys=Object.keys(storage);storageKeys.forEach(function(storageKey){if(regExpKey.test(storageKey)){storage.removeItem(storageKey);}});}else {storage.removeItem(key);}}catch(e){var message="Unable to remove storage item due to: ".concat(e.message);logMessage(source,message);}}function getLimitedStorageItemValue(value){if(typeof value!=="string"){throw new Error("Invalid value");}var allowedStorageValues=new Set(["undefined","false","true","null","","yes","no","on","off","accept","accepted","reject","rejected","allowed","denied"]);var validValue;if(allowedStorageValues.has(value.toLowerCase())){validValue=value;}else if(value==="emptyArr"){validValue="[]";}else if(value==="emptyObj"){validValue="{}";}else if(/^\d+$/.test(value)){validValue=parseFloat(value);if(nativeIsNaN(validValue)){throw new Error("Invalid value");}if(Math.abs(validValue)>32767){throw new Error("Invalid value");}}else if(value==="$remove$"){validValue="$remove$";}else {throw new Error("Invalid value");}return validValue;}function isValidStrPattern(input){var FORWARD_SLASH="/";var str=escapeRegExp(input);if(input[0]===FORWARD_SLASH&&input[input.length-1]===FORWARD_SLASH){str=input.slice(1,-1);}var isValid;try{isValid=new RegExp(str);isValid=true;}catch(e){isValid=false;}return isValid;}function toRegExp(rawInput){var input=rawInput||"";var DEFAULT_VALUE=".?";var FORWARD_SLASH="/";if(input===""){return new RegExp(DEFAULT_VALUE);}var delimiterIndex=input.lastIndexOf(FORWARD_SLASH);var flagsPart=input.substring(delimiterIndex+1);var regExpPart=input.substring(0,delimiterIndex+1);var isValidRegExpFlag=function isValidRegExpFlag(flag){if(!flag){return false;}try{new RegExp("",flag);return true;}catch(ex){return false;}};var getRegExpFlags=function getRegExpFlags(regExpStr,flagsStr){if(regExpStr.startsWith(FORWARD_SLASH)&&regExpStr.endsWith(FORWARD_SLASH)&&!regExpStr.endsWith("\\/")&&isValidRegExpFlag(flagsStr)){return flagsStr;}return "";};var flags=getRegExpFlags(regExpPart,flagsPart);if(input.startsWith(FORWARD_SLASH)&&input.endsWith(FORWARD_SLASH)||flags){var regExpInput=flags?regExpPart:input;return new RegExp(regExpInput.slice(1,-1),flags);}var escaped=input.replace(/\\'/g,"'").replace(/\\"/g,'"').replace(/[.*+?^${}()|[\]\\]/g,"\\$&");return new RegExp(escaped);}function escapeRegExp(str){return str.replace(/[.*+?^${}()|[\]\\]/g,"\\$&");}var updatedArgs=args?[].concat(source).concat(args):[source];try{setSessionStorageItem.apply(this,updatedArgs);if(source.uniqueId){Object.defineProperty(Window.prototype.toString,uniqueIdentifier,{value:flag,enumerable:false,writable:false,configurable:false});}}catch(e){console.log(e);}}function spoofCSS(source,args){var flag="done";var uniqueIdentifier=source.uniqueId+source.name+"_"+(Array.isArray(args)?args.join("_"):"");if(source.uniqueId){if(Window.prototype.toString[uniqueIdentifier]===flag){return;}}function spoofCSS(source,selectors,cssPropertyName,cssPropertyValue){if(!selectors){return;}var uboAliases=["spoof-css.js","ubo-spoof-css.js","ubo-spoof-css"];function convertToCamelCase(cssProperty){if(!cssProperty.includes("-")){return cssProperty;}var splittedProperty=cssProperty.split("-");var firstPart=splittedProperty[0];var secondPart=splittedProperty[1];return "".concat(firstPart).concat(secondPart[0].toUpperCase()).concat(secondPart.slice(1));}var shouldDebug=!!(cssPropertyName==="debug"&&cssPropertyValue);var propToValueMap=new Map();if(uboAliases.includes(source.name)){var args=source.args;var arrayOfProperties=[];var isDebug=args.at(-2);if(isDebug==="debug"){arrayOfProperties=args.slice(1,-2);}else {arrayOfProperties=args.slice(1);}for(var i=0;i<arrayOfProperties.length;i+=2){if(arrayOfProperties[i]===""){break;}propToValueMap.set(convertToCamelCase(arrayOfProperties[i]),arrayOfProperties[i+1]);}}else if(cssPropertyName&&cssPropertyValue&&!shouldDebug){propToValueMap.set(convertToCamelCase(cssPropertyName),cssPropertyValue);}var spoofStyle=function spoofStyle(cssProperty,realCssValue){return propToValueMap.has(cssProperty)?propToValueMap.get(cssProperty):realCssValue;};var setRectValue=function setRectValue(rect,prop,value){Object.defineProperty(rect,prop,{value:parseFloat(value)});};var getter=function getter(target,prop,receiver){hit(source);if(prop==="toString"){return target.toString.bind(target);}return Reflect.get(target,prop,receiver);};var getComputedStyleWrapper=function getComputedStyleWrapper(target,thisArg,args){if(shouldDebug){debugger;}var style=Reflect.apply(target,thisArg,args);if(!args[0].matches(selectors)){return style;}var proxiedStyle=new Proxy(style,{get(target,prop){var CSSStyleProp=target[prop];if(typeof CSSStyleProp!=="function"){return spoofStyle(prop,CSSStyleProp||"");}if(prop!=="getPropertyValue"){return CSSStyleProp.bind(target);}var getPropertyValueFunc=new Proxy(CSSStyleProp,{apply(target,thisArg,args){var cssName=args[0];var cssValue=thisArg[cssName];return spoofStyle(cssName,cssValue);},get:getter});return getPropertyValueFunc;},getOwnPropertyDescriptor(target,prop){if(propToValueMap.has(prop)){return {configurable:true,enumerable:true,value:propToValueMap.get(prop),writable:true};}return Reflect.getOwnPropertyDescriptor(target,prop);}});hit(source);return proxiedStyle;};var getComputedStyleHandler={apply:getComputedStyleWrapper,get:getter};window.getComputedStyle=new Proxy(window.getComputedStyle,getComputedStyleHandler);var getBoundingClientRectWrapper=function getBoundingClientRectWrapper(target,thisArg,args){if(shouldDebug){debugger;}var rect=Reflect.apply(target,thisArg,args);if(!thisArg.matches(selectors)){return rect;}var top=rect.top,bottom=rect.bottom,height=rect.height,width=rect.width,left=rect.left,right=rect.right;var newDOMRect=new window.DOMRect(rect.x,rect.y,top,bottom,width,height,left,right);if(propToValueMap.has("top")){setRectValue(newDOMRect,"top",propToValueMap.get("top"));}if(propToValueMap.has("bottom")){setRectValue(newDOMRect,"bottom",propToValueMap.get("bottom"));}if(propToValueMap.has("left")){setRectValue(newDOMRect,"left",propToValueMap.get("left"));}if(propToValueMap.has("right")){setRectValue(newDOMRect,"right",propToValueMap.get("right"));}if(propToValueMap.has("height")){setRectValue(newDOMRect,"height",propToValueMap.get("height"));}if(propToValueMap.has("width")){setRectValue(newDOMRect,"width",propToValueMap.get("width"));}hit(source);return newDOMRect;};var getBoundingClientRectHandler={apply:getBoundingClientRectWrapper,get:getter};window.Element.prototype.getBoundingClientRect=new Proxy(window.Element.prototype.getBoundingClientRect,getBoundingClientRectHandler);}function hit(source){var ADGUARD_PREFIX="[AdGuard]";if(!source.verbose){return;}try{var trace=console.trace.bind(console);var label="".concat(ADGUARD_PREFIX," ");if(source.engine==="corelibs"){label+=source.ruleText;}else {if(source.domainName){label+="".concat(source.domainName);}if(source.args){label+="#%#//scriptlet('".concat(source.name,"', '").concat(source.args.join("', '"),"')");}else {label+="#%#//scriptlet('".concat(source.name,"')");}}if(trace){trace(label);}}catch(e){}if(typeof window.__debug==="function"){window.__debug(source);}}var updatedArgs=args?[].concat(source).concat(args):[source];try{spoofCSS.apply(this,updatedArgs);if(source.uniqueId){Object.defineProperty(Window.prototype.toString,uniqueIdentifier,{value:flag,enumerable:false,writable:false,configurable:false});}}catch(e){console.log(e);}}function trustedClickElement(source,args){var flag="done";var uniqueIdentifier=source.uniqueId+source.name+"_"+(Array.isArray(args)?args.join("_"):"");if(source.uniqueId){if(Window.prototype.toString[uniqueIdentifier]===flag){return;}}function trustedClickElement(source,selectors){var extraMatch=arguments.length>2&&arguments[2]!==undefined?arguments[2]:"";var delay=arguments.length>3&&arguments[3]!==undefined?arguments[3]:NaN;var reload=arguments.length>4&&arguments[4]!==undefined?arguments[4]:"";if(!selectors){return;}var SHADOW_COMBINATOR=" >>> ";var OBSERVER_TIMEOUT_MS=1e4;var THROTTLE_DELAY_MS=20;var STATIC_CLICK_DELAY_MS=150;var STATIC_RELOAD_DELAY_MS=500;var COOKIE_MATCH_MARKER="cookie:";var LOCAL_STORAGE_MATCH_MARKER="localStorage:";var TEXT_MATCH_MARKER="containsText:";var RELOAD_ON_FINAL_CLICK_MARKER="reloadAfterClick";var SELECTORS_DELIMITER=",";var COOKIE_STRING_DELIMITER=";";var COLON=":";var EXTRA_MATCH_DELIMITER=/(,\s*){1}(?=!?cookie:|!?localStorage:|containsText:)/;var sleep=function sleep(delayMs){return new Promise(function(resolve){return setTimeout(resolve,delayMs);});};if(selectors.includes(SHADOW_COMBINATOR)){var attachShadowWrapper=function attachShadowWrapper(target,thisArg,argumentsList){var _argumentsList$;var mode=(_argumentsList$=argumentsList[0])===null||_argumentsList$===void 0?void 0:_argumentsList$.mode;if(mode==="closed"){argumentsList[0].mode="open";}return Reflect.apply(target,thisArg,argumentsList);};var attachShadowHandler={apply:attachShadowWrapper};window.Element.prototype.attachShadow=new Proxy(window.Element.prototype.attachShadow,attachShadowHandler);}var parsedDelay;if(delay){parsedDelay=parseInt(String(delay),10);var isValidDelay=!Number.isNaN(parsedDelay)||parsedDelay<OBSERVER_TIMEOUT_MS;if(!isValidDelay){var message="Passed delay '".concat(delay,"' is invalid or bigger than ").concat(OBSERVER_TIMEOUT_MS," ms");logMessage(source,message);return;}}var canClick=!parsedDelay;var cookieMatches=[];var localStorageMatches=[];var textMatches="";var isInvertedMatchCookie=false;var isInvertedMatchLocalStorage=false;if(extraMatch){var parsedExtraMatch=extraMatch.split(EXTRA_MATCH_DELIMITER).map(function(matchStr){return matchStr.trim();});parsedExtraMatch.forEach(function(matchStr){if(matchStr.includes(COOKIE_MATCH_MARKER)){var _parseMatchArg=parseMatchArg(matchStr),isInvertedMatch=_parseMatchArg.isInvertedMatch,matchValue=_parseMatchArg.matchValue;isInvertedMatchCookie=isInvertedMatch;var cookieMatch=matchValue.replace(COOKIE_MATCH_MARKER,"");cookieMatches.push(cookieMatch);}if(matchStr.includes(LOCAL_STORAGE_MATCH_MARKER)){var _parseMatchArg2=parseMatchArg(matchStr),_isInvertedMatch=_parseMatchArg2.isInvertedMatch,_matchValue=_parseMatchArg2.matchValue;isInvertedMatchLocalStorage=_isInvertedMatch;var localStorageMatch=_matchValue.replace(LOCAL_STORAGE_MATCH_MARKER,"");localStorageMatches.push(localStorageMatch);}if(matchStr.includes(TEXT_MATCH_MARKER)){var _parseMatchArg3=parseMatchArg(matchStr),_matchValue2=_parseMatchArg3.matchValue;var textMatch=_matchValue2.replace(TEXT_MATCH_MARKER,"");textMatches=textMatch;}});}if(cookieMatches.length>0){var parsedCookieMatches=parseCookieString(cookieMatches.join(COOKIE_STRING_DELIMITER));var parsedCookies=parseCookieString(document.cookie);var cookieKeys=Object.keys(parsedCookies);if(cookieKeys.length===0){return;}var cookiesMatched=Object.keys(parsedCookieMatches).every(function(key){var valueMatch=parsedCookieMatches[key]?toRegExp(parsedCookieMatches[key]):null;var keyMatch=toRegExp(key);return cookieKeys.some(function(cookieKey){var keysMatched=keyMatch.test(cookieKey);if(!keysMatched){return false;}if(!valueMatch){return true;}var parsedCookieValue=parsedCookies[cookieKey];if(!parsedCookieValue){return false;}return valueMatch.test(parsedCookieValue);});});var shouldRun=cookiesMatched!==isInvertedMatchCookie;if(!shouldRun){return;}}if(localStorageMatches.length>0){var localStorageMatched=localStorageMatches.every(function(str){var itemValue=window.localStorage.getItem(str);return itemValue||itemValue==="";});var _shouldRun=localStorageMatched!==isInvertedMatchLocalStorage;if(!_shouldRun){return;}}var textMatchRegexp=textMatches?toRegExp(textMatches):null;var doesElementContainText=function doesElementContainText(element,matchRegexp){var textContent=element.textContent;if(!textContent){return false;}return matchRegexp.test(textContent);};var selectorsSequence=selectors.split(SELECTORS_DELIMITER).map(function(selector){return selector.trim();});var createElementObj=function createElementObj(element){return {element:element||null,clicked:false};};var elementsSequence=Array(selectorsSequence.length).fill(createElementObj(null));var shouldReloadAfterClick=false;var reloadDelayMs=STATIC_RELOAD_DELAY_MS;if(reload){var _reload$split=reload.split(COLON),_reload$split2=_slicedToArray(_reload$split,2),reloadMarker=_reload$split2[0],reloadValue=_reload$split2[1];if(reloadMarker!==RELOAD_ON_FINAL_CLICK_MARKER){logMessage(source,"Passed reload option '".concat(reload,"' is invalid"));return;}if(reloadValue){var passedReload=Number(reloadValue);if(Number.isNaN(passedReload)){logMessage(source,"Passed reload delay value '".concat(passedReload,"' is invalid"));return;}if(passedReload>OBSERVER_TIMEOUT_MS){logMessage(source,"Passed reload delay value '".concat(passedReload,"' is bigger than maximum ").concat(OBSERVER_TIMEOUT_MS," ms"));return;}reloadDelayMs=passedReload;}shouldReloadAfterClick=true;}var canReload=true;var clickElementsBySequence=async function clickElementsBySequence(){for(var i=0;i<elementsSequence.length;i+=1){var elementObj=elementsSequence[i];if(i>=1){await sleep(STATIC_CLICK_DELAY_MS);}if(!elementObj.element){break;}if(!elementObj.clicked){if(textMatchRegexp&&!doesElementContainText(elementObj.element,textMatchRegexp)){continue;}elementObj.element.click();elementObj.clicked=true;}}var allElementsClicked=elementsSequence.every(function(elementObj){return elementObj.clicked===true;});if(allElementsClicked){if(shouldReloadAfterClick&&canReload){canReload=false;setTimeout(function(){window.location.reload();},reloadDelayMs);}hit(source);}};var handleElement=function handleElement(element,i){var elementObj=createElementObj(element);elementsSequence[i]=elementObj;if(canClick){clickElementsBySequence();}};var fulfillAndHandleSelectors=function fulfillAndHandleSelectors(){var fulfilledSelectors=[];selectorsSequence.forEach(function(selector,i){if(!selector){return;}var element=queryShadowSelector(selector);if(!element){return;}handleElement(element,i);fulfilledSelectors.push(selector);});selectorsSequence=selectorsSequence.map(function(selector){return selector&&fulfilledSelectors.includes(selector)?null:selector;});return selectorsSequence;};var findElements=function findElements(mutations,observer){selectorsSequence=fulfillAndHandleSelectors();var allSelectorsFulfilled=selectorsSequence.every(function(selector){return selector===null;});if(allSelectorsFulfilled){observer.disconnect();}};var initializeMutationObserver=function initializeMutationObserver(){var observer=new MutationObserver(throttle(findElements,THROTTLE_DELAY_MS));observer.observe(document.documentElement,{attributes:true,childList:true,subtree:true});setTimeout(function(){return observer.disconnect();},OBSERVER_TIMEOUT_MS);};var checkInitialElements=function checkInitialElements(){var foundElements=selectorsSequence.every(function(selector){if(!selector){return false;}var element=queryShadowSelector(selector);return !!element;});if(foundElements){fulfillAndHandleSelectors();}else {initializeMutationObserver();}};checkInitialElements();if(parsedDelay){setTimeout(function(){clickElementsBySequence();canClick=true;},parsedDelay);}}function hit(source){var ADGUARD_PREFIX="[AdGuard]";if(!source.verbose){return;}try{var trace=console.trace.bind(console);var label="".concat(ADGUARD_PREFIX," ");if(source.engine==="corelibs"){label+=source.ruleText;}else {if(source.domainName){label+="".concat(source.domainName);}if(source.args){label+="#%#//scriptlet('".concat(source.name,"', '").concat(source.args.join("', '"),"')");}else {label+="#%#//scriptlet('".concat(source.name,"')");}}if(trace){trace(label);}}catch(e){}if(typeof window.__debug==="function"){window.__debug(source);}}function toRegExp(rawInput){var input=rawInput||"";var DEFAULT_VALUE=".?";var FORWARD_SLASH="/";if(input===""){return new RegExp(DEFAULT_VALUE);}var delimiterIndex=input.lastIndexOf(FORWARD_SLASH);var flagsPart=input.substring(delimiterIndex+1);var regExpPart=input.substring(0,delimiterIndex+1);var isValidRegExpFlag=function isValidRegExpFlag(flag){if(!flag){return false;}try{new RegExp("",flag);return true;}catch(ex){return false;}};var getRegExpFlags=function getRegExpFlags(regExpStr,flagsStr){if(regExpStr.startsWith(FORWARD_SLASH)&&regExpStr.endsWith(FORWARD_SLASH)&&!regExpStr.endsWith("\\/")&&isValidRegExpFlag(flagsStr)){return flagsStr;}return "";};var flags=getRegExpFlags(regExpPart,flagsPart);if(input.startsWith(FORWARD_SLASH)&&input.endsWith(FORWARD_SLASH)||flags){var regExpInput=flags?regExpPart:input;return new RegExp(regExpInput.slice(1,-1),flags);}var escaped=input.replace(/\\'/g,"'").replace(/\\"/g,'"').replace(/[.*+?^${}()|[\]\\]/g,"\\$&");return new RegExp(escaped);}function parseCookieString(cookieString){var COOKIE_DELIMITER="=";var COOKIE_PAIRS_DELIMITER=";";var cookieChunks=cookieString.split(COOKIE_PAIRS_DELIMITER);var cookieData={};cookieChunks.forEach(function(singleCookie){var cookieKey;var cookieValue="";var delimiterIndex=singleCookie.indexOf(COOKIE_DELIMITER);if(delimiterIndex===-1){cookieKey=singleCookie.trim();}else {cookieKey=singleCookie.slice(0,delimiterIndex).trim();cookieValue=singleCookie.slice(delimiterIndex+1);}cookieData[cookieKey]=cookieValue||null;});return cookieData;}function throttle(cb,delay){var wait=false;var savedArgs;var wrapper=function wrapper(){for(var _len=arguments.length,args=new Array(_len),_key=0;_key<_len;_key++){args[_key]=arguments[_key];}if(wait){savedArgs=args;return;}cb(...args);wait=true;setTimeout(function(){wait=false;if(savedArgs){wrapper(...savedArgs);savedArgs=null;}},delay);};return wrapper;}function logMessage(source,message){var forced=arguments.length>2&&arguments[2]!==undefined?arguments[2]:false;var convertMessageToString=arguments.length>3&&arguments[3]!==undefined?arguments[3]:true;var name=source.name,verbose=source.verbose;if(!forced&&!verbose){return;}var nativeConsole=console.log;if(!convertMessageToString){nativeConsole("".concat(name,":"),message);return;}nativeConsole("".concat(name,": ").concat(message));}function parseMatchArg(match){var INVERT_MARKER="!";var isInvertedMatch=match?match===null||match===void 0?void 0:match.startsWith(INVERT_MARKER):false;var matchValue=isInvertedMatch?match.slice(1):match;var matchRegexp=toRegExp(matchValue);return {isInvertedMatch:isInvertedMatch,matchRegexp:matchRegexp,matchValue:matchValue};}function queryShadowSelector(selector){var context=arguments.length>1&&arguments[1]!==undefined?arguments[1]:document.documentElement;var SHADOW_COMBINATOR=" >>> ";var pos=selector.indexOf(SHADOW_COMBINATOR);if(pos===-1){return context.querySelector(selector);}var shadowHostSelector=selector.slice(0,pos).trim();var elem=context.querySelector(shadowHostSelector);if(!elem||!elem.shadowRoot){return null;}var shadowRootSelector=selector.slice(pos+SHADOW_COMBINATOR.length).trim();return queryShadowSelector(shadowRootSelector,elem.shadowRoot);}var updatedArgs=args?[].concat(source).concat(args):[source];try{trustedClickElement.apply(this,updatedArgs);if(source.uniqueId){Object.defineProperty(Window.prototype.toString,uniqueIdentifier,{value:flag,enumerable:false,writable:false,configurable:false});}}catch(e){console.log(e);}}function trustedCreateElement(source,args){var flag="done";var uniqueIdentifier=source.uniqueId+source.name+"_"+(Array.isArray(args)?args.join("_"):"");if(source.uniqueId){if(Window.prototype.toString[uniqueIdentifier]===flag){return;}}function trustedCreateElement(source,parentSelector,tagName){var attributePairs=arguments.length>3&&arguments[3]!==undefined?arguments[3]:"";var textContent=arguments.length>4&&arguments[4]!==undefined?arguments[4]:"";var cleanupDelayMs=arguments.length>5&&arguments[5]!==undefined?arguments[5]:NaN;if(!parentSelector||!tagName){return;}var IFRAME_WINDOW_NAME="trusted-create-element-window";if(window.name===IFRAME_WINDOW_NAME){return;}var logError=function logError(prefix,error){logMessage(source,"".concat(prefix," due to ").concat(getErrorMessage(error)));};var element;try{element=document.createElement(tagName);element.textContent=textContent;}catch(e){logError("Cannot create element with tag name '".concat(tagName,"'"),e);return;}var attributes=[];try{attributes=parseAttributePairs(attributePairs);}catch(e){logError("Cannot parse attributePairs param: '".concat(attributePairs,"'"),e);return;}attributes.forEach(function(attr){try{element.setAttribute(attr.name,attr.value);}catch(e){logError("Cannot set attribute '".concat(attr.name,"' with value '").concat(attr.value,"'"),e);}});var timerId;var elementCreated=false;var elementRemoved=false;var findParentAndAppendEl=function findParentAndAppendEl(parentElSelector,el,removeElDelayMs){var parentEl;try{parentEl=document.querySelector(parentElSelector);}catch(e){logError("Cannot find parent element by selector '".concat(parentElSelector,"'"),e);return false;}if(!parentEl){logMessage(source,"No parent element found by selector: '".concat(parentElSelector,"'"));return false;}try{if(!parentEl.contains(el)){parentEl.append(el);}if(el instanceof HTMLIFrameElement&&el.contentWindow){el.contentWindow.name=IFRAME_WINDOW_NAME;}elementCreated=true;hit(source);}catch(e){logError("Cannot append child to parent by selector '".concat(parentElSelector,"'"),e);return false;}if(!nativeIsNaN(removeElDelayMs)){timerId=setTimeout(function(){el.remove();elementRemoved=true;clearTimeout(timerId);},removeElDelayMs);}return true;};if(!findParentAndAppendEl(parentSelector,element,cleanupDelayMs)){observeDocumentWithTimeout(function(mutations,observer){if(elementRemoved||elementCreated||findParentAndAppendEl(parentSelector,element,cleanupDelayMs)){observer.disconnect();}});}}function hit(source){var ADGUARD_PREFIX="[AdGuard]";if(!source.verbose){return;}try{var trace=console.trace.bind(console);var label="".concat(ADGUARD_PREFIX," ");if(source.engine==="corelibs"){label+=source.ruleText;}else {if(source.domainName){label+="".concat(source.domainName);}if(source.args){label+="#%#//scriptlet('".concat(source.name,"', '").concat(source.args.join("', '"),"')");}else {label+="#%#//scriptlet('".concat(source.name,"')");}}if(trace){trace(label);}}catch(e){}if(typeof window.__debug==="function"){window.__debug(source);}}function logMessage(source,message){var forced=arguments.length>2&&arguments[2]!==undefined?arguments[2]:false;var convertMessageToString=arguments.length>3&&arguments[3]!==undefined?arguments[3]:true;var name=source.name,verbose=source.verbose;if(!forced&&!verbose){return;}var nativeConsole=console.log;if(!convertMessageToString){nativeConsole("".concat(name,":"),message);return;}nativeConsole("".concat(name,": ").concat(message));}function observeDocumentWithTimeout(callback){var options=arguments.length>1&&arguments[1]!==undefined?arguments[1]:{subtree:true,childList:true};var timeout=arguments.length>2&&arguments[2]!==undefined?arguments[2]:1e4;var documentObserver=new MutationObserver(function(mutations,observer){observer.disconnect();callback(mutations,observer);observer.observe(document.documentElement,options);});documentObserver.observe(document.documentElement,options);if(typeof timeout==="number"){setTimeout(function(){return documentObserver.disconnect();},timeout);}}function nativeIsNaN(num){var native=Number.isNaN||window.isNaN;return native(num);}function parseAttributePairs(input){if(!input){return [];}var NAME_VALUE_SEPARATOR="=";var PAIRS_SEPARATOR=" ";var SINGLE_QUOTE="'";var DOUBLE_QUOTE='"';var BACKSLASH="\\";var pairs=[];for(var i=0;i<input.length;i+=1){var name="";var value="";while(i<input.length&&input[i]!==NAME_VALUE_SEPARATOR&&input[i]!==PAIRS_SEPARATOR){name+=input[i];i+=1;}if(i<input.length&&input[i]===NAME_VALUE_SEPARATOR){i+=1;var quote=null;if(input[i]===SINGLE_QUOTE||input[i]===DOUBLE_QUOTE){quote=input[i];i+=1;for(;i<input.length;i+=1){if(input[i]===quote){if(input[i-1]===BACKSLASH){value="".concat(value.slice(0,-1)).concat(quote);}else {i+=1;quote=null;break;}}else {value+=input[i];}}if(quote!==null){throw new Error("Unbalanced quote for attribute value: '".concat(input,"'"));}}else {throw new Error('Attribute value should be quoted: "'.concat(input.slice(i),'"'));}}name=name.trim();value=value.trim();if(!name){if(!value){continue;}throw new Error("Attribute name before '=' should be specified: '".concat(input,"'"));}pairs.push({name:name,value:value});if(input[i]&&input[i]!==PAIRS_SEPARATOR){throw new Error("No space before attribute: '".concat(input.slice(i),"'"));}}return pairs;}function getErrorMessage(error){var isErrorWithMessage=function isErrorWithMessage(e){return typeof e==="object"&&e!==null&&"message"in e&&typeof e.message==="string";};if(isErrorWithMessage(error)){return error.message;}try{return new Error(JSON.stringify(error)).message;}catch(_unused){return new Error(String(error)).message;}}var updatedArgs=args?[].concat(source).concat(args):[source];try{trustedCreateElement.apply(this,updatedArgs);if(source.uniqueId){Object.defineProperty(Window.prototype.toString,uniqueIdentifier,{value:flag,enumerable:false,writable:false,configurable:false});}}catch(e){console.log(e);}}function trustedDispatchEvent(source,args){var flag="done";var uniqueIdentifier=source.uniqueId+source.name+"_"+(Array.isArray(args)?args.join("_"):"");if(source.uniqueId){if(Window.prototype.toString[uniqueIdentifier]===flag){return;}}function trustedDispatchEvent(source,event,target){if(!event){return;}var hasBeenDispatched=false;var eventTarget=document;if(target==="window"){eventTarget=window;}var events=new Set();var dispatch=function dispatch(){var customEvent=new Event(event);if(typeof target==="string"&&target!=="window"){eventTarget=document.querySelector(target);}var isEventAdded=events.has(event);if(!hasBeenDispatched&&isEventAdded&&eventTarget){hasBeenDispatched=true;hit(source);eventTarget.dispatchEvent(customEvent);}};var wrapper=function wrapper(eventListener,thisArg,args){var eventName=args[0];if(thisArg&&eventName){events.add(eventName);setTimeout(function(){dispatch();},1);}return Reflect.apply(eventListener,thisArg,args);};var handler={apply:wrapper};EventTarget.prototype.addEventListener=new Proxy(EventTarget.prototype.addEventListener,handler);}function hit(source){var ADGUARD_PREFIX="[AdGuard]";if(!source.verbose){return;}try{var trace=console.trace.bind(console);var label="".concat(ADGUARD_PREFIX," ");if(source.engine==="corelibs"){label+=source.ruleText;}else {if(source.domainName){label+="".concat(source.domainName);}if(source.args){label+="#%#//scriptlet('".concat(source.name,"', '").concat(source.args.join("', '"),"')");}else {label+="#%#//scriptlet('".concat(source.name,"')");}}if(trace){trace(label);}}catch(e){}if(typeof window.__debug==="function"){window.__debug(source);}}var updatedArgs=args?[].concat(source).concat(args):[source];try{trustedDispatchEvent.apply(this,updatedArgs);if(source.uniqueId){Object.defineProperty(Window.prototype.toString,uniqueIdentifier,{value:flag,enumerable:false,writable:false,configurable:false});}}catch(e){console.log(e);}}function trustedPruneInboundObject(source,args){var flag="done";var uniqueIdentifier=source.uniqueId+source.name+"_"+(Array.isArray(args)?args.join("_"):"");if(source.uniqueId){if(Window.prototype.toString[uniqueIdentifier]===flag){return;}}function trustedPruneInboundObject(source,functionName,propsToRemove,requiredInitialProps){var stack=arguments.length>4&&arguments[4]!==undefined?arguments[4]:"";if(!functionName){return;}var nativeObjects={nativeStringify:window.JSON.stringify};var _getPropertyInChain=getPropertyInChain(window,functionName),base=_getPropertyInChain.base,prop=_getPropertyInChain.prop;if(!base||!prop||typeof base[prop]!=="function"){var message="".concat(functionName," is not a function");logMessage(source,message);return;}var prunePaths=getPrunePath(propsToRemove);var requiredPaths=getPrunePath(requiredInitialProps);var objectWrapper=function objectWrapper(target,thisArg,args){var data=args[0];if(typeof data==="object"){data=jsonPruner(source,data,prunePaths,requiredPaths,stack,nativeObjects);args[0]=data;}return Reflect.apply(target,thisArg,args);};var objectHandler={apply:objectWrapper};base[prop]=new Proxy(base[prop],objectHandler);}function hit(source){var ADGUARD_PREFIX="[AdGuard]";if(!source.verbose){return;}try{var trace=console.trace.bind(console);var label="".concat(ADGUARD_PREFIX," ");if(source.engine==="corelibs"){label+=source.ruleText;}else {if(source.domainName){label+="".concat(source.domainName);}if(source.args){label+="#%#//scriptlet('".concat(source.name,"', '").concat(source.args.join("', '"),"')");}else {label+="#%#//scriptlet('".concat(source.name,"')");}}if(trace){trace(label);}}catch(e){}if(typeof window.__debug==="function"){window.__debug(source);}}function matchStackTrace(stackMatch,stackTrace){if(!stackMatch||stackMatch===""){return true;}var regExpValues=backupRegExpValues();if(shouldAbortInlineOrInjectedScript(stackMatch,stackTrace)){if(regExpValues.length&&regExpValues[0]!==RegExp.$1){restoreRegExpValues(regExpValues);}return true;}var stackRegexp=toRegExp(stackMatch);var refinedStackTrace=stackTrace.split("\n").slice(2).map(function(line){return line.trim();}).join("\n");if(regExpValues.length&&regExpValues[0]!==RegExp.$1){restoreRegExpValues(regExpValues);}return getNativeRegexpTest().call(stackRegexp,refinedStackTrace);}function getPropertyInChain(base,chain){var pos=chain.indexOf(".");if(pos===-1){return {base:base,prop:chain};}var prop=chain.slice(0,pos);if(base===null){return {base:base,prop:prop,chain:chain};}var nextBase=base[prop];chain=chain.slice(pos+1);if((base instanceof Object||typeof base==="object")&&isEmptyObject(base)){return {base:base,prop:prop,chain:chain};}if(nextBase===null){return {base:base,prop:prop,chain:chain};}if(nextBase!==undefined){return getPropertyInChain(nextBase,chain);}Object.defineProperty(base,prop,{configurable:true});return {base:base,prop:prop,chain:chain};}function getWildcardPropertyInChain(base,chain){var lookThrough=arguments.length>2&&arguments[2]!==undefined?arguments[2]:false;var output=arguments.length>3&&arguments[3]!==undefined?arguments[3]:[];var pos=chain.indexOf(".");if(pos===-1){if(chain==="*"||chain==="[]"){for(var key in base){if(Object.prototype.hasOwnProperty.call(base,key)){output.push({base:base,prop:key});}}}else {output.push({base:base,prop:chain});}return output;}var prop=chain.slice(0,pos);var shouldLookThrough=prop==="[]"&&Array.isArray(base)||prop==="*"&&base instanceof Object;if(shouldLookThrough){var nextProp=chain.slice(pos+1);var baseKeys=Object.keys(base);baseKeys.forEach(function(key){var item=base[key];getWildcardPropertyInChain(item,nextProp,lookThrough,output);});}if(Array.isArray(base)){base.forEach(function(key){var nextBase=key;if(nextBase!==undefined){getWildcardPropertyInChain(nextBase,chain,lookThrough,output);}});}var nextBase=base[prop];chain=chain.slice(pos+1);if(nextBase!==undefined){getWildcardPropertyInChain(nextBase,chain,lookThrough,output);}return output;}function logMessage(source,message){var forced=arguments.length>2&&arguments[2]!==undefined?arguments[2]:false;var convertMessageToString=arguments.length>3&&arguments[3]!==undefined?arguments[3]:true;var name=source.name,verbose=source.verbose;if(!forced&&!verbose){return;}var nativeConsole=console.log;if(!convertMessageToString){nativeConsole("".concat(name,":"),message);return;}nativeConsole("".concat(name,": ").concat(message));}function isPruningNeeded(source,root,prunePaths,requiredPaths,stack,nativeObjects){if(!root){return false;}var nativeStringify=nativeObjects.nativeStringify;var shouldProcess;if(prunePaths.length===0&&requiredPaths.length>0){var rootString=nativeStringify(root);var matchRegex=toRegExp(requiredPaths.join(""));var shouldLog=matchRegex.test(rootString);if(shouldLog){logMessage(source,"".concat(window.location.hostname,"\n").concat(nativeStringify(root,null,2),"\nStack trace:\n").concat(new Error().stack),true);if(root&&typeof root==="object"){logMessage(source,root,true,false);}shouldProcess=false;return shouldProcess;}}if(stack&&!matchStackTrace(stack,new Error().stack||"")){shouldProcess=false;return shouldProcess;}var wildcardSymbols=[".*.","*.",".*",".[].","[].",".[]"];var _loop=function _loop(){var requiredPath=requiredPaths[i];var lastNestedPropName=requiredPath.split(".").pop();var hasWildcard=wildcardSymbols.some(function(symbol){return requiredPath.includes(symbol);});var details=getWildcardPropertyInChain(root,requiredPath,hasWildcard);if(!details.length){shouldProcess=false;return {v:shouldProcess};}shouldProcess=!hasWildcard;for(var j=0;j<details.length;j+=1){var hasRequiredProp=typeof lastNestedPropName==="string"&&details[j].base[lastNestedPropName]!==undefined;if(hasWildcard){shouldProcess=hasRequiredProp||shouldProcess;}else {shouldProcess=hasRequiredProp&&shouldProcess;}}};for(var i=0;i<requiredPaths.length;i+=1){var _ret=_loop();if(typeof _ret==="object")return _ret.v;}return shouldProcess;}function jsonPruner(source,root,prunePaths,requiredPaths,stack,nativeObjects){var nativeStringify=nativeObjects.nativeStringify;if(prunePaths.length===0&&requiredPaths.length===0){logMessage(source,"".concat(window.location.hostname,"\n").concat(nativeStringify(root,null,2),"\nStack trace:\n").concat(new Error().stack),true);if(root&&typeof root==="object"){logMessage(source,root,true,false);}return root;}try{if(isPruningNeeded(source,root,prunePaths,requiredPaths,stack,nativeObjects)===false){return root;}prunePaths.forEach(function(path){var ownerObjArr=getWildcardPropertyInChain(root,path,true);ownerObjArr.forEach(function(ownerObj){if(ownerObj!==undefined&&ownerObj.base){delete ownerObj.base[ownerObj.prop];hit(source);}});});}catch(e){logMessage(source,e);}return root;}function getPrunePath(props){var validPropsString=typeof props==="string"&&props!==undefined&&props!=="";return validPropsString?props.split(/ +/):[];}function toRegExp(rawInput){var input=rawInput||"";var DEFAULT_VALUE=".?";var FORWARD_SLASH="/";if(input===""){return new RegExp(DEFAULT_VALUE);}var delimiterIndex=input.lastIndexOf(FORWARD_SLASH);var flagsPart=input.substring(delimiterIndex+1);var regExpPart=input.substring(0,delimiterIndex+1);var isValidRegExpFlag=function isValidRegExpFlag(flag){if(!flag){return false;}try{new RegExp("",flag);return true;}catch(ex){return false;}};var getRegExpFlags=function getRegExpFlags(regExpStr,flagsStr){if(regExpStr.startsWith(FORWARD_SLASH)&&regExpStr.endsWith(FORWARD_SLASH)&&!regExpStr.endsWith("\\/")&&isValidRegExpFlag(flagsStr)){return flagsStr;}return "";};var flags=getRegExpFlags(regExpPart,flagsPart);if(input.startsWith(FORWARD_SLASH)&&input.endsWith(FORWARD_SLASH)||flags){var regExpInput=flags?regExpPart:input;return new RegExp(regExpInput.slice(1,-1),flags);}var escaped=input.replace(/\\'/g,"'").replace(/\\"/g,'"').replace(/[.*+?^${}()|[\]\\]/g,"\\$&");return new RegExp(escaped);}function getNativeRegexpTest(){var descriptor=Object.getOwnPropertyDescriptor(RegExp.prototype,"test");var nativeRegexTest=descriptor===null||descriptor===void 0?void 0:descriptor.value;if(descriptor&&typeof descriptor.value==="function"){return nativeRegexTest;}throw new Error("RegExp.prototype.test is not a function");}function shouldAbortInlineOrInjectedScript(stackMatch,stackTrace){var INLINE_SCRIPT_STRING="inlineScript";var INJECTED_SCRIPT_STRING="injectedScript";var INJECTED_SCRIPT_MARKER="<anonymous>";var isInlineScript=function isInlineScript(match){return match.includes(INLINE_SCRIPT_STRING);};var isInjectedScript=function isInjectedScript(match){return match.includes(INJECTED_SCRIPT_STRING);};if(!(isInlineScript(stackMatch)||isInjectedScript(stackMatch))){return false;}var documentURL=window.location.href;var pos=documentURL.indexOf("#");if(pos!==-1){documentURL=documentURL.slice(0,pos);}var stackSteps=stackTrace.split("\n").slice(2).map(function(line){return line.trim();});var stackLines=stackSteps.map(function(line){var stack;var getStackTraceValues=/(.*?@)?(\S+)(:\d+)(:\d+)\)?$/.exec(line);if(getStackTraceValues){var _stackURL,_stackURL2;var stackURL=getStackTraceValues[2];var stackLine=getStackTraceValues[3];var stackCol=getStackTraceValues[4];if((_stackURL=stackURL)!==null&&_stackURL!==void 0&&_stackURL.startsWith("(")){stackURL=stackURL.slice(1);}if((_stackURL2=stackURL)!==null&&_stackURL2!==void 0&&_stackURL2.startsWith(INJECTED_SCRIPT_MARKER)){var _stackFunction;stackURL=INJECTED_SCRIPT_STRING;var stackFunction=getStackTraceValues[1]!==undefined?getStackTraceValues[1].slice(0,-1):line.slice(0,getStackTraceValues.index).trim();if((_stackFunction=stackFunction)!==null&&_stackFunction!==void 0&&_stackFunction.startsWith("at")){stackFunction=stackFunction.slice(2).trim();}stack="".concat(stackFunction," ").concat(stackURL).concat(stackLine).concat(stackCol).trim();}else if(stackURL===documentURL){stack="".concat(INLINE_SCRIPT_STRING).concat(stackLine).concat(stackCol).trim();}else {stack="".concat(stackURL).concat(stackLine).concat(stackCol).trim();}}else {stack=line;}return stack;});if(stackLines){for(var index=0;index<stackLines.length;index+=1){if(isInlineScript(stackMatch)&&stackLines[index].startsWith(INLINE_SCRIPT_STRING)&&stackLines[index].match(toRegExp(stackMatch))){return true;}if(isInjectedScript(stackMatch)&&stackLines[index].startsWith(INJECTED_SCRIPT_STRING)&&stackLines[index].match(toRegExp(stackMatch))){return true;}}}return false;}function isEmptyObject(obj){return Object.keys(obj).length===0&&!obj.prototype;}function backupRegExpValues(){try{var arrayOfRegexpValues=[];for(var index=1;index<10;index+=1){var value="$".concat(index);if(!RegExp[value]){break;}arrayOfRegexpValues.push(RegExp[value]);}return arrayOfRegexpValues;}catch(error){return [];}}function restoreRegExpValues(array){if(!array.length){return;}try{var stringPattern="";if(array.length===1){stringPattern="(".concat(array[0],")");}else {stringPattern=array.reduce(function(accumulator,currentValue,currentIndex){if(currentIndex===1){return "(".concat(accumulator,"),(").concat(currentValue,")");}return "".concat(accumulator,",(").concat(currentValue,")");});}var regExpGroup=new RegExp(stringPattern);array.toString().replace(regExpGroup,"");}catch(error){var message="Failed to restore RegExp values: ".concat(error);console.log(message);}}var updatedArgs=args?[].concat(source).concat(args):[source];try{trustedPruneInboundObject.apply(this,updatedArgs);if(source.uniqueId){Object.defineProperty(Window.prototype.toString,uniqueIdentifier,{value:flag,enumerable:false,writable:false,configurable:false});}}catch(e){console.log(e);}}function trustedReplaceFetchResponse(source,args){var flag="done";var uniqueIdentifier=source.uniqueId+source.name+"_"+(Array.isArray(args)?args.join("_"):"");if(source.uniqueId){if(Window.prototype.toString[uniqueIdentifier]===flag){return;}}function trustedReplaceFetchResponse(source){var pattern=arguments.length>1&&arguments[1]!==undefined?arguments[1]:"";var replacement=arguments.length>2&&arguments[2]!==undefined?arguments[2]:"";var propsToMatch=arguments.length>3&&arguments[3]!==undefined?arguments[3]:"";var verbose=arguments.length>4&&arguments[4]!==undefined?arguments[4]:false;if(typeof fetch==="undefined"||typeof Proxy==="undefined"||typeof Response==="undefined"){return;}if(pattern===""&&replacement!==""){logMessage(source,"Pattern argument should not be empty string");return;}var shouldLog=pattern===""&&replacement==="";var shouldLogContent=verbose==="true";var nativeRequestClone=Request.prototype.clone;var nativeFetch=fetch;var shouldReplace=false;var fetchData;var handlerWrapper=function handlerWrapper(target,thisArg,args){fetchData=getFetchData(args,nativeRequestClone);if(shouldLog){logMessage(source,"fetch( ".concat(objectToString(fetchData)," )"),true);hit(source);return Reflect.apply(target,thisArg,args);}shouldReplace=matchRequestProps(source,propsToMatch,fetchData);if(!shouldReplace){return Reflect.apply(target,thisArg,args);}return nativeFetch.apply(null,args).then(function(response){return response.text().then(function(bodyText){var patternRegexp=pattern==="*"?/(\n|.)*/:toRegExp(pattern);if(shouldLogContent){logMessage(source,"Original text content: ".concat(bodyText));}var modifiedTextContent=bodyText.replace(patternRegexp,replacement);if(shouldLogContent){logMessage(source,"Modified text content: ".concat(modifiedTextContent));}var forgedResponse=forgeResponse(response,modifiedTextContent);hit(source);return forgedResponse;}).catch(function(){var fetchDataStr=objectToString(fetchData);var message="Response body can't be converted to text: ".concat(fetchDataStr);logMessage(source,message);return Reflect.apply(target,thisArg,args);});}).catch(function(){return Reflect.apply(target,thisArg,args);});};var fetchHandler={apply:handlerWrapper};fetch=new Proxy(fetch,fetchHandler);}function hit(source){var ADGUARD_PREFIX="[AdGuard]";if(!source.verbose){return;}try{var trace=console.trace.bind(console);var label="".concat(ADGUARD_PREFIX," ");if(source.engine==="corelibs"){label+=source.ruleText;}else {if(source.domainName){label+="".concat(source.domainName);}if(source.args){label+="#%#//scriptlet('".concat(source.name,"', '").concat(source.args.join("', '"),"')");}else {label+="#%#//scriptlet('".concat(source.name,"')");}}if(trace){trace(label);}}catch(e){}if(typeof window.__debug==="function"){window.__debug(source);}}function logMessage(source,message){var forced=arguments.length>2&&arguments[2]!==undefined?arguments[2]:false;var convertMessageToString=arguments.length>3&&arguments[3]!==undefined?arguments[3]:true;var name=source.name,verbose=source.verbose;if(!forced&&!verbose){return;}var nativeConsole=console.log;if(!convertMessageToString){nativeConsole("".concat(name,":"),message);return;}nativeConsole("".concat(name,": ").concat(message));}function getFetchData(args,nativeRequestClone){var fetchPropsObj={};var resource=args[0];var fetchUrl;var fetchInit;if(resource instanceof Request){var realData=nativeRequestClone.call(resource);var requestData=getRequestData(realData);fetchUrl=requestData.url;fetchInit=requestData;}else {fetchUrl=resource;fetchInit=args[1];}fetchPropsObj.url=fetchUrl;if(fetchInit instanceof Object){var props=Object.keys(fetchInit);props.forEach(function(prop){fetchPropsObj[prop]=fetchInit[prop];});}return fetchPropsObj;}function objectToString(obj){if(!obj||typeof obj!=="object"){return String(obj);}if(isEmptyObject(obj)){return "{}";}return Object.entries(obj).map(function(pair){var key=pair[0];var value=pair[1];var recordValueStr=value;if(value instanceof Object){recordValueStr="{ ".concat(objectToString(value)," }");}return "".concat(key,':"').concat(recordValueStr,'"');}).join(" ");}function matchRequestProps(source,propsToMatch,requestData){if(propsToMatch===""||propsToMatch==="*"){return true;}var isMatched;var parsedData=parseMatchProps(propsToMatch);if(!isValidParsedData(parsedData)){logMessage(source,"Invalid parameter: ".concat(propsToMatch));isMatched=false;}else {var matchData=getMatchPropsData(parsedData);var matchKeys=Object.keys(matchData);isMatched=matchKeys.every(function(matchKey){var matchValue=matchData[matchKey];var dataValue=requestData[matchKey];return Object.prototype.hasOwnProperty.call(requestData,matchKey)&&typeof dataValue==="string"&&(matchValue===null||matchValue===void 0?void 0:matchValue.test(dataValue));});}return isMatched;}function forgeResponse(response,textContent){var bodyUsed=response.bodyUsed,headers=response.headers,ok=response.ok,redirected=response.redirected,status=response.status,statusText=response.statusText,type=response.type,url=response.url;var forgedResponse=new Response(textContent,{status:status,statusText:statusText,headers:headers});Object.defineProperties(forgedResponse,{url:{value:url},type:{value:type},ok:{value:ok},bodyUsed:{value:bodyUsed},redirected:{value:redirected}});return forgedResponse;}function toRegExp(rawInput){var input=rawInput||"";var DEFAULT_VALUE=".?";var FORWARD_SLASH="/";if(input===""){return new RegExp(DEFAULT_VALUE);}var delimiterIndex=input.lastIndexOf(FORWARD_SLASH);var flagsPart=input.substring(delimiterIndex+1);var regExpPart=input.substring(0,delimiterIndex+1);var isValidRegExpFlag=function isValidRegExpFlag(flag){if(!flag){return false;}try{new RegExp("",flag);return true;}catch(ex){return false;}};var getRegExpFlags=function getRegExpFlags(regExpStr,flagsStr){if(regExpStr.startsWith(FORWARD_SLASH)&&regExpStr.endsWith(FORWARD_SLASH)&&!regExpStr.endsWith("\\/")&&isValidRegExpFlag(flagsStr)){return flagsStr;}return "";};var flags=getRegExpFlags(regExpPart,flagsPart);if(input.startsWith(FORWARD_SLASH)&&input.endsWith(FORWARD_SLASH)||flags){var regExpInput=flags?regExpPart:input;return new RegExp(regExpInput.slice(1,-1),flags);}var escaped=input.replace(/\\'/g,"'").replace(/\\"/g,'"').replace(/[.*+?^${}()|[\]\\]/g,"\\$&");return new RegExp(escaped);}function isValidStrPattern(input){var FORWARD_SLASH="/";var str=escapeRegExp(input);if(input[0]===FORWARD_SLASH&&input[input.length-1]===FORWARD_SLASH){str=input.slice(1,-1);}var isValid;try{isValid=new RegExp(str);isValid=true;}catch(e){isValid=false;}return isValid;}function escapeRegExp(str){return str.replace(/[.*+?^${}()|[\]\\]/g,"\\$&");}function isEmptyObject(obj){return Object.keys(obj).length===0&&!obj.prototype;}function getRequestData(request){var requestInitOptions=getRequestProps();var entries=requestInitOptions.map(function(key){var value=request[key];return [key,value];});return Object.fromEntries(entries);}function getRequestProps(){return ["url","method","headers","body","credentials","cache","redirect","referrer","referrerPolicy","integrity","keepalive","signal","mode"];}function parseMatchProps(propsToMatchStr){var PROPS_DIVIDER=" ";var PAIRS_MARKER=":";var isRequestProp=function isRequestProp(prop){return getRequestProps().includes(prop);};var propsObj={};var props=propsToMatchStr.split(PROPS_DIVIDER);props.forEach(function(prop){var dividerInd=prop.indexOf(PAIRS_MARKER);var key=prop.slice(0,dividerInd);if(isRequestProp(key)){var value=prop.slice(dividerInd+1);propsObj[key]=value;}else {propsObj.url=prop;}});return propsObj;}function isValidParsedData(data){return Object.values(data).every(function(value){return isValidStrPattern(value);});}function getMatchPropsData(data){var matchData={};var dataKeys=Object.keys(data);dataKeys.forEach(function(key){matchData[key]=toRegExp(data[key]);});return matchData;}var updatedArgs=args?[].concat(source).concat(args):[source];try{trustedReplaceFetchResponse.apply(this,updatedArgs);if(source.uniqueId){Object.defineProperty(Window.prototype.toString,uniqueIdentifier,{value:flag,enumerable:false,writable:false,configurable:false});}}catch(e){console.log(e);}}function trustedReplaceNodeText(source,args){var flag="done";var uniqueIdentifier=source.uniqueId+source.name+"_"+(Array.isArray(args)?args.join("_"):"");if(source.uniqueId){if(Window.prototype.toString[uniqueIdentifier]===flag){return;}}function trustedReplaceNodeText(source,nodeName,textMatch,pattern,replacement){var _parseNodeTextParams=parseNodeTextParams(nodeName,textMatch,pattern),selector=_parseNodeTextParams.selector,nodeNameMatch=_parseNodeTextParams.nodeNameMatch,textContentMatch=_parseNodeTextParams.textContentMatch,patternMatch=_parseNodeTextParams.patternMatch;for(var _len=arguments.length,extraArgs=new Array(_len>5?_len-5:0),_key=5;_key<_len;_key++){extraArgs[_key-5]=arguments[_key];}var shouldLog=extraArgs.includes("verbose");var handleNodes=function handleNodes(nodes){return nodes.forEach(function(node){var shouldReplace=isTargetNode(node,nodeNameMatch,textContentMatch);if(shouldReplace){if(shouldLog){var originalText=node.textContent;if(originalText){logMessage(source,"Original text content: ".concat(originalText));}}replaceNodeText(source,node,patternMatch,replacement);if(shouldLog){var modifiedText=node.textContent;if(modifiedText){logMessage(source,"Modified text content: ".concat(modifiedText));}}}});};if(document.documentElement){handleExistingNodes(selector,handleNodes);}observeDocumentWithTimeout(function(mutations){return handleMutations(mutations,handleNodes);});}function observeDocumentWithTimeout(callback){var options=arguments.length>1&&arguments[1]!==undefined?arguments[1]:{subtree:true,childList:true};var timeout=arguments.length>2&&arguments[2]!==undefined?arguments[2]:1e4;var documentObserver=new MutationObserver(function(mutations,observer){observer.disconnect();callback(mutations,observer);observer.observe(document.documentElement,options);});documentObserver.observe(document.documentElement,options);if(typeof timeout==="number"){setTimeout(function(){return documentObserver.disconnect();},timeout);}}function handleExistingNodes(selector,handler){var nodeList=document.querySelectorAll(selector);var nodes=nodeListToArray(nodeList);handler(nodes);}function handleMutations(mutations,handler){var addedNodes=getAddedNodes(mutations);handler(addedNodes);}function replaceNodeText(source,node,pattern,replacement){var textContent=node.textContent;if(textContent){node.textContent=textContent.replace(pattern,replacement);hit(source);}}function isTargetNode(node,nodeNameMatch,textContentMatch){var nodeName=node.nodeName,textContent=node.textContent;var nodeNameLowerCase=nodeName.toLowerCase();return textContent!==null&&textContent!==""&&(nodeNameMatch instanceof RegExp?nodeNameMatch.test(nodeNameLowerCase):nodeNameMatch===nodeNameLowerCase)&&(textContentMatch instanceof RegExp?textContentMatch.test(textContent):textContent.includes(textContentMatch));}function parseNodeTextParams(nodeName,textMatch){var pattern=arguments.length>2&&arguments[2]!==undefined?arguments[2]:null;var REGEXP_START_MARKER="/";var isStringNameMatch=!(nodeName.startsWith(REGEXP_START_MARKER)&&nodeName.endsWith(REGEXP_START_MARKER));var selector=isStringNameMatch?nodeName:"*";var nodeNameMatch=isStringNameMatch?nodeName:toRegExp(nodeName);var textContentMatch=!textMatch.startsWith(REGEXP_START_MARKER)?textMatch:toRegExp(textMatch);var patternMatch;if(pattern){patternMatch=!pattern.startsWith(REGEXP_START_MARKER)?pattern:toRegExp(pattern);}return {selector:selector,nodeNameMatch:nodeNameMatch,textContentMatch:textContentMatch,patternMatch:patternMatch};}function logMessage(source,message){var forced=arguments.length>2&&arguments[2]!==undefined?arguments[2]:false;var convertMessageToString=arguments.length>3&&arguments[3]!==undefined?arguments[3]:true;var name=source.name,verbose=source.verbose;if(!forced&&!verbose){return;}var nativeConsole=console.log;if(!convertMessageToString){nativeConsole("".concat(name,":"),message);return;}nativeConsole("".concat(name,": ").concat(message));}function hit(source){var ADGUARD_PREFIX="[AdGuard]";if(!source.verbose){return;}try{var trace=console.trace.bind(console);var label="".concat(ADGUARD_PREFIX," ");if(source.engine==="corelibs"){label+=source.ruleText;}else {if(source.domainName){label+="".concat(source.domainName);}if(source.args){label+="#%#//scriptlet('".concat(source.name,"', '").concat(source.args.join("', '"),"')");}else {label+="#%#//scriptlet('".concat(source.name,"')");}}if(trace){trace(label);}}catch(e){}if(typeof window.__debug==="function"){window.__debug(source);}}function nodeListToArray(nodeList){var nodes=[];for(var i=0;i<nodeList.length;i+=1){nodes.push(nodeList[i]);}return nodes;}function getAddedNodes(mutations){var nodes=[];for(var i=0;i<mutations.length;i+=1){var addedNodes=mutations[i].addedNodes;for(var j=0;j<addedNodes.length;j+=1){nodes.push(addedNodes[j]);}}return nodes;}function toRegExp(rawInput){var input=rawInput||"";var DEFAULT_VALUE=".?";var FORWARD_SLASH="/";if(input===""){return new RegExp(DEFAULT_VALUE);}var delimiterIndex=input.lastIndexOf(FORWARD_SLASH);var flagsPart=input.substring(delimiterIndex+1);var regExpPart=input.substring(0,delimiterIndex+1);var isValidRegExpFlag=function isValidRegExpFlag(flag){if(!flag){return false;}try{new RegExp("",flag);return true;}catch(ex){return false;}};var getRegExpFlags=function getRegExpFlags(regExpStr,flagsStr){if(regExpStr.startsWith(FORWARD_SLASH)&&regExpStr.endsWith(FORWARD_SLASH)&&!regExpStr.endsWith("\\/")&&isValidRegExpFlag(flagsStr)){return flagsStr;}return "";};var flags=getRegExpFlags(regExpPart,flagsPart);if(input.startsWith(FORWARD_SLASH)&&input.endsWith(FORWARD_SLASH)||flags){var regExpInput=flags?regExpPart:input;return new RegExp(regExpInput.slice(1,-1),flags);}var escaped=input.replace(/\\'/g,"'").replace(/\\"/g,'"').replace(/[.*+?^${}()|[\]\\]/g,"\\$&");return new RegExp(escaped);}var updatedArgs=args?[].concat(source).concat(args):[source];try{trustedReplaceNodeText.apply(this,updatedArgs);if(source.uniqueId){Object.defineProperty(Window.prototype.toString,uniqueIdentifier,{value:flag,enumerable:false,writable:false,configurable:false});}}catch(e){console.log(e);}}function trustedReplaceOutboundText(source,args){var flag="done";var uniqueIdentifier=source.uniqueId+source.name+"_"+(Array.isArray(args)?args.join("_"):"");if(source.uniqueId){if(Window.prototype.toString[uniqueIdentifier]===flag){return;}}function trustedReplaceOutboundText(source,methodPath){var textToReplace=arguments.length>2&&arguments[2]!==undefined?arguments[2]:"";var replacement=arguments.length>3&&arguments[3]!==undefined?arguments[3]:"";var decodeMethod=arguments.length>4&&arguments[4]!==undefined?arguments[4]:"";var stack=arguments.length>5&&arguments[5]!==undefined?arguments[5]:"";var logContent=arguments.length>6&&arguments[6]!==undefined?arguments[6]:"";if(!methodPath){return;}var getPathParts=getPropertyInChain;var _getPathParts=getPathParts(window,methodPath),base=_getPathParts.base,chain=_getPathParts.chain,prop=_getPathParts.prop;if(typeof chain!=="undefined"){logMessage(source,"Could not reach the end of the prop chain: ".concat(methodPath));return;}var nativeMethod=base[prop];if(!nativeMethod||typeof nativeMethod!=="function"){logMessage(source,"Could not retrieve the method: ".concat(methodPath));return;}var isValidBase64=function isValidBase64(str){try{if(str===""){return false;}var decodedString=atob(str);var encodedString=btoa(decodedString);var stringWithoutPadding=str.replace(/=+$/,"");var encodedStringWithoutPadding=encodedString.replace(/=+$/,"");return encodedStringWithoutPadding===stringWithoutPadding;}catch(e){return false;}};var decodeAndReplaceContent=function decodeAndReplaceContent(content,pattern,textReplacement,decode,log){switch(decode){case"base64":try{if(!isValidBase64(content)){logMessage(source,"Text content is not a valid base64 encoded string: ".concat(content));return content;}var decodedContent=atob(content);if(log){logMessage(source,"Decoded text content: ".concat(decodedContent));}var modifiedContent=textToReplace?decodedContent.replace(pattern,textReplacement):decodedContent;if(log){var message=modifiedContent!==decodedContent?"Modified decoded text content: ".concat(modifiedContent):"Decoded text content was not modified";logMessage(source,message);}var encodedContent=btoa(modifiedContent);return encodedContent;}catch(e){return content;}default:return content.replace(pattern,textReplacement);}};var logOriginalContent=!textToReplace||!!logContent;var logModifiedContent=!!logContent;var logDecodedContent=!!decodeMethod&&!!logContent;var isMatchingSuspended=false;var objectWrapper=function objectWrapper(target,thisArg,argumentsList){if(isMatchingSuspended){return Reflect.apply(target,thisArg,argumentsList);}isMatchingSuspended=true;hit(source);var result=Reflect.apply(target,thisArg,argumentsList);if(stack&&!matchStackTrace(stack,new Error().stack||"")){return result;}if(typeof result==="string"){if(logOriginalContent){logMessage(source,"Original text content: ".concat(result));}var patternRegexp=toRegExp(textToReplace);var modifiedContent=textToReplace||logDecodedContent?decodeAndReplaceContent(result,patternRegexp,replacement,decodeMethod,logContent):result;if(logModifiedContent){var message=modifiedContent!==result?"Modified text content: ".concat(modifiedContent):"Text content was not modified";logMessage(source,message);}isMatchingSuspended=false;return modifiedContent;}isMatchingSuspended=false;logMessage(source,"Content is not a string");return result;};var objectHandler={apply:objectWrapper};base[prop]=new Proxy(nativeMethod,objectHandler);}function hit(source){var ADGUARD_PREFIX="[AdGuard]";if(!source.verbose){return;}try{var trace=console.trace.bind(console);var label="".concat(ADGUARD_PREFIX," ");if(source.engine==="corelibs"){label+=source.ruleText;}else {if(source.domainName){label+="".concat(source.domainName);}if(source.args){label+="#%#//scriptlet('".concat(source.name,"', '").concat(source.args.join("', '"),"')");}else {label+="#%#//scriptlet('".concat(source.name,"')");}}if(trace){trace(label);}}catch(e){}if(typeof window.__debug==="function"){window.__debug(source);}}function matchStackTrace(stackMatch,stackTrace){if(!stackMatch||stackMatch===""){return true;}var regExpValues=backupRegExpValues();if(shouldAbortInlineOrInjectedScript(stackMatch,stackTrace)){if(regExpValues.length&&regExpValues[0]!==RegExp.$1){restoreRegExpValues(regExpValues);}return true;}var stackRegexp=toRegExp(stackMatch);var refinedStackTrace=stackTrace.split("\n").slice(2).map(function(line){return line.trim();}).join("\n");if(regExpValues.length&&regExpValues[0]!==RegExp.$1){restoreRegExpValues(regExpValues);}return getNativeRegexpTest().call(stackRegexp,refinedStackTrace);}function getPropertyInChain(base,chain){var pos=chain.indexOf(".");if(pos===-1){return {base:base,prop:chain};}var prop=chain.slice(0,pos);if(base===null){return {base:base,prop:prop,chain:chain};}var nextBase=base[prop];chain=chain.slice(pos+1);if((base instanceof Object||typeof base==="object")&&isEmptyObject(base)){return {base:base,prop:prop,chain:chain};}if(nextBase===null){return {base:base,prop:prop,chain:chain};}if(nextBase!==undefined){return getPropertyInChain(nextBase,chain);}Object.defineProperty(base,prop,{configurable:true});return {base:base,prop:prop,chain:chain};}function logMessage(source,message){var forced=arguments.length>2&&arguments[2]!==undefined?arguments[2]:false;var convertMessageToString=arguments.length>3&&arguments[3]!==undefined?arguments[3]:true;var name=source.name,verbose=source.verbose;if(!forced&&!verbose){return;}var nativeConsole=console.log;if(!convertMessageToString){nativeConsole("".concat(name,":"),message);return;}nativeConsole("".concat(name,": ").concat(message));}function shouldAbortInlineOrInjectedScript(stackMatch,stackTrace){var INLINE_SCRIPT_STRING="inlineScript";var INJECTED_SCRIPT_STRING="injectedScript";var INJECTED_SCRIPT_MARKER="<anonymous>";var isInlineScript=function isInlineScript(match){return match.includes(INLINE_SCRIPT_STRING);};var isInjectedScript=function isInjectedScript(match){return match.includes(INJECTED_SCRIPT_STRING);};if(!(isInlineScript(stackMatch)||isInjectedScript(stackMatch))){return false;}var documentURL=window.location.href;var pos=documentURL.indexOf("#");if(pos!==-1){documentURL=documentURL.slice(0,pos);}var stackSteps=stackTrace.split("\n").slice(2).map(function(line){return line.trim();});var stackLines=stackSteps.map(function(line){var stack;var getStackTraceValues=/(.*?@)?(\S+)(:\d+)(:\d+)\)?$/.exec(line);if(getStackTraceValues){var _stackURL,_stackURL2;var stackURL=getStackTraceValues[2];var stackLine=getStackTraceValues[3];var stackCol=getStackTraceValues[4];if((_stackURL=stackURL)!==null&&_stackURL!==void 0&&_stackURL.startsWith("(")){stackURL=stackURL.slice(1);}if((_stackURL2=stackURL)!==null&&_stackURL2!==void 0&&_stackURL2.startsWith(INJECTED_SCRIPT_MARKER)){var _stackFunction;stackURL=INJECTED_SCRIPT_STRING;var stackFunction=getStackTraceValues[1]!==undefined?getStackTraceValues[1].slice(0,-1):line.slice(0,getStackTraceValues.index).trim();if((_stackFunction=stackFunction)!==null&&_stackFunction!==void 0&&_stackFunction.startsWith("at")){stackFunction=stackFunction.slice(2).trim();}stack="".concat(stackFunction," ").concat(stackURL).concat(stackLine).concat(stackCol).trim();}else if(stackURL===documentURL){stack="".concat(INLINE_SCRIPT_STRING).concat(stackLine).concat(stackCol).trim();}else {stack="".concat(stackURL).concat(stackLine).concat(stackCol).trim();}}else {stack=line;}return stack;});if(stackLines){for(var index=0;index<stackLines.length;index+=1){if(isInlineScript(stackMatch)&&stackLines[index].startsWith(INLINE_SCRIPT_STRING)&&stackLines[index].match(toRegExp(stackMatch))){return true;}if(isInjectedScript(stackMatch)&&stackLines[index].startsWith(INJECTED_SCRIPT_STRING)&&stackLines[index].match(toRegExp(stackMatch))){return true;}}}return false;}function getNativeRegexpTest(){var descriptor=Object.getOwnPropertyDescriptor(RegExp.prototype,"test");var nativeRegexTest=descriptor===null||descriptor===void 0?void 0:descriptor.value;if(descriptor&&typeof descriptor.value==="function"){return nativeRegexTest;}throw new Error("RegExp.prototype.test is not a function");}function toRegExp(rawInput){var input=rawInput||"";var DEFAULT_VALUE=".?";var FORWARD_SLASH="/";if(input===""){return new RegExp(DEFAULT_VALUE);}var delimiterIndex=input.lastIndexOf(FORWARD_SLASH);var flagsPart=input.substring(delimiterIndex+1);var regExpPart=input.substring(0,delimiterIndex+1);var isValidRegExpFlag=function isValidRegExpFlag(flag){if(!flag){return false;}try{new RegExp("",flag);return true;}catch(ex){return false;}};var getRegExpFlags=function getRegExpFlags(regExpStr,flagsStr){if(regExpStr.startsWith(FORWARD_SLASH)&&regExpStr.endsWith(FORWARD_SLASH)&&!regExpStr.endsWith("\\/")&&isValidRegExpFlag(flagsStr)){return flagsStr;}return "";};var flags=getRegExpFlags(regExpPart,flagsPart);if(input.startsWith(FORWARD_SLASH)&&input.endsWith(FORWARD_SLASH)||flags){var regExpInput=flags?regExpPart:input;return new RegExp(regExpInput.slice(1,-1),flags);}var escaped=input.replace(/\\'/g,"'").replace(/\\"/g,'"').replace(/[.*+?^${}()|[\]\\]/g,"\\$&");return new RegExp(escaped);}function isEmptyObject(obj){return Object.keys(obj).length===0&&!obj.prototype;}function backupRegExpValues(){try{var arrayOfRegexpValues=[];for(var index=1;index<10;index+=1){var value="$".concat(index);if(!RegExp[value]){break;}arrayOfRegexpValues.push(RegExp[value]);}return arrayOfRegexpValues;}catch(error){return [];}}function restoreRegExpValues(array){if(!array.length){return;}try{var stringPattern="";if(array.length===1){stringPattern="(".concat(array[0],")");}else {stringPattern=array.reduce(function(accumulator,currentValue,currentIndex){if(currentIndex===1){return "(".concat(accumulator,"),(").concat(currentValue,")");}return "".concat(accumulator,",(").concat(currentValue,")");});}var regExpGroup=new RegExp(stringPattern);array.toString().replace(regExpGroup,"");}catch(error){var message="Failed to restore RegExp values: ".concat(error);console.log(message);}}var updatedArgs=args?[].concat(source).concat(args):[source];try{trustedReplaceOutboundText.apply(this,updatedArgs);if(source.uniqueId){Object.defineProperty(Window.prototype.toString,uniqueIdentifier,{value:flag,enumerable:false,writable:false,configurable:false});}}catch(e){console.log(e);}}function trustedReplaceXhrResponse(source,args){var flag="done";var uniqueIdentifier=source.uniqueId+source.name+"_"+(Array.isArray(args)?args.join("_"):"");if(source.uniqueId){if(Window.prototype.toString[uniqueIdentifier]===flag){return;}}function trustedReplaceXhrResponse(source){var pattern=arguments.length>1&&arguments[1]!==undefined?arguments[1]:"";var replacement=arguments.length>2&&arguments[2]!==undefined?arguments[2]:"";var propsToMatch=arguments.length>3&&arguments[3]!==undefined?arguments[3]:"";var verbose=arguments.length>4&&arguments[4]!==undefined?arguments[4]:false;if(typeof Proxy==="undefined"){return;}if(pattern===""&&replacement!==""){var message="Pattern argument should not be empty string.";logMessage(source,message);return;}var shouldLog=pattern===""&&replacement==="";var shouldLogContent=verbose==="true";var nativeOpen=window.XMLHttpRequest.prototype.open;var nativeSend=window.XMLHttpRequest.prototype.send;var xhrData;var openWrapper=function openWrapper(target,thisArg,args){xhrData=getXhrData.apply(null,args);if(shouldLog){var _message="xhr( ".concat(objectToString(xhrData)," )");logMessage(source,_message,true);hit(source);return Reflect.apply(target,thisArg,args);}if(matchRequestProps(source,propsToMatch,xhrData)){thisArg.shouldBePrevented=true;thisArg.headersReceived=!!thisArg.headersReceived;}if(thisArg.shouldBePrevented&&!thisArg.headersReceived){thisArg.headersReceived=true;thisArg.collectedHeaders=[];var setRequestHeaderWrapper=function setRequestHeaderWrapper(target,thisArg,args){thisArg.collectedHeaders.push(args);return Reflect.apply(target,thisArg,args);};var setRequestHeaderHandler={apply:setRequestHeaderWrapper};thisArg.setRequestHeader=new Proxy(thisArg.setRequestHeader,setRequestHeaderHandler);}return Reflect.apply(target,thisArg,args);};var sendWrapper=function sendWrapper(target,thisArg,args){if(!thisArg.shouldBePrevented){return Reflect.apply(target,thisArg,args);}var forgedRequest=new XMLHttpRequest();forgedRequest.addEventListener("readystatechange",function(){if(forgedRequest.readyState!==4){return;}var readyState=forgedRequest.readyState,response=forgedRequest.response,responseText=forgedRequest.responseText,responseURL=forgedRequest.responseURL,responseXML=forgedRequest.responseXML,status=forgedRequest.status,statusText=forgedRequest.statusText;var content=responseText||response;if(typeof content!=="string"){return;}var patternRegexp=pattern==="*"?/(\n|.)*/:toRegExp(pattern);if(shouldLogContent){logMessage(source,"Original text content: ".concat(content));}var modifiedContent=content.replace(patternRegexp,replacement);if(shouldLogContent){logMessage(source,"Modified text content: ".concat(modifiedContent));}Object.defineProperties(thisArg,{readyState:{value:readyState,writable:false},responseURL:{value:responseURL,writable:false},responseXML:{value:responseXML,writable:false},status:{value:status,writable:false},statusText:{value:statusText,writable:false},response:{value:modifiedContent,writable:false},responseText:{value:modifiedContent,writable:false}});setTimeout(function(){var stateEvent=new Event("readystatechange");thisArg.dispatchEvent(stateEvent);var loadEvent=new Event("load");thisArg.dispatchEvent(loadEvent);var loadEndEvent=new Event("loadend");thisArg.dispatchEvent(loadEndEvent);},1);hit(source);});nativeOpen.apply(forgedRequest,[xhrData.method,xhrData.url]);thisArg.collectedHeaders.forEach(function(header){var name=header[0];var value=header[1];forgedRequest.setRequestHeader(name,value);});thisArg.collectedHeaders=[];try{nativeSend.call(forgedRequest,args);}catch(_unused){return Reflect.apply(target,thisArg,args);}return undefined;};var openHandler={apply:openWrapper};var sendHandler={apply:sendWrapper};XMLHttpRequest.prototype.open=new Proxy(XMLHttpRequest.prototype.open,openHandler);XMLHttpRequest.prototype.send=new Proxy(XMLHttpRequest.prototype.send,sendHandler);}function hit(source){var ADGUARD_PREFIX="[AdGuard]";if(!source.verbose){return;}try{var trace=console.trace.bind(console);var label="".concat(ADGUARD_PREFIX," ");if(source.engine==="corelibs"){label+=source.ruleText;}else {if(source.domainName){label+="".concat(source.domainName);}if(source.args){label+="#%#//scriptlet('".concat(source.name,"', '").concat(source.args.join("', '"),"')");}else {label+="#%#//scriptlet('".concat(source.name,"')");}}if(trace){trace(label);}}catch(e){}if(typeof window.__debug==="function"){window.__debug(source);}}function logMessage(source,message){var forced=arguments.length>2&&arguments[2]!==undefined?arguments[2]:false;var convertMessageToString=arguments.length>3&&arguments[3]!==undefined?arguments[3]:true;var name=source.name,verbose=source.verbose;if(!forced&&!verbose){return;}var nativeConsole=console.log;if(!convertMessageToString){nativeConsole("".concat(name,":"),message);return;}nativeConsole("".concat(name,": ").concat(message));}function toRegExp(rawInput){var input=rawInput||"";var DEFAULT_VALUE=".?";var FORWARD_SLASH="/";if(input===""){return new RegExp(DEFAULT_VALUE);}var delimiterIndex=input.lastIndexOf(FORWARD_SLASH);var flagsPart=input.substring(delimiterIndex+1);var regExpPart=input.substring(0,delimiterIndex+1);var isValidRegExpFlag=function isValidRegExpFlag(flag){if(!flag){return false;}try{new RegExp("",flag);return true;}catch(ex){return false;}};var getRegExpFlags=function getRegExpFlags(regExpStr,flagsStr){if(regExpStr.startsWith(FORWARD_SLASH)&&regExpStr.endsWith(FORWARD_SLASH)&&!regExpStr.endsWith("\\/")&&isValidRegExpFlag(flagsStr)){return flagsStr;}return "";};var flags=getRegExpFlags(regExpPart,flagsPart);if(input.startsWith(FORWARD_SLASH)&&input.endsWith(FORWARD_SLASH)||flags){var regExpInput=flags?regExpPart:input;return new RegExp(regExpInput.slice(1,-1),flags);}var escaped=input.replace(/\\'/g,"'").replace(/\\"/g,'"').replace(/[.*+?^${}()|[\]\\]/g,"\\$&");return new RegExp(escaped);}function objectToString(obj){if(!obj||typeof obj!=="object"){return String(obj);}if(isEmptyObject(obj)){return "{}";}return Object.entries(obj).map(function(pair){var key=pair[0];var value=pair[1];var recordValueStr=value;if(value instanceof Object){recordValueStr="{ ".concat(objectToString(value)," }");}return "".concat(key,':"').concat(recordValueStr,'"');}).join(" ");}function matchRequestProps(source,propsToMatch,requestData){if(propsToMatch===""||propsToMatch==="*"){return true;}var isMatched;var parsedData=parseMatchProps(propsToMatch);if(!isValidParsedData(parsedData)){logMessage(source,"Invalid parameter: ".concat(propsToMatch));isMatched=false;}else {var matchData=getMatchPropsData(parsedData);var matchKeys=Object.keys(matchData);isMatched=matchKeys.every(function(matchKey){var matchValue=matchData[matchKey];var dataValue=requestData[matchKey];return Object.prototype.hasOwnProperty.call(requestData,matchKey)&&typeof dataValue==="string"&&(matchValue===null||matchValue===void 0?void 0:matchValue.test(dataValue));});}return isMatched;}function getXhrData(method,url,async,user,password){return {method:method,url:url,async:async,user:user,password:password};}function getMatchPropsData(data){var matchData={};var dataKeys=Object.keys(data);dataKeys.forEach(function(key){matchData[key]=toRegExp(data[key]);});return matchData;}function getRequestProps(){return ["url","method","headers","body","credentials","cache","redirect","referrer","referrerPolicy","integrity","keepalive","signal","mode"];}function isValidParsedData(data){return Object.values(data).every(function(value){return isValidStrPattern(value);});}function parseMatchProps(propsToMatchStr){var PROPS_DIVIDER=" ";var PAIRS_MARKER=":";var isRequestProp=function isRequestProp(prop){return getRequestProps().includes(prop);};var propsObj={};var props=propsToMatchStr.split(PROPS_DIVIDER);props.forEach(function(prop){var dividerInd=prop.indexOf(PAIRS_MARKER);var key=prop.slice(0,dividerInd);if(isRequestProp(key)){var value=prop.slice(dividerInd+1);propsObj[key]=value;}else {propsObj.url=prop;}});return propsObj;}function isValidStrPattern(input){var FORWARD_SLASH="/";var str=escapeRegExp(input);if(input[0]===FORWARD_SLASH&&input[input.length-1]===FORWARD_SLASH){str=input.slice(1,-1);}var isValid;try{isValid=new RegExp(str);isValid=true;}catch(e){isValid=false;}return isValid;}function escapeRegExp(str){return str.replace(/[.*+?^${}()|[\]\\]/g,"\\$&");}function isEmptyObject(obj){return Object.keys(obj).length===0&&!obj.prototype;}var updatedArgs=args?[].concat(source).concat(args):[source];try{trustedReplaceXhrResponse.apply(this,updatedArgs);if(source.uniqueId){Object.defineProperty(Window.prototype.toString,uniqueIdentifier,{value:flag,enumerable:false,writable:false,configurable:false});}}catch(e){console.log(e);}}function trustedSetAttr(source,args){var flag="done";var uniqueIdentifier=source.uniqueId+source.name+"_"+(Array.isArray(args)?args.join("_"):"");if(source.uniqueId){if(Window.prototype.toString[uniqueIdentifier]===flag){return;}}function trustedSetAttr(source,selector,attr){var value=arguments.length>3&&arguments[3]!==undefined?arguments[3]:"";if(!selector||!attr){return;}setAttributeBySelector(source,selector,attr,value);observeDOMChanges(function(){return setAttributeBySelector(source,selector,attr,value);},true);}function setAttributeBySelector(source,selector,attribute,value){var attributeSetter=arguments.length>4&&arguments[4]!==undefined?arguments[4]:defaultAttributeSetter;var elements;try{elements=document.querySelectorAll(selector);}catch(_unused){logMessage(source,'Failed to find elements matching selector "'.concat(selector,'"'));return;}if(!elements||elements.length===0){return;}try{elements.forEach(function(elem){return attributeSetter(elem,attribute,value);});hit(source);}catch(_unused2){logMessage(source,"Failed to set [".concat(attribute,'="').concat(value,'"] to each of selected elements.'));}}function observeDOMChanges(callback){var observeAttrs=arguments.length>1&&arguments[1]!==undefined?arguments[1]:false;var attrsToObserve=arguments.length>2&&arguments[2]!==undefined?arguments[2]:[];var THROTTLE_DELAY_MS=20;var observer=new MutationObserver(throttle(callbackWrapper,THROTTLE_DELAY_MS));var connect=function connect(){if(attrsToObserve.length>0){observer.observe(document.documentElement,{childList:true,subtree:true,attributes:observeAttrs,attributeFilter:attrsToObserve});}else {observer.observe(document.documentElement,{childList:true,subtree:true,attributes:observeAttrs});}};var disconnect=function disconnect(){observer.disconnect();};function callbackWrapper(){disconnect();callback();connect();}connect();}function defaultAttributeSetter(elem,attribute,value){return elem.setAttribute(attribute,value);}function logMessage(source,message){var forced=arguments.length>2&&arguments[2]!==undefined?arguments[2]:false;var convertMessageToString=arguments.length>3&&arguments[3]!==undefined?arguments[3]:true;var name=source.name,verbose=source.verbose;if(!forced&&!verbose){return;}var nativeConsole=console.log;if(!convertMessageToString){nativeConsole("".concat(name,":"),message);return;}nativeConsole("".concat(name,": ").concat(message));}function throttle(cb,delay){var wait=false;var savedArgs;var wrapper=function wrapper(){for(var _len=arguments.length,args=new Array(_len),_key=0;_key<_len;_key++){args[_key]=arguments[_key];}if(wait){savedArgs=args;return;}cb(...args);wait=true;setTimeout(function(){wait=false;if(savedArgs){wrapper(...savedArgs);savedArgs=null;}},delay);};return wrapper;}function hit(source){var ADGUARD_PREFIX="[AdGuard]";if(!source.verbose){return;}try{var trace=console.trace.bind(console);var label="".concat(ADGUARD_PREFIX," ");if(source.engine==="corelibs"){label+=source.ruleText;}else {if(source.domainName){label+="".concat(source.domainName);}if(source.args){label+="#%#//scriptlet('".concat(source.name,"', '").concat(source.args.join("', '"),"')");}else {label+="#%#//scriptlet('".concat(source.name,"')");}}if(trace){trace(label);}}catch(e){}if(typeof window.__debug==="function"){window.__debug(source);}}var updatedArgs=args?[].concat(source).concat(args):[source];try{trustedSetAttr.apply(this,updatedArgs);if(source.uniqueId){Object.defineProperty(Window.prototype.toString,uniqueIdentifier,{value:flag,enumerable:false,writable:false,configurable:false});}}catch(e){console.log(e);}}function trustedSetConstant(source,args){var flag="done";var uniqueIdentifier=source.uniqueId+source.name+"_"+(Array.isArray(args)?args.join("_"):"");if(source.uniqueId){if(Window.prototype.toString[uniqueIdentifier]===flag){return;}}function trustedSetConstant(source,property,value,stack){if(!property||!matchStackTrace(stack,new Error().stack)){return;}var constantValue;try{constantValue=inferValue(value);}catch(e){logMessage(source,e);return;}var canceled=false;var mustCancel=function mustCancel(value){if(canceled){return canceled;}canceled=value!==undefined&&constantValue!==undefined&&typeof value!==typeof constantValue&&value!==null;return canceled;};var trapProp=function trapProp(base,prop,configurable,handler){if(!handler.init(base[prop])){return false;}var origDescriptor=Object.getOwnPropertyDescriptor(base,prop);var prevSetter;if(origDescriptor instanceof Object){if(!origDescriptor.configurable){var message="Property '".concat(prop,"' is not configurable");logMessage(source,message);return false;}base[prop]=constantValue;if(origDescriptor.set instanceof Function){prevSetter=origDescriptor.set;}}Object.defineProperty(base,prop,{configurable:configurable,get(){return handler.get();},set(a){if(prevSetter!==undefined){prevSetter(a);}handler.set(a);}});return true;};var setChainPropAccess=function setChainPropAccess(owner,property){var chainInfo=getPropertyInChain(owner,property);var base=chainInfo.base;var prop=chainInfo.prop,chain=chainInfo.chain;var inChainPropHandler={factValue:undefined,init(a){this.factValue=a;return true;},get(){return this.factValue;},set(a){if(this.factValue===a){return;}this.factValue=a;if(a instanceof Object){setChainPropAccess(a,chain);}}};var endPropHandler={init(a){if(mustCancel(a)){return false;}return true;},get(){return constantValue;},set(a){if(!mustCancel(a)){return;}constantValue=a;}};if(!chain){var isTrapped=trapProp(base,prop,false,endPropHandler);if(isTrapped){hit(source);}return;}if(base!==undefined&&base[prop]===null){trapProp(base,prop,true,inChainPropHandler);return;}if((base instanceof Object||typeof base==="object")&&isEmptyObject(base)){trapProp(base,prop,true,inChainPropHandler);}var propValue=owner[prop];if(propValue instanceof Object||typeof propValue==="object"&&propValue!==null){setChainPropAccess(propValue,chain);}trapProp(base,prop,true,inChainPropHandler);};setChainPropAccess(window,property);}function hit(source){var ADGUARD_PREFIX="[AdGuard]";if(!source.verbose){return;}try{var trace=console.trace.bind(console);var label="".concat(ADGUARD_PREFIX," ");if(source.engine==="corelibs"){label+=source.ruleText;}else {if(source.domainName){label+="".concat(source.domainName);}if(source.args){label+="#%#//scriptlet('".concat(source.name,"', '").concat(source.args.join("', '"),"')");}else {label+="#%#//scriptlet('".concat(source.name,"')");}}if(trace){trace(label);}}catch(e){}if(typeof window.__debug==="function"){window.__debug(source);}}function inferValue(value){if(value==="undefined"){return undefined;}if(value==="false"){return false;}if(value==="true"){return true;}if(value==="null"){return null;}if(value==="NaN"){return NaN;}if(value.startsWith("/")&&value.endsWith("/")){return toRegExp(value);}var MAX_ALLOWED_NUM=32767;var numVal=Number(value);if(!nativeIsNaN(numVal)){if(Math.abs(numVal)>MAX_ALLOWED_NUM){throw new Error("number values bigger than 32767 are not allowed");}return numVal;}var errorMessage="'".concat(value,"' value type can't be inferred");try{var parsableVal=JSON.parse(value);if(parsableVal instanceof Object||typeof parsableVal==="string"){return parsableVal;}}catch(e){errorMessage+=": ".concat(e);}throw new TypeError(errorMessage);}function logMessage(source,message){var forced=arguments.length>2&&arguments[2]!==undefined?arguments[2]:false;var convertMessageToString=arguments.length>3&&arguments[3]!==undefined?arguments[3]:true;var name=source.name,verbose=source.verbose;if(!forced&&!verbose){return;}var nativeConsole=console.log;if(!convertMessageToString){nativeConsole("".concat(name,":"),message);return;}nativeConsole("".concat(name,": ").concat(message));}function getPropertyInChain(base,chain){var pos=chain.indexOf(".");if(pos===-1){return {base:base,prop:chain};}var prop=chain.slice(0,pos);if(base===null){return {base:base,prop:prop,chain:chain};}var nextBase=base[prop];chain=chain.slice(pos+1);if((base instanceof Object||typeof base==="object")&&isEmptyObject(base)){return {base:base,prop:prop,chain:chain};}if(nextBase===null){return {base:base,prop:prop,chain:chain};}if(nextBase!==undefined){return getPropertyInChain(nextBase,chain);}Object.defineProperty(base,prop,{configurable:true});return {base:base,prop:prop,chain:chain};}function toRegExp(rawInput){var input=rawInput||"";var DEFAULT_VALUE=".?";var FORWARD_SLASH="/";if(input===""){return new RegExp(DEFAULT_VALUE);}var delimiterIndex=input.lastIndexOf(FORWARD_SLASH);var flagsPart=input.substring(delimiterIndex+1);var regExpPart=input.substring(0,delimiterIndex+1);var isValidRegExpFlag=function isValidRegExpFlag(flag){if(!flag){return false;}try{new RegExp("",flag);return true;}catch(ex){return false;}};var getRegExpFlags=function getRegExpFlags(regExpStr,flagsStr){if(regExpStr.startsWith(FORWARD_SLASH)&&regExpStr.endsWith(FORWARD_SLASH)&&!regExpStr.endsWith("\\/")&&isValidRegExpFlag(flagsStr)){return flagsStr;}return "";};var flags=getRegExpFlags(regExpPart,flagsPart);if(input.startsWith(FORWARD_SLASH)&&input.endsWith(FORWARD_SLASH)||flags){var regExpInput=flags?regExpPart:input;return new RegExp(regExpInput.slice(1,-1),flags);}var escaped=input.replace(/\\'/g,"'").replace(/\\"/g,'"').replace(/[.*+?^${}()|[\]\\]/g,"\\$&");return new RegExp(escaped);}function matchStackTrace(stackMatch,stackTrace){if(!stackMatch||stackMatch===""){return true;}var regExpValues=backupRegExpValues();if(shouldAbortInlineOrInjectedScript(stackMatch,stackTrace)){if(regExpValues.length&&regExpValues[0]!==RegExp.$1){restoreRegExpValues(regExpValues);}return true;}var stackRegexp=toRegExp(stackMatch);var refinedStackTrace=stackTrace.split("\n").slice(2).map(function(line){return line.trim();}).join("\n");if(regExpValues.length&&regExpValues[0]!==RegExp.$1){restoreRegExpValues(regExpValues);}return getNativeRegexpTest().call(stackRegexp,refinedStackTrace);}function nativeIsNaN(num){var native=Number.isNaN||window.isNaN;return native(num);}function isEmptyObject(obj){return Object.keys(obj).length===0&&!obj.prototype;}function getNativeRegexpTest(){var descriptor=Object.getOwnPropertyDescriptor(RegExp.prototype,"test");var nativeRegexTest=descriptor===null||descriptor===void 0?void 0:descriptor.value;if(descriptor&&typeof descriptor.value==="function"){return nativeRegexTest;}throw new Error("RegExp.prototype.test is not a function");}function shouldAbortInlineOrInjectedScript(stackMatch,stackTrace){var INLINE_SCRIPT_STRING="inlineScript";var INJECTED_SCRIPT_STRING="injectedScript";var INJECTED_SCRIPT_MARKER="<anonymous>";var isInlineScript=function isInlineScript(match){return match.includes(INLINE_SCRIPT_STRING);};var isInjectedScript=function isInjectedScript(match){return match.includes(INJECTED_SCRIPT_STRING);};if(!(isInlineScript(stackMatch)||isInjectedScript(stackMatch))){return false;}var documentURL=window.location.href;var pos=documentURL.indexOf("#");if(pos!==-1){documentURL=documentURL.slice(0,pos);}var stackSteps=stackTrace.split("\n").slice(2).map(function(line){return line.trim();});var stackLines=stackSteps.map(function(line){var stack;var getStackTraceValues=/(.*?@)?(\S+)(:\d+)(:\d+)\)?$/.exec(line);if(getStackTraceValues){var _stackURL,_stackURL2;var stackURL=getStackTraceValues[2];var stackLine=getStackTraceValues[3];var stackCol=getStackTraceValues[4];if((_stackURL=stackURL)!==null&&_stackURL!==void 0&&_stackURL.startsWith("(")){stackURL=stackURL.slice(1);}if((_stackURL2=stackURL)!==null&&_stackURL2!==void 0&&_stackURL2.startsWith(INJECTED_SCRIPT_MARKER)){var _stackFunction;stackURL=INJECTED_SCRIPT_STRING;var stackFunction=getStackTraceValues[1]!==undefined?getStackTraceValues[1].slice(0,-1):line.slice(0,getStackTraceValues.index).trim();if((_stackFunction=stackFunction)!==null&&_stackFunction!==void 0&&_stackFunction.startsWith("at")){stackFunction=stackFunction.slice(2).trim();}stack="".concat(stackFunction," ").concat(stackURL).concat(stackLine).concat(stackCol).trim();}else if(stackURL===documentURL){stack="".concat(INLINE_SCRIPT_STRING).concat(stackLine).concat(stackCol).trim();}else {stack="".concat(stackURL).concat(stackLine).concat(stackCol).trim();}}else {stack=line;}return stack;});if(stackLines){for(var index=0;index<stackLines.length;index+=1){if(isInlineScript(stackMatch)&&stackLines[index].startsWith(INLINE_SCRIPT_STRING)&&stackLines[index].match(toRegExp(stackMatch))){return true;}if(isInjectedScript(stackMatch)&&stackLines[index].startsWith(INJECTED_SCRIPT_STRING)&&stackLines[index].match(toRegExp(stackMatch))){return true;}}}return false;}function backupRegExpValues(){try{var arrayOfRegexpValues=[];for(var index=1;index<10;index+=1){var value="$".concat(index);if(!RegExp[value]){break;}arrayOfRegexpValues.push(RegExp[value]);}return arrayOfRegexpValues;}catch(error){return [];}}function restoreRegExpValues(array){if(!array.length){return;}try{var stringPattern="";if(array.length===1){stringPattern="(".concat(array[0],")");}else {stringPattern=array.reduce(function(accumulator,currentValue,currentIndex){if(currentIndex===1){return "(".concat(accumulator,"),(").concat(currentValue,")");}return "".concat(accumulator,",(").concat(currentValue,")");});}var regExpGroup=new RegExp(stringPattern);array.toString().replace(regExpGroup,"");}catch(error){var message="Failed to restore RegExp values: ".concat(error);console.log(message);}}var updatedArgs=args?[].concat(source).concat(args):[source];try{trustedSetConstant.apply(this,updatedArgs);if(source.uniqueId){Object.defineProperty(Window.prototype.toString,uniqueIdentifier,{value:flag,enumerable:false,writable:false,configurable:false});}}catch(e){console.log(e);}}function trustedSetCookie(source,args){var flag="done";var uniqueIdentifier=source.uniqueId+source.name+"_"+(Array.isArray(args)?args.join("_"):"");if(source.uniqueId){if(Window.prototype.toString[uniqueIdentifier]===flag){return;}}function trustedSetCookie(source,name,value){var offsetExpiresSec=arguments.length>3&&arguments[3]!==undefined?arguments[3]:"";var path=arguments.length>4&&arguments[4]!==undefined?arguments[4]:"/";var domain=arguments.length>5&&arguments[5]!==undefined?arguments[5]:"";if(typeof name==="undefined"){logMessage(source,"Cookie name should be specified");return;}if(typeof value==="undefined"){logMessage(source,"Cookie value should be specified");return;}var parsedValue=parseKeywordValue(value);if(!isValidCookiePath(path)){logMessage(source,"Invalid cookie path: '".concat(path,"'"));return;}if(!document.location.origin.includes(domain)){logMessage(source,"Cookie domain not matched by origin: '".concat(domain,"'"));return;}var cookieToSet=serializeCookie(name,parsedValue,path,domain,false);if(!cookieToSet){logMessage(source,"Invalid cookie name or value");return;}if(offsetExpiresSec){var parsedOffsetMs=getTrustedCookieOffsetMs(offsetExpiresSec);if(!parsedOffsetMs){logMessage(source,"Invalid offsetExpiresSec value: ".concat(offsetExpiresSec));return;}var expires=Date.now()+parsedOffsetMs;cookieToSet+="; expires=".concat(new Date(expires).toUTCString());}document.cookie=cookieToSet;hit(source);}function hit(source){var ADGUARD_PREFIX="[AdGuard]";if(!source.verbose){return;}try{var trace=console.trace.bind(console);var label="".concat(ADGUARD_PREFIX," ");if(source.engine==="corelibs"){label+=source.ruleText;}else {if(source.domainName){label+="".concat(source.domainName);}if(source.args){label+="#%#//scriptlet('".concat(source.name,"', '").concat(source.args.join("', '"),"')");}else {label+="#%#//scriptlet('".concat(source.name,"')");}}if(trace){trace(label);}}catch(e){}if(typeof window.__debug==="function"){window.__debug(source);}}function logMessage(source,message){var forced=arguments.length>2&&arguments[2]!==undefined?arguments[2]:false;var convertMessageToString=arguments.length>3&&arguments[3]!==undefined?arguments[3]:true;var name=source.name,verbose=source.verbose;if(!forced&&!verbose){return;}var nativeConsole=console.log;if(!convertMessageToString){nativeConsole("".concat(name,":"),message);return;}nativeConsole("".concat(name,": ").concat(message));}function serializeCookie(name,rawValue,rawPath){var domainValue=arguments.length>3&&arguments[3]!==undefined?arguments[3]:"";var shouldEncodeValue=arguments.length>4&&arguments[4]!==undefined?arguments[4]:true;var HOST_PREFIX="__Host-";var SECURE_PREFIX="__Secure-";var COOKIE_BREAKER=";";if(!shouldEncodeValue&&"".concat(rawValue).includes(COOKIE_BREAKER)||name.includes(COOKIE_BREAKER)){return null;}var value=shouldEncodeValue?encodeURIComponent(rawValue):rawValue;var resultCookie="".concat(name,"=").concat(value);if(name.startsWith(HOST_PREFIX)){resultCookie+="; path=/; secure";if(domainValue){console.debug('Domain value: "'.concat(domainValue,'" has been ignored, because is not allowed for __Host- prefixed cookies'));}return resultCookie;}var path=getCookiePath(rawPath);if(path){resultCookie+="; ".concat(path);}if(name.startsWith(SECURE_PREFIX)){resultCookie+="; secure";}if(domainValue){resultCookie+="; domain=".concat(domainValue);}return resultCookie;}function isValidCookiePath(rawPath){return rawPath==="/"||rawPath==="none";}function getTrustedCookieOffsetMs(offsetExpiresSec){var ONE_YEAR_EXPIRATION_KEYWORD="1year";var ONE_DAY_EXPIRATION_KEYWORD="1day";var MS_IN_SEC=1e3;var SECONDS_IN_YEAR=365*24*60*60;var SECONDS_IN_DAY=24*60*60;var parsedSec;if(offsetExpiresSec===ONE_YEAR_EXPIRATION_KEYWORD){parsedSec=SECONDS_IN_YEAR;}else if(offsetExpiresSec===ONE_DAY_EXPIRATION_KEYWORD){parsedSec=SECONDS_IN_DAY;}else {parsedSec=Number.parseInt(offsetExpiresSec,10);if(Number.isNaN(parsedSec)){return null;}}return parsedSec*MS_IN_SEC;}function parseKeywordValue(rawValue){var NOW_VALUE_KEYWORD="$now$";var CURRENT_DATE_KEYWORD="$currentDate$";var CURRENT_ISO_DATE_KEYWORD="$currentISODate$";var parsedValue=rawValue;if(rawValue===NOW_VALUE_KEYWORD){parsedValue=Date.now().toString();}else if(rawValue===CURRENT_DATE_KEYWORD){parsedValue=Date();}else if(rawValue===CURRENT_ISO_DATE_KEYWORD){parsedValue=new Date().toISOString();}return parsedValue;}function getCookiePath(rawPath){if(rawPath==="/"){return "path=/";}return "";}var updatedArgs=args?[].concat(source).concat(args):[source];try{trustedSetCookie.apply(this,updatedArgs);if(source.uniqueId){Object.defineProperty(Window.prototype.toString,uniqueIdentifier,{value:flag,enumerable:false,writable:false,configurable:false});}}catch(e){console.log(e);}}function trustedSetCookieReload(source,args){var flag="done";var uniqueIdentifier=source.uniqueId+source.name+"_"+(Array.isArray(args)?args.join("_"):"");if(source.uniqueId){if(Window.prototype.toString[uniqueIdentifier]===flag){return;}}function trustedSetCookieReload(source,name,value){var offsetExpiresSec=arguments.length>3&&arguments[3]!==undefined?arguments[3]:"";var path=arguments.length>4&&arguments[4]!==undefined?arguments[4]:"/";var domain=arguments.length>5&&arguments[5]!==undefined?arguments[5]:"";if(typeof name==="undefined"){logMessage(source,"Cookie name should be specified");return;}if(typeof value==="undefined"){logMessage(source,"Cookie value should be specified");return;}if(isCookieSetWithValue(document.cookie,name,value)){return;}var parsedValue=parseKeywordValue(value);if(!isValidCookiePath(path)){logMessage(source,"Invalid cookie path: '".concat(path,"'"));return;}if(!document.location.origin.includes(domain)){logMessage(source,"Cookie domain not matched by origin: '".concat(domain,"'"));return;}var cookieToSet=serializeCookie(name,parsedValue,path,domain,false);if(!cookieToSet){logMessage(source,"Invalid cookie name or value");return;}if(offsetExpiresSec){var parsedOffsetMs=getTrustedCookieOffsetMs(offsetExpiresSec);if(!parsedOffsetMs){logMessage(source,"Invalid offsetExpiresSec value: ".concat(offsetExpiresSec));return;}var expires=Date.now()+parsedOffsetMs;cookieToSet+="; expires=".concat(new Date(expires).toUTCString());}document.cookie=cookieToSet;hit(source);var cookieValueToCheck=parseCookieString(document.cookie)[name];if(isCookieSetWithValue(document.cookie,name,cookieValueToCheck)){window.location.reload();}}function hit(source){var ADGUARD_PREFIX="[AdGuard]";if(!source.verbose){return;}try{var trace=console.trace.bind(console);var label="".concat(ADGUARD_PREFIX," ");if(source.engine==="corelibs"){label+=source.ruleText;}else {if(source.domainName){label+="".concat(source.domainName);}if(source.args){label+="#%#//scriptlet('".concat(source.name,"', '").concat(source.args.join("', '"),"')");}else {label+="#%#//scriptlet('".concat(source.name,"')");}}if(trace){trace(label);}}catch(e){}if(typeof window.__debug==="function"){window.__debug(source);}}function logMessage(source,message){var forced=arguments.length>2&&arguments[2]!==undefined?arguments[2]:false;var convertMessageToString=arguments.length>3&&arguments[3]!==undefined?arguments[3]:true;var name=source.name,verbose=source.verbose;if(!forced&&!verbose){return;}var nativeConsole=console.log;if(!convertMessageToString){nativeConsole("".concat(name,":"),message);return;}nativeConsole("".concat(name,": ").concat(message));}function isCookieSetWithValue(cookieString,name,value){return cookieString.split(";").some(function(cookieStr){var pos=cookieStr.indexOf("=");if(pos===-1){return false;}var cookieName=cookieStr.slice(0,pos).trim();var cookieValue=cookieStr.slice(pos+1).trim();return name===cookieName&&value===cookieValue;});}function serializeCookie(name,rawValue,rawPath){var domainValue=arguments.length>3&&arguments[3]!==undefined?arguments[3]:"";var shouldEncodeValue=arguments.length>4&&arguments[4]!==undefined?arguments[4]:true;var HOST_PREFIX="__Host-";var SECURE_PREFIX="__Secure-";var COOKIE_BREAKER=";";if(!shouldEncodeValue&&"".concat(rawValue).includes(COOKIE_BREAKER)||name.includes(COOKIE_BREAKER)){return null;}var value=shouldEncodeValue?encodeURIComponent(rawValue):rawValue;var resultCookie="".concat(name,"=").concat(value);if(name.startsWith(HOST_PREFIX)){resultCookie+="; path=/; secure";if(domainValue){console.debug('Domain value: "'.concat(domainValue,'" has been ignored, because is not allowed for __Host- prefixed cookies'));}return resultCookie;}var path=getCookiePath(rawPath);if(path){resultCookie+="; ".concat(path);}if(name.startsWith(SECURE_PREFIX)){resultCookie+="; secure";}if(domainValue){resultCookie+="; domain=".concat(domainValue);}return resultCookie;}function isValidCookiePath(rawPath){return rawPath==="/"||rawPath==="none";}function getTrustedCookieOffsetMs(offsetExpiresSec){var ONE_YEAR_EXPIRATION_KEYWORD="1year";var ONE_DAY_EXPIRATION_KEYWORD="1day";var MS_IN_SEC=1e3;var SECONDS_IN_YEAR=365*24*60*60;var SECONDS_IN_DAY=24*60*60;var parsedSec;if(offsetExpiresSec===ONE_YEAR_EXPIRATION_KEYWORD){parsedSec=SECONDS_IN_YEAR;}else if(offsetExpiresSec===ONE_DAY_EXPIRATION_KEYWORD){parsedSec=SECONDS_IN_DAY;}else {parsedSec=Number.parseInt(offsetExpiresSec,10);if(Number.isNaN(parsedSec)){return null;}}return parsedSec*MS_IN_SEC;}function parseKeywordValue(rawValue){var NOW_VALUE_KEYWORD="$now$";var CURRENT_DATE_KEYWORD="$currentDate$";var CURRENT_ISO_DATE_KEYWORD="$currentISODate$";var parsedValue=rawValue;if(rawValue===NOW_VALUE_KEYWORD){parsedValue=Date.now().toString();}else if(rawValue===CURRENT_DATE_KEYWORD){parsedValue=Date();}else if(rawValue===CURRENT_ISO_DATE_KEYWORD){parsedValue=new Date().toISOString();}return parsedValue;}function parseCookieString(cookieString){var COOKIE_DELIMITER="=";var COOKIE_PAIRS_DELIMITER=";";var cookieChunks=cookieString.split(COOKIE_PAIRS_DELIMITER);var cookieData={};cookieChunks.forEach(function(singleCookie){var cookieKey;var cookieValue="";var delimiterIndex=singleCookie.indexOf(COOKIE_DELIMITER);if(delimiterIndex===-1){cookieKey=singleCookie.trim();}else {cookieKey=singleCookie.slice(0,delimiterIndex).trim();cookieValue=singleCookie.slice(delimiterIndex+1);}cookieData[cookieKey]=cookieValue||null;});return cookieData;}function getCookiePath(rawPath){if(rawPath==="/"){return "path=/";}return "";}var updatedArgs=args?[].concat(source).concat(args):[source];try{trustedSetCookieReload.apply(this,updatedArgs);if(source.uniqueId){Object.defineProperty(Window.prototype.toString,uniqueIdentifier,{value:flag,enumerable:false,writable:false,configurable:false});}}catch(e){console.log(e);}}function trustedSetLocalStorageItem(source,args){var flag="done";var uniqueIdentifier=source.uniqueId+source.name+"_"+(Array.isArray(args)?args.join("_"):"");if(source.uniqueId){if(Window.prototype.toString[uniqueIdentifier]===flag){return;}}function trustedSetLocalStorageItem(source,key,value){if(typeof key==="undefined"){logMessage(source,"Item key should be specified");return;}if(typeof value==="undefined"){logMessage(source,"Item value should be specified");return;}var parsedValue=parseKeywordValue(value);var _window=window,localStorage=_window.localStorage;setStorageItem(source,localStorage,key,parsedValue);hit(source);}function hit(source){var ADGUARD_PREFIX="[AdGuard]";if(!source.verbose){return;}try{var trace=console.trace.bind(console);var label="".concat(ADGUARD_PREFIX," ");if(source.engine==="corelibs"){label+=source.ruleText;}else {if(source.domainName){label+="".concat(source.domainName);}if(source.args){label+="#%#//scriptlet('".concat(source.name,"', '").concat(source.args.join("', '"),"')");}else {label+="#%#//scriptlet('".concat(source.name,"')");}}if(trace){trace(label);}}catch(e){}if(typeof window.__debug==="function"){window.__debug(source);}}function logMessage(source,message){var forced=arguments.length>2&&arguments[2]!==undefined?arguments[2]:false;var convertMessageToString=arguments.length>3&&arguments[3]!==undefined?arguments[3]:true;var name=source.name,verbose=source.verbose;if(!forced&&!verbose){return;}var nativeConsole=console.log;if(!convertMessageToString){nativeConsole("".concat(name,":"),message);return;}nativeConsole("".concat(name,": ").concat(message));}function setStorageItem(source,storage,key,value){try{storage.setItem(key,value);}catch(e){var message="Unable to set sessionStorage item due to: ".concat(e.message);logMessage(source,message);}}function parseKeywordValue(rawValue){var NOW_VALUE_KEYWORD="$now$";var CURRENT_DATE_KEYWORD="$currentDate$";var CURRENT_ISO_DATE_KEYWORD="$currentISODate$";var parsedValue=rawValue;if(rawValue===NOW_VALUE_KEYWORD){parsedValue=Date.now().toString();}else if(rawValue===CURRENT_DATE_KEYWORD){parsedValue=Date();}else if(rawValue===CURRENT_ISO_DATE_KEYWORD){parsedValue=new Date().toISOString();}return parsedValue;}var updatedArgs=args?[].concat(source).concat(args):[source];try{trustedSetLocalStorageItem.apply(this,updatedArgs);if(source.uniqueId){Object.defineProperty(Window.prototype.toString,uniqueIdentifier,{value:flag,enumerable:false,writable:false,configurable:false});}}catch(e){console.log(e);}}function trustedSetSessionStorageItem(source,args){var flag="done";var uniqueIdentifier=source.uniqueId+source.name+"_"+(Array.isArray(args)?args.join("_"):"");if(source.uniqueId){if(Window.prototype.toString[uniqueIdentifier]===flag){return;}}function trustedSetSessionStorageItem(source,key,value){if(typeof key==="undefined"){logMessage(source,"Item key should be specified");return;}if(typeof value==="undefined"){logMessage(source,"Item value should be specified");return;}var parsedValue=parseKeywordValue(value);var _window=window,sessionStorage=_window.sessionStorage;setStorageItem(source,sessionStorage,key,parsedValue);hit(source);}function hit(source){var ADGUARD_PREFIX="[AdGuard]";if(!source.verbose){return;}try{var trace=console.trace.bind(console);var label="".concat(ADGUARD_PREFIX," ");if(source.engine==="corelibs"){label+=source.ruleText;}else {if(source.domainName){label+="".concat(source.domainName);}if(source.args){label+="#%#//scriptlet('".concat(source.name,"', '").concat(source.args.join("', '"),"')");}else {label+="#%#//scriptlet('".concat(source.name,"')");}}if(trace){trace(label);}}catch(e){}if(typeof window.__debug==="function"){window.__debug(source);}}function logMessage(source,message){var forced=arguments.length>2&&arguments[2]!==undefined?arguments[2]:false;var convertMessageToString=arguments.length>3&&arguments[3]!==undefined?arguments[3]:true;var name=source.name,verbose=source.verbose;if(!forced&&!verbose){return;}var nativeConsole=console.log;if(!convertMessageToString){nativeConsole("".concat(name,":"),message);return;}nativeConsole("".concat(name,": ").concat(message));}function setStorageItem(source,storage,key,value){try{storage.setItem(key,value);}catch(e){var message="Unable to set sessionStorage item due to: ".concat(e.message);logMessage(source,message);}}function parseKeywordValue(rawValue){var NOW_VALUE_KEYWORD="$now$";var CURRENT_DATE_KEYWORD="$currentDate$";var CURRENT_ISO_DATE_KEYWORD="$currentISODate$";var parsedValue=rawValue;if(rawValue===NOW_VALUE_KEYWORD){parsedValue=Date.now().toString();}else if(rawValue===CURRENT_DATE_KEYWORD){parsedValue=Date();}else if(rawValue===CURRENT_ISO_DATE_KEYWORD){parsedValue=new Date().toISOString();}return parsedValue;}var updatedArgs=args?[].concat(source).concat(args):[source];try{trustedSetSessionStorageItem.apply(this,updatedArgs);if(source.uniqueId){Object.defineProperty(Window.prototype.toString,uniqueIdentifier,{value:flag,enumerable:false,writable:false,configurable:false});}}catch(e){console.log(e);}}function trustedSuppressNativeMethod(source,args){var flag="done";var uniqueIdentifier=source.uniqueId+source.name+"_"+(Array.isArray(args)?args.join("_"):"");if(source.uniqueId){if(Window.prototype.toString[uniqueIdentifier]===flag){return;}}function trustedSuppressNativeMethod(source,methodPath,signatureStr){var how=arguments.length>3&&arguments[3]!==undefined?arguments[3]:"abort";var stack=arguments.length>4&&arguments[4]!==undefined?arguments[4]:"";if(!methodPath||!signatureStr){return;}var IGNORE_ARG_SYMBOL=" ";var suppress=how==="abort"?getAbortFunc():function(){};var signatureMatcher;try{signatureMatcher=signatureStr.split("|").map(function(value){return value===IGNORE_ARG_SYMBOL?value:inferValue(value);});}catch(e){logMessage(source,"Could not parse the signature matcher: ".concat(getErrorMessage(e)));return;}var getPathParts=getPropertyInChain;var _getPathParts=getPathParts(window,methodPath),base=_getPathParts.base,chain=_getPathParts.chain,prop=_getPathParts.prop;if(typeof chain!=="undefined"){logMessage(source,"Could not reach the end of the prop chain: ".concat(methodPath));return;}var nativeMethod=base[prop];if(!nativeMethod||typeof nativeMethod!=="function"){logMessage(source,"Could not retrieve the method: ".concat(methodPath));return;}function matchMethodCall(nativeArguments,matchArguments){return matchArguments.every(function(matcher,i){if(matcher===IGNORE_ARG_SYMBOL){return true;}var argument=nativeArguments[i];return isValueMatched(argument,matcher);});}var isMatchingSuspended=false;function apply(target,thisArg,argumentsList){if(isMatchingSuspended){return Reflect.apply(target,thisArg,argumentsList);}isMatchingSuspended=true;if(stack&&!matchStackTrace(stack,new Error().stack||"")){return Reflect.apply(target,thisArg,argumentsList);}var isMatching=matchMethodCall(argumentsList,signatureMatcher);isMatchingSuspended=false;if(isMatching){hit(source);return suppress();}return Reflect.apply(target,thisArg,argumentsList);}base[prop]=new Proxy(nativeMethod,{apply:apply});}function hit(source){var ADGUARD_PREFIX="[AdGuard]";if(!source.verbose){return;}try{var trace=console.trace.bind(console);var label="".concat(ADGUARD_PREFIX," ");if(source.engine==="corelibs"){label+=source.ruleText;}else {if(source.domainName){label+="".concat(source.domainName);}if(source.args){label+="#%#//scriptlet('".concat(source.name,"', '").concat(source.args.join("', '"),"')");}else {label+="#%#//scriptlet('".concat(source.name,"')");}}if(trace){trace(label);}}catch(e){}if(typeof window.__debug==="function"){window.__debug(source);}}function logMessage(source,message){var forced=arguments.length>2&&arguments[2]!==undefined?arguments[2]:false;var convertMessageToString=arguments.length>3&&arguments[3]!==undefined?arguments[3]:true;var name=source.name,verbose=source.verbose;if(!forced&&!verbose){return;}var nativeConsole=console.log;if(!convertMessageToString){nativeConsole("".concat(name,":"),message);return;}nativeConsole("".concat(name,": ").concat(message));}function getPropertyInChain(base,chain){var pos=chain.indexOf(".");if(pos===-1){return {base:base,prop:chain};}var prop=chain.slice(0,pos);if(base===null){return {base:base,prop:prop,chain:chain};}var nextBase=base[prop];chain=chain.slice(pos+1);if((base instanceof Object||typeof base==="object")&&isEmptyObject(base)){return {base:base,prop:prop,chain:chain};}if(nextBase===null){return {base:base,prop:prop,chain:chain};}if(nextBase!==undefined){return getPropertyInChain(nextBase,chain);}Object.defineProperty(base,prop,{configurable:true});return {base:base,prop:prop,chain:chain};}function inferValue(value){if(value==="undefined"){return undefined;}if(value==="false"){return false;}if(value==="true"){return true;}if(value==="null"){return null;}if(value==="NaN"){return NaN;}if(value.startsWith("/")&&value.endsWith("/")){return toRegExp(value);}var MAX_ALLOWED_NUM=32767;var numVal=Number(value);if(!nativeIsNaN(numVal)){if(Math.abs(numVal)>MAX_ALLOWED_NUM){throw new Error("number values bigger than 32767 are not allowed");}return numVal;}var errorMessage="'".concat(value,"' value type can't be inferred");try{var parsableVal=JSON.parse(value);if(parsableVal instanceof Object||typeof parsableVal==="string"){return parsableVal;}}catch(e){errorMessage+=": ".concat(e);}throw new TypeError(errorMessage);}function isValueMatched(value,matcher){if(typeof value==="function"){return false;}if(nativeIsNaN(value)){return nativeIsNaN(matcher);}if(value===null||typeof value==="undefined"||typeof value==="number"||typeof value==="boolean"){return value===matcher;}if(typeof value==="string"){if(typeof matcher==="string"||matcher instanceof RegExp){return isStringMatched(value,matcher);}return false;}if(Array.isArray(value)&&Array.isArray(matcher)){return isArrayMatched(value,matcher);}if(isArbitraryObject(value)&&isArbitraryObject(matcher)){return isObjectMatched(value,matcher);}return false;}function getAbortFunc(){var rid=randomId();var isErrorHandlerSet=false;return function abort(){if(!isErrorHandlerSet){window.onerror=createOnErrorHandler(rid);isErrorHandlerSet=true;}throw new ReferenceError(rid);};}function matchStackTrace(stackMatch,stackTrace){if(!stackMatch||stackMatch===""){return true;}var regExpValues=backupRegExpValues();if(shouldAbortInlineOrInjectedScript(stackMatch,stackTrace)){if(regExpValues.length&&regExpValues[0]!==RegExp.$1){restoreRegExpValues(regExpValues);}return true;}var stackRegexp=toRegExp(stackMatch);var refinedStackTrace=stackTrace.split("\n").slice(2).map(function(line){return line.trim();}).join("\n");if(regExpValues.length&&regExpValues[0]!==RegExp.$1){restoreRegExpValues(regExpValues);}return getNativeRegexpTest().call(stackRegexp,refinedStackTrace);}function getErrorMessage(error){var isErrorWithMessage=function isErrorWithMessage(e){return typeof e==="object"&&e!==null&&"message"in e&&typeof e.message==="string";};if(isErrorWithMessage(error)){return error.message;}try{return new Error(JSON.stringify(error)).message;}catch(_unused){return new Error(String(error)).message;}}function shouldAbortInlineOrInjectedScript(stackMatch,stackTrace){var INLINE_SCRIPT_STRING="inlineScript";var INJECTED_SCRIPT_STRING="injectedScript";var INJECTED_SCRIPT_MARKER="<anonymous>";var isInlineScript=function isInlineScript(match){return match.includes(INLINE_SCRIPT_STRING);};var isInjectedScript=function isInjectedScript(match){return match.includes(INJECTED_SCRIPT_STRING);};if(!(isInlineScript(stackMatch)||isInjectedScript(stackMatch))){return false;}var documentURL=window.location.href;var pos=documentURL.indexOf("#");if(pos!==-1){documentURL=documentURL.slice(0,pos);}var stackSteps=stackTrace.split("\n").slice(2).map(function(line){return line.trim();});var stackLines=stackSteps.map(function(line){var stack;var getStackTraceValues=/(.*?@)?(\S+)(:\d+)(:\d+)\)?$/.exec(line);if(getStackTraceValues){var _stackURL,_stackURL2;var stackURL=getStackTraceValues[2];var stackLine=getStackTraceValues[3];var stackCol=getStackTraceValues[4];if((_stackURL=stackURL)!==null&&_stackURL!==void 0&&_stackURL.startsWith("(")){stackURL=stackURL.slice(1);}if((_stackURL2=stackURL)!==null&&_stackURL2!==void 0&&_stackURL2.startsWith(INJECTED_SCRIPT_MARKER)){var _stackFunction;stackURL=INJECTED_SCRIPT_STRING;var stackFunction=getStackTraceValues[1]!==undefined?getStackTraceValues[1].slice(0,-1):line.slice(0,getStackTraceValues.index).trim();if((_stackFunction=stackFunction)!==null&&_stackFunction!==void 0&&_stackFunction.startsWith("at")){stackFunction=stackFunction.slice(2).trim();}stack="".concat(stackFunction," ").concat(stackURL).concat(stackLine).concat(stackCol).trim();}else if(stackURL===documentURL){stack="".concat(INLINE_SCRIPT_STRING).concat(stackLine).concat(stackCol).trim();}else {stack="".concat(stackURL).concat(stackLine).concat(stackCol).trim();}}else {stack=line;}return stack;});if(stackLines){for(var index=0;index<stackLines.length;index+=1){if(isInlineScript(stackMatch)&&stackLines[index].startsWith(INLINE_SCRIPT_STRING)&&stackLines[index].match(toRegExp(stackMatch))){return true;}if(isInjectedScript(stackMatch)&&stackLines[index].startsWith(INJECTED_SCRIPT_STRING)&&stackLines[index].match(toRegExp(stackMatch))){return true;}}}return false;}function getNativeRegexpTest(){var descriptor=Object.getOwnPropertyDescriptor(RegExp.prototype,"test");var nativeRegexTest=descriptor===null||descriptor===void 0?void 0:descriptor.value;if(descriptor&&typeof descriptor.value==="function"){return nativeRegexTest;}throw new Error("RegExp.prototype.test is not a function");}function toRegExp(rawInput){var input=rawInput||"";var DEFAULT_VALUE=".?";var FORWARD_SLASH="/";if(input===""){return new RegExp(DEFAULT_VALUE);}var delimiterIndex=input.lastIndexOf(FORWARD_SLASH);var flagsPart=input.substring(delimiterIndex+1);var regExpPart=input.substring(0,delimiterIndex+1);var isValidRegExpFlag=function isValidRegExpFlag(flag){if(!flag){return false;}try{new RegExp("",flag);return true;}catch(ex){return false;}};var getRegExpFlags=function getRegExpFlags(regExpStr,flagsStr){if(regExpStr.startsWith(FORWARD_SLASH)&&regExpStr.endsWith(FORWARD_SLASH)&&!regExpStr.endsWith("\\/")&&isValidRegExpFlag(flagsStr)){return flagsStr;}return "";};var flags=getRegExpFlags(regExpPart,flagsPart);if(input.startsWith(FORWARD_SLASH)&&input.endsWith(FORWARD_SLASH)||flags){var regExpInput=flags?regExpPart:input;return new RegExp(regExpInput.slice(1,-1),flags);}var escaped=input.replace(/\\'/g,"'").replace(/\\"/g,'"').replace(/[.*+?^${}()|[\]\\]/g,"\\$&");return new RegExp(escaped);}function nativeIsNaN(num){var native=Number.isNaN||window.isNaN;return native(num);}function randomId(){return Math.random().toString(36).slice(2,9);}function createOnErrorHandler(rid){var nativeOnError=window.onerror;return function onError(error){if(typeof error==="string"&&error.includes(rid)){return true;}if(nativeOnError instanceof Function){for(var _len=arguments.length,args=new Array(_len>1?_len-1:0),_key=1;_key<_len;_key++){args[_key-1]=arguments[_key];}return nativeOnError.apply(window,[error,...args]);}return false;};}function isEmptyObject(obj){return Object.keys(obj).length===0&&!obj.prototype;}function isArbitraryObject(value){return value!==null&&typeof value==="object"&&!Array.isArray(value)&&!(value instanceof RegExp);}function isStringMatched(str,matcher){if(typeof matcher==="string"){if(matcher===""){return str===matcher;}return str.includes(matcher);}if(matcher instanceof RegExp){return matcher.test(str);}return false;}function isArrayMatched(array,matcher){if(array.length===0){return matcher.length===0;}if(matcher.length===0){return false;}var _loop=function _loop(){var matcherValue=matcher[i];var isMatching=array.some(function(arrItem){return isValueMatched(arrItem,matcherValue);});if(!isMatching){return {v:false};}return "continue";};for(var i=0;i<matcher.length;i+=1){var _ret=_loop();if(_ret==="continue")continue;if(typeof _ret==="object")return _ret.v;}return true;}function isObjectMatched(obj,matcher){var matcherKeys=Object.keys(matcher);for(var i=0;i<matcherKeys.length;i+=1){var key=matcherKeys[i];var value=obj[key];if(!isValueMatched(value,matcher[key])){return false;}continue;}return true;}function backupRegExpValues(){try{var arrayOfRegexpValues=[];for(var index=1;index<10;index+=1){var value="$".concat(index);if(!RegExp[value]){break;}arrayOfRegexpValues.push(RegExp[value]);}return arrayOfRegexpValues;}catch(error){return [];}}function restoreRegExpValues(array){if(!array.length){return;}try{var stringPattern="";if(array.length===1){stringPattern="(".concat(array[0],")");}else {stringPattern=array.reduce(function(accumulator,currentValue,currentIndex){if(currentIndex===1){return "(".concat(accumulator,"),(").concat(currentValue,")");}return "".concat(accumulator,",(").concat(currentValue,")");});}var regExpGroup=new RegExp(stringPattern);array.toString().replace(regExpGroup,"");}catch(error){var message="Failed to restore RegExp values: ".concat(error);console.log(message);}}var updatedArgs=args?[].concat(source).concat(args):[source];try{trustedSuppressNativeMethod.apply(this,updatedArgs);if(source.uniqueId){Object.defineProperty(Window.prototype.toString,uniqueIdentifier,{value:flag,enumerable:false,writable:false,configurable:false});}}catch(e){console.log(e);}}function xmlPrune(source,args){var flag="done";var uniqueIdentifier=source.uniqueId+source.name+"_"+(Array.isArray(args)?args.join("_"):"");if(source.uniqueId){if(Window.prototype.toString[uniqueIdentifier]===flag){return;}}function xmlPrune(source,propsToRemove){var optionalProp=arguments.length>2&&arguments[2]!==undefined?arguments[2]:"";var urlToMatch=arguments.length>3&&arguments[3]!==undefined?arguments[3]:"";var verbose=arguments.length>4&&arguments[4]!==undefined?arguments[4]:false;if(typeof Reflect==="undefined"||typeof fetch==="undefined"||typeof Proxy==="undefined"||typeof Response==="undefined"){return;}var shouldPruneResponse=false;var shouldLogContent=verbose==="true";var urlMatchRegexp=toRegExp(urlToMatch);var XPATH_MARKER="xpath(";var isXpath=propsToRemove&&propsToRemove.startsWith(XPATH_MARKER);var getXPathElements=function getXPathElements(contextNode){var matchedElements=[];try{var elementsToRemove=propsToRemove.slice(XPATH_MARKER.length,-1);var xpathResult=contextNode.evaluate(elementsToRemove,contextNode,null,XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE,null);for(var i=0;i<xpathResult.snapshotLength;i+=1){matchedElements.push(xpathResult.snapshotItem(i));}}catch(ex){var message="Invalid XPath parameter: ".concat(propsToRemove,"\n").concat(ex);logMessage(source,message);}return matchedElements;};var xPathPruning=function xPathPruning(xPathElements){xPathElements.forEach(function(element){if(element.nodeType===1){element.remove();}else if(element.nodeType===2){element.ownerElement.removeAttribute(element.nodeName);}});};var isXML=function isXML(text){if(typeof text==="string"){var trimmedText=text.trim();if(trimmedText.startsWith("<")&&trimmedText.endsWith(">")){return true;}}return false;};var createXMLDocument=function createXMLDocument(text){var xmlParser=new DOMParser();var xmlDocument=xmlParser.parseFromString(text,"text/xml");return xmlDocument;};var isPruningNeeded=function isPruningNeeded(response,propsToRemove){if(!isXML(response)){return false;}var docXML=createXMLDocument(response);return isXpath?getXPathElements(docXML):!!docXML.querySelector(propsToRemove);};var pruneXML=function pruneXML(text){if(!isXML(text)){shouldPruneResponse=false;return text;}var xmlDoc=createXMLDocument(text);var errorNode=xmlDoc.querySelector("parsererror");if(errorNode){return text;}if(optionalProp!==""&&xmlDoc.querySelector(optionalProp)===null){shouldPruneResponse=false;return text;}var elements=isXpath?getXPathElements(xmlDoc):xmlDoc.querySelectorAll(propsToRemove);if(!elements.length){shouldPruneResponse=false;return text;}if(shouldLogContent){var cloneXmlDoc=xmlDoc.cloneNode(true);logMessage(source,"Original xml:");logMessage(source,cloneXmlDoc,true,false);}if(isXpath){xPathPruning(elements);}else {elements.forEach(function(elem){elem.remove();});}if(shouldLogContent){logMessage(source,"Modified xml:");logMessage(source,xmlDoc,true,false);}var serializer=new XMLSerializer();text=serializer.serializeToString(xmlDoc);return text;};var nativeOpen=window.XMLHttpRequest.prototype.open;var nativeSend=window.XMLHttpRequest.prototype.send;var xhrData;var openWrapper=function openWrapper(target,thisArg,args){xhrData=getXhrData.apply(null,args);if(matchRequestProps(source,urlToMatch,xhrData)){thisArg.shouldBePruned=true;}if(thisArg.shouldBePruned){thisArg.collectedHeaders=[];var setRequestHeaderWrapper=function setRequestHeaderWrapper(target,thisArg,args){thisArg.collectedHeaders.push(args);return Reflect.apply(target,thisArg,args);};var setRequestHeaderHandler={apply:setRequestHeaderWrapper};thisArg.setRequestHeader=new Proxy(thisArg.setRequestHeader,setRequestHeaderHandler);}return Reflect.apply(target,thisArg,args);};var sendWrapper=function sendWrapper(target,thisArg,args){var allowedResponseTypeValues=["","text"];if(!thisArg.shouldBePruned||!allowedResponseTypeValues.includes(thisArg.responseType)){return Reflect.apply(target,thisArg,args);}var forgedRequest=new XMLHttpRequest();forgedRequest.addEventListener("readystatechange",function(){if(forgedRequest.readyState!==4){return;}var readyState=forgedRequest.readyState,response=forgedRequest.response,responseText=forgedRequest.responseText,responseURL=forgedRequest.responseURL,responseXML=forgedRequest.responseXML,status=forgedRequest.status,statusText=forgedRequest.statusText;var content=responseText||response;if(typeof content!=="string"){return;}if(!propsToRemove){if(isXML(response)){var message="XMLHttpRequest.open() URL: ".concat(responseURL,"\nresponse: ").concat(response);logMessage(source,message);logMessage(source,createXMLDocument(response),true,false);}}else {shouldPruneResponse=isPruningNeeded(response,propsToRemove);}var responseContent=shouldPruneResponse?pruneXML(response):response;Object.defineProperties(thisArg,{readyState:{value:readyState,writable:false},responseURL:{value:responseURL,writable:false},responseXML:{value:responseXML,writable:false},status:{value:status,writable:false},statusText:{value:statusText,writable:false},response:{value:responseContent,writable:false},responseText:{value:responseContent,writable:false}});setTimeout(function(){var stateEvent=new Event("readystatechange");thisArg.dispatchEvent(stateEvent);var loadEvent=new Event("load");thisArg.dispatchEvent(loadEvent);var loadEndEvent=new Event("loadend");thisArg.dispatchEvent(loadEndEvent);},1);hit(source);});nativeOpen.apply(forgedRequest,[xhrData.method,xhrData.url]);thisArg.collectedHeaders.forEach(function(header){var name=header[0];var value=header[1];forgedRequest.setRequestHeader(name,value);});thisArg.collectedHeaders=[];try{nativeSend.call(forgedRequest,args);}catch(_unused){return Reflect.apply(target,thisArg,args);}return undefined;};var openHandler={apply:openWrapper};var sendHandler={apply:sendWrapper};XMLHttpRequest.prototype.open=new Proxy(XMLHttpRequest.prototype.open,openHandler);XMLHttpRequest.prototype.send=new Proxy(XMLHttpRequest.prototype.send,sendHandler);var nativeFetch=window.fetch;var fetchWrapper=async function fetchWrapper(target,thisArg,args){var fetchURL=args[0]instanceof Request?args[0].url:args[0];if(typeof fetchURL!=="string"||fetchURL.length===0){return Reflect.apply(target,thisArg,args);}if(urlMatchRegexp.test(fetchURL)){var response=await nativeFetch(...args);var clonedResponse=response.clone();var responseText=await response.text();shouldPruneResponse=isPruningNeeded(responseText,propsToRemove);if(!shouldPruneResponse){var message="fetch URL: ".concat(fetchURL,"\nresponse text: ").concat(responseText);logMessage(source,message);logMessage(source,createXMLDocument(responseText),true,false);return clonedResponse;}var prunedText=pruneXML(responseText);if(shouldPruneResponse){hit(source);return new Response(prunedText,{status:response.status,statusText:response.statusText,headers:response.headers});}return clonedResponse;}return Reflect.apply(target,thisArg,args);};var fetchHandler={apply:fetchWrapper};window.fetch=new Proxy(window.fetch,fetchHandler);}function hit(source){var ADGUARD_PREFIX="[AdGuard]";if(!source.verbose){return;}try{var trace=console.trace.bind(console);var label="".concat(ADGUARD_PREFIX," ");if(source.engine==="corelibs"){label+=source.ruleText;}else {if(source.domainName){label+="".concat(source.domainName);}if(source.args){label+="#%#//scriptlet('".concat(source.name,"', '").concat(source.args.join("', '"),"')");}else {label+="#%#//scriptlet('".concat(source.name,"')");}}if(trace){trace(label);}}catch(e){}if(typeof window.__debug==="function"){window.__debug(source);}}function logMessage(source,message){var forced=arguments.length>2&&arguments[2]!==undefined?arguments[2]:false;var convertMessageToString=arguments.length>3&&arguments[3]!==undefined?arguments[3]:true;var name=source.name,verbose=source.verbose;if(!forced&&!verbose){return;}var nativeConsole=console.log;if(!convertMessageToString){nativeConsole("".concat(name,":"),message);return;}nativeConsole("".concat(name,": ").concat(message));}function toRegExp(rawInput){var input=rawInput||"";var DEFAULT_VALUE=".?";var FORWARD_SLASH="/";if(input===""){return new RegExp(DEFAULT_VALUE);}var delimiterIndex=input.lastIndexOf(FORWARD_SLASH);var flagsPart=input.substring(delimiterIndex+1);var regExpPart=input.substring(0,delimiterIndex+1);var isValidRegExpFlag=function isValidRegExpFlag(flag){if(!flag){return false;}try{new RegExp("",flag);return true;}catch(ex){return false;}};var getRegExpFlags=function getRegExpFlags(regExpStr,flagsStr){if(regExpStr.startsWith(FORWARD_SLASH)&&regExpStr.endsWith(FORWARD_SLASH)&&!regExpStr.endsWith("\\/")&&isValidRegExpFlag(flagsStr)){return flagsStr;}return "";};var flags=getRegExpFlags(regExpPart,flagsPart);if(input.startsWith(FORWARD_SLASH)&&input.endsWith(FORWARD_SLASH)||flags){var regExpInput=flags?regExpPart:input;return new RegExp(regExpInput.slice(1,-1),flags);}var escaped=input.replace(/\\'/g,"'").replace(/\\"/g,'"').replace(/[.*+?^${}()|[\]\\]/g,"\\$&");return new RegExp(escaped);}function getXhrData(method,url,async,user,password){return {method:method,url:url,async:async,user:user,password:password};}function matchRequestProps(source,propsToMatch,requestData){if(propsToMatch===""||propsToMatch==="*"){return true;}var isMatched;var parsedData=parseMatchProps(propsToMatch);if(!isValidParsedData(parsedData)){logMessage(source,"Invalid parameter: ".concat(propsToMatch));isMatched=false;}else {var matchData=getMatchPropsData(parsedData);var matchKeys=Object.keys(matchData);isMatched=matchKeys.every(function(matchKey){var matchValue=matchData[matchKey];var dataValue=requestData[matchKey];return Object.prototype.hasOwnProperty.call(requestData,matchKey)&&typeof dataValue==="string"&&(matchValue===null||matchValue===void 0?void 0:matchValue.test(dataValue));});}return isMatched;}function getMatchPropsData(data){var matchData={};var dataKeys=Object.keys(data);dataKeys.forEach(function(key){matchData[key]=toRegExp(data[key]);});return matchData;}function getRequestProps(){return ["url","method","headers","body","credentials","cache","redirect","referrer","referrerPolicy","integrity","keepalive","signal","mode"];}function isValidParsedData(data){return Object.values(data).every(function(value){return isValidStrPattern(value);});}function parseMatchProps(propsToMatchStr){var PROPS_DIVIDER=" ";var PAIRS_MARKER=":";var isRequestProp=function isRequestProp(prop){return getRequestProps().includes(prop);};var propsObj={};var props=propsToMatchStr.split(PROPS_DIVIDER);props.forEach(function(prop){var dividerInd=prop.indexOf(PAIRS_MARKER);var key=prop.slice(0,dividerInd);if(isRequestProp(key)){var value=prop.slice(dividerInd+1);propsObj[key]=value;}else {propsObj.url=prop;}});return propsObj;}function isValidStrPattern(input){var FORWARD_SLASH="/";var str=escapeRegExp(input);if(input[0]===FORWARD_SLASH&&input[input.length-1]===FORWARD_SLASH){str=input.slice(1,-1);}var isValid;try{isValid=new RegExp(str);isValid=true;}catch(e){isValid=false;}return isValid;}function escapeRegExp(str){return str.replace(/[.*+?^${}()|[\]\\]/g,"\\$&");}var updatedArgs=args?[].concat(source).concat(args):[source];try{xmlPrune.apply(this,updatedArgs);if(source.uniqueId){Object.defineProperty(Window.prototype.toString,uniqueIdentifier,{value:flag,enumerable:false,writable:false,configurable:false});}}catch(e){console.log(e);}}var scriptletsMap={"amazon-apstag":AmazonApstag,"ubo-amazon_apstag.js":AmazonApstag,"amazon_apstag.js":AmazonApstag,"didomi-loader":DidomiLoader,fingerprintjs2:Fingerprintjs2,"ubo-fingerprint2.js":Fingerprintjs2,"fingerprint2.js":Fingerprintjs2,fingerprintjs3:Fingerprintjs3,"ubo-fingerprint3.js":Fingerprintjs3,"fingerprint3.js":Fingerprintjs3,gemius:Gemius,"google-analytics":GoogleAnalytics,"ubo-google-analytics_analytics.js":GoogleAnalytics,"google-analytics_analytics.js":GoogleAnalytics,"googletagmanager-gtm":GoogleAnalytics,"ubo-googletagmanager_gtm.js":GoogleAnalytics,"googletagmanager_gtm.js":GoogleAnalytics,"google-analytics-ga":GoogleAnalyticsGa,"ubo-google-analytics_ga.js":GoogleAnalyticsGa,"google-analytics_ga.js":GoogleAnalyticsGa,"google-ima3":GoogleIma3,"ubo-google-ima.js":GoogleIma3,"google-ima.js":GoogleIma3,"googlesyndication-adsbygoogle":GoogleSyndicationAdsByGoogle,"ubo-googlesyndication_adsbygoogle.js":GoogleSyndicationAdsByGoogle,"googlesyndication_adsbygoogle.js":GoogleSyndicationAdsByGoogle,"googletagservices-gpt":GoogleTagServicesGpt,"ubo-googletagservices_gpt.js":GoogleTagServicesGpt,"googletagservices_gpt.js":GoogleTagServicesGpt,matomo:Matomo,"naver-wcslog":NaverWcslog,"pardot-1.0":Pardot,prebid:Prebid,"scorecardresearch-beacon":ScoreCardResearchBeacon,"ubo-scorecardresearch_beacon.js":ScoreCardResearchBeacon,"scorecardresearch_beacon.js":ScoreCardResearchBeacon,"abort-current-inline-script":abortCurrentInlineScript,"abort-current-script.js":abortCurrentInlineScript,"ubo-abort-current-script.js":abortCurrentInlineScript,"acs.js":abortCurrentInlineScript,"ubo-acs.js":abortCurrentInlineScript,"ubo-abort-current-script":abortCurrentInlineScript,"ubo-acs":abortCurrentInlineScript,"abort-current-inline-script.js":abortCurrentInlineScript,"ubo-abort-current-inline-script.js":abortCurrentInlineScript,"acis.js":abortCurrentInlineScript,"ubo-acis.js":abortCurrentInlineScript,"ubo-abort-current-inline-script":abortCurrentInlineScript,"ubo-acis":abortCurrentInlineScript,"abp-abort-current-inline-script":abortCurrentInlineScript,"abort-on-property-read":abortOnPropertyRead,"abort-on-property-read.js":abortOnPropertyRead,"ubo-abort-on-property-read.js":abortOnPropertyRead,"aopr.js":abortOnPropertyRead,"ubo-aopr.js":abortOnPropertyRead,"ubo-abort-on-property-read":abortOnPropertyRead,"ubo-aopr":abortOnPropertyRead,"abp-abort-on-property-read":abortOnPropertyRead,"abort-on-property-write":abortOnPropertyWrite,"abort-on-property-write.js":abortOnPropertyWrite,"ubo-abort-on-property-write.js":abortOnPropertyWrite,"aopw.js":abortOnPropertyWrite,"ubo-aopw.js":abortOnPropertyWrite,"ubo-abort-on-property-write":abortOnPropertyWrite,"ubo-aopw":abortOnPropertyWrite,"abp-abort-on-property-write":abortOnPropertyWrite,"abort-on-stack-trace":abortOnStackTrace,"abort-on-stack-trace.js":abortOnStackTrace,"ubo-abort-on-stack-trace.js":abortOnStackTrace,"aost.js":abortOnStackTrace,"ubo-aost.js":abortOnStackTrace,"ubo-abort-on-stack-trace":abortOnStackTrace,"ubo-aost":abortOnStackTrace,"abp-abort-on-stack-trace":abortOnStackTrace,"adjust-setInterval":adjustSetInterval,"nano-setInterval-booster.js":adjustSetInterval,"ubo-nano-setInterval-booster.js":adjustSetInterval,"nano-sib.js":adjustSetInterval,"ubo-nano-sib.js":adjustSetInterval,"adjust-setInterval.js":adjustSetInterval,"ubo-adjust-setInterval.js":adjustSetInterval,"ubo-nano-setInterval-booster":adjustSetInterval,"ubo-nano-sib":adjustSetInterval,"ubo-adjust-setInterval":adjustSetInterval,"adjust-setTimeout":adjustSetTimeout,"adjust-setTimeout.js":adjustSetTimeout,"ubo-adjust-setTimeout.js":adjustSetTimeout,"nano-setTimeout-booster.js":adjustSetTimeout,"ubo-nano-setTimeout-booster.js":adjustSetTimeout,"nano-stb.js":adjustSetTimeout,"ubo-nano-stb.js":adjustSetTimeout,"ubo-adjust-setTimeout":adjustSetTimeout,"ubo-nano-setTimeout-booster":adjustSetTimeout,"ubo-nano-stb":adjustSetTimeout,"call-nothrow":callNoThrow,"call-nothrow.js":callNoThrow,"ubo-call-nothrow.js":callNoThrow,"ubo-call-nothrow":callNoThrow,"debug-current-inline-script":debugCurrentInlineScript,"debug-on-property-read":debugOnPropertyRead,"debug-on-property-write":debugOnPropertyWrite,"dir-string":dirString,"disable-newtab-links":disableNewtabLinks,"disable-newtab-links.js":disableNewtabLinks,"ubo-disable-newtab-links.js":disableNewtabLinks,"ubo-disable-newtab-links":disableNewtabLinks,"evaldata-prune":evalDataPrune,"evaldata-prune.js":evalDataPrune,"ubo-evaldata-prune.js":evalDataPrune,"ubo-evaldata-prune":evalDataPrune,"close-window":forceWindowClose,"window-close-if.js":forceWindowClose,"ubo-window-close-if.js":forceWindowClose,"ubo-window-close-if":forceWindowClose,"close-window.js":forceWindowClose,"ubo-close-window.js":forceWindowClose,"ubo-close-window":forceWindowClose,"hide-in-shadow-dom":hideInShadowDom,"href-sanitizer":hrefSanitizer,"href-sanitizer.js":hrefSanitizer,"ubo-href-sanitizer.js":hrefSanitizer,"ubo-href-sanitizer":hrefSanitizer,"inject-css-in-shadow-dom":injectCssInShadowDom,"json-prune":jsonPrune,"json-prune.js":jsonPrune,"ubo-json-prune.js":jsonPrune,"ubo-json-prune":jsonPrune,"abp-json-prune":jsonPrune,"json-prune-fetch-response":jsonPruneFetchResponse,"json-prune-fetch-response.js":jsonPruneFetchResponse,"ubo-json-prune-fetch-response.js":jsonPruneFetchResponse,"ubo-json-prune-fetch-response":jsonPruneFetchResponse,"json-prune-xhr-response":jsonPruneXhrResponse,"json-prune-xhr-response.js":jsonPruneXhrResponse,"ubo-json-prune-xhr-response.js":jsonPruneXhrResponse,"ubo-json-prune-xhr-response":jsonPruneXhrResponse,log:log,"abp-log":log,"log-addEventListener":logAddEventListener,"addEventListener-logger.js":logAddEventListener,"ubo-addEventListener-logger.js":logAddEventListener,"aell.js":logAddEventListener,"ubo-aell.js":logAddEventListener,"ubo-addEventListener-logger":logAddEventListener,"ubo-aell":logAddEventListener,"log-eval":logEval,"log-on-stack-trace":logOnStacktrace,"m3u-prune":m3uPrune,"m3u-prune.js":m3uPrune,"ubo-m3u-prune.js":m3uPrune,"ubo-m3u-prune":m3uPrune,"metrika-yandex-tag":metrikaYandexTag,"metrika-yandex-watch":metrikaYandexWatch,"no-protected-audience":noProtectedAudience,"no-topics":noTopics,noeval:noeval,"noeval.js":noeval,"silent-noeval.js":noeval,"ubo-noeval.js":noeval,"ubo-silent-noeval.js":noeval,"ubo-noeval":noeval,"ubo-silent-noeval":noeval,nowebrtc:nowebrtc,"nowebrtc.js":nowebrtc,"ubo-nowebrtc.js":nowebrtc,"ubo-nowebrtc":nowebrtc,"prevent-addEventListener":preventAddEventListener,"addEventListener-defuser.js":preventAddEventListener,"ubo-addEventListener-defuser.js":preventAddEventListener,"aeld.js":preventAddEventListener,"ubo-aeld.js":preventAddEventListener,"ubo-addEventListener-defuser":preventAddEventListener,"ubo-aeld":preventAddEventListener,"abp-prevent-listener":preventAddEventListener,"prevent-adfly":preventAdfly,"prevent-bab":preventBab,"prevent-element-src-loading":preventElementSrcLoading,"prevent-eval-if":preventEvalIf,"noeval-if.js":preventEvalIf,"ubo-noeval-if.js":preventEvalIf,"ubo-noeval-if":preventEvalIf,"prevent-fab-3.2.0":preventFab,"nofab.js":preventFab,"ubo-nofab.js":preventFab,"fuckadblock.js-3.2.0":preventFab,"ubo-fuckadblock.js-3.2.0":preventFab,"ubo-nofab":preventFab,"prevent-fetch":preventFetch,"prevent-fetch.js":preventFetch,"ubo-prevent-fetch.js":preventFetch,"ubo-prevent-fetch":preventFetch,"no-fetch-if.js":preventFetch,"ubo-no-fetch-if.js":preventFetch,"ubo-no-fetch-if":preventFetch,"prevent-popads-net":preventPopadsNet,"popads.net.js":preventPopadsNet,"ubo-popads.net.js":preventPopadsNet,"ubo-popads.net":preventPopadsNet,"prevent-refresh":preventRefresh,"prevent-refresh.js":preventRefresh,"refresh-defuser.js":preventRefresh,"refresh-defuser":preventRefresh,"ubo-prevent-refresh.js":preventRefresh,"ubo-prevent-refresh":preventRefresh,"ubo-refresh-defuser.js":preventRefresh,"ubo-refresh-defuser":preventRefresh,"prevent-requestAnimationFrame":preventRequestAnimationFrame,"no-requestAnimationFrame-if.js":preventRequestAnimationFrame,"ubo-no-requestAnimationFrame-if.js":preventRequestAnimationFrame,"norafif.js":preventRequestAnimationFrame,"ubo-norafif.js":preventRequestAnimationFrame,"ubo-no-requestAnimationFrame-if":preventRequestAnimationFrame,"ubo-norafif":preventRequestAnimationFrame,"prevent-setInterval":preventSetInterval,"no-setInterval-if.js":preventSetInterval,"ubo-no-setInterval-if.js":preventSetInterval,"setInterval-defuser.js":preventSetInterval,"ubo-setInterval-defuser.js":preventSetInterval,"nosiif.js":preventSetInterval,"ubo-nosiif.js":preventSetInterval,"sid.js":preventSetInterval,"ubo-sid.js":preventSetInterval,"ubo-no-setInterval-if":preventSetInterval,"ubo-setInterval-defuser":preventSetInterval,"ubo-nosiif":preventSetInterval,"ubo-sid":preventSetInterval,"prevent-setTimeout":preventSetTimeout,"no-setTimeout-if.js":preventSetTimeout,"ubo-no-setTimeout-if.js":preventSetTimeout,"nostif.js":preventSetTimeout,"ubo-nostif.js":preventSetTimeout,"ubo-no-setTimeout-if":preventSetTimeout,"ubo-nostif":preventSetTimeout,"setTimeout-defuser.js":preventSetTimeout,"ubo-setTimeout-defuser.js":preventSetTimeout,"ubo-setTimeout-defuser":preventSetTimeout,"std.js":preventSetTimeout,"ubo-std.js":preventSetTimeout,"ubo-std":preventSetTimeout,"prevent-window-open":preventWindowOpen,"window.open-defuser.js":preventWindowOpen,"ubo-window.open-defuser.js":preventWindowOpen,"ubo-window.open-defuser":preventWindowOpen,"nowoif.js":preventWindowOpen,"ubo-nowoif.js":preventWindowOpen,"ubo-nowoif":preventWindowOpen,"no-window-open-if.js":preventWindowOpen,"ubo-no-window-open-if.js":preventWindowOpen,"ubo-no-window-open-if":preventWindowOpen,"prevent-xhr":preventXHR,"no-xhr-if.js":preventXHR,"ubo-no-xhr-if.js":preventXHR,"ubo-no-xhr-if":preventXHR,"remove-attr":removeAttr,"remove-attr.js":removeAttr,"ubo-remove-attr.js":removeAttr,"ra.js":removeAttr,"ubo-ra.js":removeAttr,"ubo-remove-attr":removeAttr,"ubo-ra":removeAttr,"remove-class":removeClass,"remove-class.js":removeClass,"ubo-remove-class.js":removeClass,"rc.js":removeClass,"ubo-rc.js":removeClass,"ubo-remove-class":removeClass,"ubo-rc":removeClass,"remove-cookie":removeCookie,"cookie-remover.js":removeCookie,"ubo-cookie-remover.js":removeCookie,"ubo-cookie-remover":removeCookie,"remove-cookie.js":removeCookie,"ubo-remove-cookie.js":removeCookie,"ubo-remove-cookie":removeCookie,"abp-cookie-remover":removeCookie,"remove-in-shadow-dom":removeInShadowDom,"remove-node-text":removeNodeText,"remove-node-text.js":removeNodeText,"ubo-remove-node-text.js":removeNodeText,"rmnt.js":removeNodeText,"ubo-rmnt.js":removeNodeText,"ubo-remove-node-text":removeNodeText,"ubo-rmnt":removeNodeText,"set-attr":setAttr,"set-attr.js":setAttr,"ubo-set-attr.js":setAttr,"ubo-set-attr":setAttr,"set-constant":setConstant,"set-constant.js":setConstant,"ubo-set-constant.js":setConstant,"set.js":setConstant,"ubo-set.js":setConstant,"ubo-set-constant":setConstant,"ubo-set":setConstant,"abp-override-property-read":setConstant,"set-cookie":setCookie,"set-cookie.js":setCookie,"ubo-set-cookie.js":setCookie,"ubo-set-cookie":setCookie,"set-cookie-reload":setCookieReload,"set-cookie-reload.js":setCookieReload,"ubo-set-cookie-reload.js":setCookieReload,"ubo-set-cookie-reload":setCookieReload,"set-local-storage-item":setLocalStorageItem,"set-local-storage-item.js":setLocalStorageItem,"ubo-set-local-storage-item.js":setLocalStorageItem,"ubo-set-local-storage-item":setLocalStorageItem,"set-popads-dummy":setPopadsDummy,"popads-dummy.js":setPopadsDummy,"ubo-popads-dummy.js":setPopadsDummy,"ubo-popads-dummy":setPopadsDummy,"set-session-storage-item":setSessionStorageItem,"set-session-storage-item.js":setSessionStorageItem,"ubo-set-session-storage-item.js":setSessionStorageItem,"ubo-set-session-storage-item":setSessionStorageItem,"spoof-css":spoofCSS,"spoof-css.js":spoofCSS,"ubo-spoof-css.js":spoofCSS,"ubo-spoof-css":spoofCSS,"trusted-click-element":trustedClickElement,"trusted-create-element":trustedCreateElement,"trusted-dispatch-event":trustedDispatchEvent,"trusted-prune-inbound-object":trustedPruneInboundObject,"trusted-replace-fetch-response":trustedReplaceFetchResponse,"trusted-replace-node-text":trustedReplaceNodeText,"trusted-replace-outbound-text":trustedReplaceOutboundText,"trusted-replace-xhr-response":trustedReplaceXhrResponse,"trusted-set-attr":trustedSetAttr,"trusted-set-constant":trustedSetConstant,"trusted-set-cookie":trustedSetCookie,"trusted-set-cookie-reload":trustedSetCookieReload,"trusted-set-local-storage-item":trustedSetLocalStorageItem,"trusted-set-session-storage-item":trustedSetSessionStorageItem,"trusted-suppress-native-method":trustedSuppressNativeMethod,"xml-prune":xmlPrune,"xml-prune.js":xmlPrune,"ubo-xml-prune.js":xmlPrune,"ubo-xml-prune":xmlPrune};var getScriptletFunction=function getScriptletFunction(name){return scriptletsMap[name];};

    /**
     * @typedef {object} Source Scriptlet properties.
     * @property {string} name Scriptlet name.
     * @property {Array<string>} args Arguments for scriptlet function.
     * @property {'extension'|'corelibs'|'test'} engine Defines the final form of scriptlet string presentation.
     * @property {string} [version] Extension version.
     * @property {boolean} [verbose] Flag to enable debug information printing to console.
     * @property {string} [ruleText] Source rule text, needed for debug purposes.
     * @property {string} [domainName] Domain name where scriptlet is applied, needed for debug purposes.
     */

    /**
     * Returns scriptlet code by `source`.
     *
     * @param {Source} source Scriptlet properties.
     *
     * @returns {string|null} Scriptlet code.
     * @throws An error on unknown scriptlet name.
     */
    function getScriptletCode(source) {
      if (!validator.isValidScriptletName(source.name)) {
        return null;
      }
      var scriptletFunction = getScriptletFunction(source.name);
      // In case isValidScriptletName check will pass invalid scriptlet name,
      // for example when there is a bad alias
      if (typeof scriptletFunction !== 'function') {
        throw new Error("Error: cannot invoke scriptlet with name: '".concat(source.name, "'"));
      }
      var scriptletFunctionString = scriptletFunction.toString();
      var result = source.engine === 'corelibs' || source.engine === 'test' ? wrapInNonameFunc(scriptletFunctionString) : passSourceAndProps(source, scriptletFunctionString);
      return result;
    }

    /**
     * Scriptlets variable
     *
     * @returns {object} object with methods:
     * `invoke` method receives one argument with `Source` type
     * `validate` method receives one argument with `String` type
     */
    var scriptletsObject = function () {
      return {
        invoke: getScriptletCode,
        getScriptletFunction,
        isValidScriptletName: validator.isValidScriptletName,
        isValidScriptletRule,
        isAdgScriptletRule: validator.isAdgScriptletRule,
        isUboScriptletRule: validator.isUboScriptletRule,
        isAbpSnippetRule: validator.isAbpSnippetRule,
        convertUboToAdg: convertUboScriptletToAdg,
        convertAbpToAdg: convertAbpSnippetToAdg,
        convertScriptletToAdg,
        convertAdgToUbo: convertAdgScriptletToUbo,
        redirects,
        SCRIPTLETS_VERSION: version
      };
    }();

    /**
     * Add module exports to be used as node package
     */
    module.exports = scriptletsObject;

}));

/**
 * -------------------------------------------
 * |                                         |
 * |  If you want to add your own scriptlet  |
 * |  please put your code below             |
 * |                                         |
 * -------------------------------------------
 */


/***/ })

},
/******/ __webpack_require__ => { // webpackRuntimeModules
/******/ var __webpack_exec__ = (moduleId) => (__webpack_require__(__webpack_require__.s = moduleId))
/******/ var __webpack_exports__ = (__webpack_exec__(97730));
/******/ }
]);