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

/***/ 28416:
/***/ ((__unused_webpack_module, __unused_webpack___webpack_exports__, __webpack_require__) => {

"use strict";

// UNUSED EXPORTS: ALLOWLIST_FILTER_ID, BACKGROUND_TAB_ID, CUSTOM_FILTERS_START_ID, ContentType, CosmeticRule, EXTENDED_CSS_VERSION, EventChannel, ExtSessionStorage, ExtensionStorage, FRAME_DELETION_TIMEOUT_MS, FilterListPreprocessor, FilteringEventType, FilteringLog, Frame, LF, MAIN_FRAME_ID, MESSAGE_HANDLER_NAME, MessageType, NetworkRule, NetworkRuleOption, PersistentValueContainer, QUICK_FIXES_FILTER_ID, RequestBlockingApi, RequestContextStorage, RequestEvent, RequestEvents, StealthActions, StealthHelper, TSWEBEXTENSION_VERSION, TabContext, TabsApi, TabsCosmeticInjector, TsWebExtension, USER_FILTER_ID, allowlist, basicFilterValidator, companiesDbService, configurationMV2Validator, configurationValidator, createExtensionStorageDecorator, createTsWebExtension, defaultFilteringLog, documentApi, documentBlockingService, engineApi, extSessionStorage, filterMV2Validator, findHeaderByName, getAssistantCreateRulePayloadValidator, getCookieRulesPayloadValidator, getCosmeticDataPayloadValidator, getDomain, getErrorMessage, getExtendedCssPayloadValidator, getHost, getRequestType, getRuleSourceIndex, getRuleSourceText, getSaveCookieLogEventPayloadValidator, getUpperLevelDomain, hideRequestInitiatorElement, isEmptySrcFrame, isExtensionUrl, isHttpOrWsRequest, isHttpRequest, isThirdPartyRequest, logger, messageValidator, messagesApi, processShouldCollapsePayloadValidator, redirectsService, requestContextStorage, resourcesService, sendAppMessage, sessionDecorator, settingsConfigValidator, stealthConfigValidator, stringifyObjectWithoutKeys, tabsApi

// EXTERNAL MODULE: ./node_modules/.pnpm/@adguard+tsurlfilter@3.1.0-alpha.7_@adguard+re2-wasm@1.2.0/node_modules/@adguard/tsurlfilter/dist/es/index.js + 2 modules
var es = __webpack_require__(37302);
// EXTERNAL MODULE: ./node_modules/.pnpm/webextension-polyfill@0.12.0/node_modules/webextension-polyfill/dist/browser-polyfill.js
var browser_polyfill = __webpack_require__(70914);
var browser_polyfill_default = /*#__PURE__*/__webpack_require__.n(browser_polyfill);
// EXTERNAL MODULE: ./node_modules/.pnpm/tldts@6.1.61/node_modules/tldts/dist/es6/index.js + 12 modules
var es6 = __webpack_require__(48514);
;// CONCATENATED MODULE: ./node_modules/.pnpm/nanoid@4.0.2/node_modules/nanoid/index.browser.js

let random = bytes => crypto.getRandomValues(new Uint8Array(bytes))
let customRandom = (alphabet, defaultSize, getRandom) => {
  let mask = (2 << (Math.log(alphabet.length - 1) / Math.LN2)) - 1
  let step = -~((1.6 * mask * defaultSize) / alphabet.length)
  return (size = defaultSize) => {
    let id = ''
    while (true) {
      let bytes = getRandom(step)
      let j = step
      while (j--) {
        id += alphabet[bytes[j] & mask] || ''
        if (id.length === size) return id
      }
    }
  }
}
let customAlphabet = (alphabet, size = 21) =>
  customRandom(alphabet, size, random)
let index_browser_nanoid = (size = 21) =>
  crypto.getRandomValues(new Uint8Array(size)).reduce((id, byte) => {
    byte &= 63
    if (byte < 36) {
      id += byte.toString(36)
    } else if (byte < 62) {
      id += (byte - 26).toString(36).toUpperCase()
    } else if (byte > 62) {
      id += '-'
    } else {
      id += '_'
    }
    return id
  }, '')

// EXTERNAL MODULE: ./node_modules/.pnpm/@adguard+tswebextension@2.4.0-alpha.11_@adguard+re2-wasm@1.2.0/node_modules/@adguard/tswebextension/dist/text-encoding-polyfill.js
var text_encoding_polyfill = __webpack_require__(74498);
// EXTERNAL MODULE: ./node_modules/.pnpm/zod@3.21.4/node_modules/zod/lib/index.mjs
var lib = __webpack_require__(44945);
// EXTERNAL MODULE: ./node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/debounce.js
var debounce = __webpack_require__(72135);
// EXTERNAL MODULE: ./node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/_baseGet.js
var _baseGet = __webpack_require__(42043);
// EXTERNAL MODULE: ./node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/_defineProperty.js
var _defineProperty = __webpack_require__(97024);
;// CONCATENATED MODULE: ./node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/_baseAssignValue.js


/**
 * The base implementation of `assignValue` and `assignMergeValue` without
 * value checks.
 *
 * @private
 * @param {Object} object The object to modify.
 * @param {string} key The key of the property to assign.
 * @param {*} value The value to assign.
 */
function baseAssignValue(object, key, value) {
  if (key == '__proto__' && _defineProperty/* default */.Z) {
    (0,_defineProperty/* default */.Z)(object, key, {
      'configurable': true,
      'enumerable': true,
      'value': value,
      'writable': true
    });
  } else {
    object[key] = value;
  }
}

/* harmony default export */ const _baseAssignValue = (baseAssignValue);

// EXTERNAL MODULE: ./node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/eq.js
var eq = __webpack_require__(99581);
;// CONCATENATED MODULE: ./node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/_assignValue.js



/** Used for built-in method references. */
var objectProto = Object.prototype;

/** Used to check objects for own properties. */
var _assignValue_hasOwnProperty = objectProto.hasOwnProperty;

/**
 * Assigns `value` to `key` of `object` if the existing value is not equivalent
 * using [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)
 * for equality comparisons.
 *
 * @private
 * @param {Object} object The object to modify.
 * @param {string} key The key of the property to assign.
 * @param {*} value The value to assign.
 */
function assignValue(object, key, value) {
  var objValue = object[key];
  if (!(_assignValue_hasOwnProperty.call(object, key) && (0,eq/* default */.Z)(objValue, value)) ||
      (value === undefined && !(key in object))) {
    _baseAssignValue(object, key, value);
  }
}

/* harmony default export */ const _assignValue = (assignValue);

// EXTERNAL MODULE: ./node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/_castPath.js
var _castPath = __webpack_require__(70093);
// EXTERNAL MODULE: ./node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/_isIndex.js
var _isIndex = __webpack_require__(91661);
// EXTERNAL MODULE: ./node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/isObject.js
var isObject = __webpack_require__(62893);
// EXTERNAL MODULE: ./node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/_toKey.js
var _toKey = __webpack_require__(53069);
;// CONCATENATED MODULE: ./node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/_baseSet.js






/**
 * The base implementation of `_.set`.
 *
 * @private
 * @param {Object} object The object to modify.
 * @param {Array|string} path The path of the property to set.
 * @param {*} value The value to set.
 * @param {Function} [customizer] The function to customize path creation.
 * @returns {Object} Returns `object`.
 */
function baseSet(object, path, value, customizer) {
  if (!(0,isObject/* default */.Z)(object)) {
    return object;
  }
  path = (0,_castPath/* default */.Z)(path, object);

  var index = -1,
      length = path.length,
      lastIndex = length - 1,
      nested = object;

  while (nested != null && ++index < length) {
    var key = (0,_toKey/* default */.Z)(path[index]),
        newValue = value;

    if (key === '__proto__' || key === 'constructor' || key === 'prototype') {
      return object;
    }

    if (index != lastIndex) {
      var objValue = nested[key];
      newValue = customizer ? customizer(objValue, key, nested) : undefined;
      if (newValue === undefined) {
        newValue = (0,isObject/* default */.Z)(objValue)
          ? objValue
          : ((0,_isIndex/* default */.Z)(path[index + 1]) ? [] : {});
      }
    }
    _assignValue(nested, key, newValue);
    nested = nested[key];
  }
  return object;
}

/* harmony default export */ const _baseSet = (baseSet);

;// CONCATENATED MODULE: ./node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/_basePickBy.js




/**
 * The base implementation of  `_.pickBy` without support for iteratee shorthands.
 *
 * @private
 * @param {Object} object The source object.
 * @param {string[]} paths The property paths to pick.
 * @param {Function} predicate The function invoked per property.
 * @returns {Object} Returns the new object.
 */
function basePickBy(object, paths, predicate) {
  var index = -1,
      length = paths.length,
      result = {};

  while (++index < length) {
    var path = paths[index],
        value = (0,_baseGet/* default */.Z)(object, path);

    if (predicate(value, path)) {
      _baseSet(result, (0,_castPath/* default */.Z)(path, object), value);
    }
  }
  return result;
}

/* harmony default export */ const _basePickBy = (basePickBy);

// EXTERNAL MODULE: ./node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/hasIn.js + 2 modules
var hasIn = __webpack_require__(94723);
;// CONCATENATED MODULE: ./node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/_basePick.js



/**
 * The base implementation of `_.pick` without support for individual
 * property identifiers.
 *
 * @private
 * @param {Object} object The source object.
 * @param {string[]} paths The property paths to pick.
 * @returns {Object} Returns the new object.
 */
function basePick(object, paths) {
  return _basePickBy(object, paths, function(value, path) {
    return (0,hasIn/* default */.Z)(object, path);
  });
}

/* harmony default export */ const _basePick = (basePick);

// EXTERNAL MODULE: ./node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/_baseFlatten.js + 1 modules
var _baseFlatten = __webpack_require__(90094);
;// CONCATENATED MODULE: ./node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/flatten.js


/**
 * Flattens `array` a single level deep.
 *
 * @static
 * @memberOf _
 * @since 0.1.0
 * @category Array
 * @param {Array} array The array to flatten.
 * @returns {Array} Returns the new flattened array.
 * @example
 *
 * _.flatten([1, [2, [3, [4]], 5]]);
 * // => [1, 2, [3, [4]], 5]
 */
function flatten(array) {
  var length = array == null ? 0 : array.length;
  return length ? (0,_baseFlatten/* default */.Z)(array, 1) : [];
}

/* harmony default export */ const lodash_es_flatten = (flatten);

// EXTERNAL MODULE: ./node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/_overRest.js + 1 modules
var _overRest = __webpack_require__(53281);
// EXTERNAL MODULE: ./node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/_setToString.js + 3 modules
var _setToString = __webpack_require__(26826);
;// CONCATENATED MODULE: ./node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/_flatRest.js




/**
 * A specialized version of `baseRest` which flattens the rest array.
 *
 * @private
 * @param {Function} func The function to apply a rest parameter to.
 * @returns {Function} Returns the new function.
 */
function flatRest(func) {
  return (0,_setToString/* default */.Z)((0,_overRest/* default */.Z)(func, undefined, lodash_es_flatten), func + '');
}

/* harmony default export */ const _flatRest = (flatRest);

;// CONCATENATED MODULE: ./node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/pick.js



/**
 * Creates an object composed of the picked `object` properties.
 *
 * @static
 * @since 0.1.0
 * @memberOf _
 * @category Object
 * @param {Object} object The source object.
 * @param {...(string|string[])} [paths] The property paths to pick.
 * @returns {Object} Returns the new object.
 * @example
 *
 * var object = { 'a': 1, 'b': '2', 'c': 3 };
 *
 * _.pick(object, ['a', 'c']);
 * // => { 'a': 1, 'c': 3 }
 */
var pick = _flatRest(function(object, paths) {
  return object == null ? {} : _basePick(object, paths);
});

/* harmony default export */ const lodash_es_pick = (pick);

// EXTERNAL MODULE: ./node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/_Stack.js + 5 modules
var _Stack = __webpack_require__(74225);
;// CONCATENATED MODULE: ./node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/_assignMergeValue.js



/**
 * This function is like `assignValue` except that it doesn't assign
 * `undefined` values.
 *
 * @private
 * @param {Object} object The object to modify.
 * @param {string} key The key of the property to assign.
 * @param {*} value The value to assign.
 */
function assignMergeValue(object, key, value) {
  if ((value !== undefined && !(0,eq/* default */.Z)(object[key], value)) ||
      (value === undefined && !(key in object))) {
    _baseAssignValue(object, key, value);
  }
}

/* harmony default export */ const _assignMergeValue = (assignMergeValue);

// EXTERNAL MODULE: ./node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/_baseFor.js + 1 modules
var _baseFor = __webpack_require__(92822);
// EXTERNAL MODULE: ./node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/_root.js
var _root = __webpack_require__(5665);
;// CONCATENATED MODULE: ./node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/_cloneBuffer.js


/** Detect free variable `exports`. */
var freeExports = typeof exports == 'object' && exports && !exports.nodeType && exports;

/** Detect free variable `module`. */
var freeModule = freeExports && typeof module == 'object' && module && !module.nodeType && module;

/** Detect the popular CommonJS extension `module.exports`. */
var moduleExports = freeModule && freeModule.exports === freeExports;

/** Built-in value references. */
var Buffer = moduleExports ? _root/* default.Buffer */.Z.Buffer : undefined,
    allocUnsafe = Buffer ? Buffer.allocUnsafe : undefined;

/**
 * Creates a clone of  `buffer`.
 *
 * @private
 * @param {Buffer} buffer The buffer to clone.
 * @param {boolean} [isDeep] Specify a deep clone.
 * @returns {Buffer} Returns the cloned buffer.
 */
function cloneBuffer(buffer, isDeep) {
  if (isDeep) {
    return buffer.slice();
  }
  var length = buffer.length,
      result = allocUnsafe ? allocUnsafe(length) : new buffer.constructor(length);

  buffer.copy(result);
  return result;
}

/* harmony default export */ const _cloneBuffer = (cloneBuffer);

// EXTERNAL MODULE: ./node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/_Uint8Array.js
var _Uint8Array = __webpack_require__(9128);
;// CONCATENATED MODULE: ./node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/_cloneArrayBuffer.js


/**
 * Creates a clone of `arrayBuffer`.
 *
 * @private
 * @param {ArrayBuffer} arrayBuffer The array buffer to clone.
 * @returns {ArrayBuffer} Returns the cloned array buffer.
 */
function cloneArrayBuffer(arrayBuffer) {
  var result = new arrayBuffer.constructor(arrayBuffer.byteLength);
  new _Uint8Array/* default */.Z(result).set(new _Uint8Array/* default */.Z(arrayBuffer));
  return result;
}

/* harmony default export */ const _cloneArrayBuffer = (cloneArrayBuffer);

;// CONCATENATED MODULE: ./node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/_cloneTypedArray.js


/**
 * Creates a clone of `typedArray`.
 *
 * @private
 * @param {Object} typedArray The typed array to clone.
 * @param {boolean} [isDeep] Specify a deep clone.
 * @returns {Object} Returns the cloned typed array.
 */
function cloneTypedArray(typedArray, isDeep) {
  var buffer = isDeep ? _cloneArrayBuffer(typedArray.buffer) : typedArray.buffer;
  return new typedArray.constructor(buffer, typedArray.byteOffset, typedArray.length);
}

/* harmony default export */ const _cloneTypedArray = (cloneTypedArray);

;// CONCATENATED MODULE: ./node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/_copyArray.js
/**
 * Copies the values of `source` to `array`.
 *
 * @private
 * @param {Array} source The array to copy values from.
 * @param {Array} [array=[]] The array to copy values to.
 * @returns {Array} Returns `array`.
 */
function copyArray(source, array) {
  var index = -1,
      length = source.length;

  array || (array = Array(length));
  while (++index < length) {
    array[index] = source[index];
  }
  return array;
}

/* harmony default export */ const _copyArray = (copyArray);

;// CONCATENATED MODULE: ./node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/_baseCreate.js


/** Built-in value references. */
var objectCreate = Object.create;

/**
 * The base implementation of `_.create` without support for assigning
 * properties to the created object.
 *
 * @private
 * @param {Object} proto The object to inherit from.
 * @returns {Object} Returns the new object.
 */
var baseCreate = (function() {
  function object() {}
  return function(proto) {
    if (!(0,isObject/* default */.Z)(proto)) {
      return {};
    }
    if (objectCreate) {
      return objectCreate(proto);
    }
    object.prototype = proto;
    var result = new object;
    object.prototype = undefined;
    return result;
  };
}());

/* harmony default export */ const _baseCreate = (baseCreate);

// EXTERNAL MODULE: ./node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/_overArg.js
var _overArg = __webpack_require__(6438);
;// CONCATENATED MODULE: ./node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/_getPrototype.js


/** Built-in value references. */
var getPrototype = (0,_overArg/* default */.Z)(Object.getPrototypeOf, Object);

/* harmony default export */ const _getPrototype = (getPrototype);

// EXTERNAL MODULE: ./node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/_isPrototype.js
var _isPrototype = __webpack_require__(41040);
;// CONCATENATED MODULE: ./node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/_initCloneObject.js




/**
 * Initializes an object clone.
 *
 * @private
 * @param {Object} object The object to clone.
 * @returns {Object} Returns the initialized clone.
 */
function initCloneObject(object) {
  return (typeof object.constructor == 'function' && !(0,_isPrototype/* default */.Z)(object))
    ? _baseCreate(_getPrototype(object))
    : {};
}

/* harmony default export */ const _initCloneObject = (initCloneObject);

// EXTERNAL MODULE: ./node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/isArguments.js
var isArguments = __webpack_require__(66161);
// EXTERNAL MODULE: ./node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/isArray.js
var isArray = __webpack_require__(24254);
// EXTERNAL MODULE: ./node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/isArrayLike.js
var isArrayLike = __webpack_require__(2762);
// EXTERNAL MODULE: ./node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/isObjectLike.js
var isObjectLike = __webpack_require__(95690);
;// CONCATENATED MODULE: ./node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/isArrayLikeObject.js



/**
 * This method is like `_.isArrayLike` except that it also checks if `value`
 * is an object.
 *
 * @static
 * @memberOf _
 * @since 4.0.0
 * @category Lang
 * @param {*} value The value to check.
 * @returns {boolean} Returns `true` if `value` is an array-like object,
 *  else `false`.
 * @example
 *
 * _.isArrayLikeObject([1, 2, 3]);
 * // => true
 *
 * _.isArrayLikeObject(document.body.children);
 * // => true
 *
 * _.isArrayLikeObject('abc');
 * // => false
 *
 * _.isArrayLikeObject(_.noop);
 * // => false
 */
function isArrayLikeObject(value) {
  return (0,isObjectLike/* default */.Z)(value) && (0,isArrayLike/* default */.Z)(value);
}

/* harmony default export */ const lodash_es_isArrayLikeObject = (isArrayLikeObject);

// EXTERNAL MODULE: ./node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/isBuffer.js
var isBuffer = __webpack_require__(5950);
// EXTERNAL MODULE: ./node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/isFunction.js
var isFunction = __webpack_require__(25827);
// EXTERNAL MODULE: ./node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/_baseGetTag.js
var _baseGetTag = __webpack_require__(85086);
;// CONCATENATED MODULE: ./node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/isPlainObject.js




/** `Object#toString` result references. */
var objectTag = '[object Object]';

/** Used for built-in method references. */
var funcProto = Function.prototype,
    isPlainObject_objectProto = Object.prototype;

/** Used to resolve the decompiled source of functions. */
var funcToString = funcProto.toString;

/** Used to check objects for own properties. */
var isPlainObject_hasOwnProperty = isPlainObject_objectProto.hasOwnProperty;

/** Used to infer the `Object` constructor. */
var objectCtorString = funcToString.call(Object);

/**
 * Checks if `value` is a plain object, that is, an object created by the
 * `Object` constructor or one with a `[[Prototype]]` of `null`.
 *
 * @static
 * @memberOf _
 * @since 0.8.0
 * @category Lang
 * @param {*} value The value to check.
 * @returns {boolean} Returns `true` if `value` is a plain object, else `false`.
 * @example
 *
 * function Foo() {
 *   this.a = 1;
 * }
 *
 * _.isPlainObject(new Foo);
 * // => false
 *
 * _.isPlainObject([1, 2, 3]);
 * // => false
 *
 * _.isPlainObject({ 'x': 0, 'y': 0 });
 * // => true
 *
 * _.isPlainObject(Object.create(null));
 * // => true
 */
function isPlainObject(value) {
  if (!(0,isObjectLike/* default */.Z)(value) || (0,_baseGetTag/* default */.Z)(value) != objectTag) {
    return false;
  }
  var proto = _getPrototype(value);
  if (proto === null) {
    return true;
  }
  var Ctor = isPlainObject_hasOwnProperty.call(proto, 'constructor') && proto.constructor;
  return typeof Ctor == 'function' && Ctor instanceof Ctor &&
    funcToString.call(Ctor) == objectCtorString;
}

/* harmony default export */ const lodash_es_isPlainObject = (isPlainObject);

// EXTERNAL MODULE: ./node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/isTypedArray.js
var isTypedArray = __webpack_require__(90284);
;// CONCATENATED MODULE: ./node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/_safeGet.js
/**
 * Gets the value at `key`, unless `key` is "__proto__" or "constructor".
 *
 * @private
 * @param {Object} object The object to query.
 * @param {string} key The key of the property to get.
 * @returns {*} Returns the property value.
 */
function safeGet(object, key) {
  if (key === 'constructor' && typeof object[key] === 'function') {
    return;
  }

  if (key == '__proto__') {
    return;
  }

  return object[key];
}

/* harmony default export */ const _safeGet = (safeGet);

;// CONCATENATED MODULE: ./node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/_copyObject.js



/**
 * Copies properties of `source` to `object`.
 *
 * @private
 * @param {Object} source The object to copy properties from.
 * @param {Array} props The property identifiers to copy.
 * @param {Object} [object={}] The object to copy properties to.
 * @param {Function} [customizer] The function to customize copied values.
 * @returns {Object} Returns `object`.
 */
function copyObject(source, props, object, customizer) {
  var isNew = !object;
  object || (object = {});

  var index = -1,
      length = props.length;

  while (++index < length) {
    var key = props[index];

    var newValue = customizer
      ? customizer(object[key], source[key], key, object, source)
      : undefined;

    if (newValue === undefined) {
      newValue = source[key];
    }
    if (isNew) {
      _baseAssignValue(object, key, newValue);
    } else {
      _assignValue(object, key, newValue);
    }
  }
  return object;
}

/* harmony default export */ const _copyObject = (copyObject);

// EXTERNAL MODULE: ./node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/_arrayLikeKeys.js + 1 modules
var _arrayLikeKeys = __webpack_require__(68180);
;// CONCATENATED MODULE: ./node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/_nativeKeysIn.js
/**
 * This function is like
 * [`Object.keys`](http://ecma-international.org/ecma-262/7.0/#sec-object.keys)
 * except that it includes inherited enumerable properties.
 *
 * @private
 * @param {Object} object The object to query.
 * @returns {Array} Returns the array of property names.
 */
function nativeKeysIn(object) {
  var result = [];
  if (object != null) {
    for (var key in Object(object)) {
      result.push(key);
    }
  }
  return result;
}

/* harmony default export */ const _nativeKeysIn = (nativeKeysIn);

;// CONCATENATED MODULE: ./node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/_baseKeysIn.js




/** Used for built-in method references. */
var _baseKeysIn_objectProto = Object.prototype;

/** Used to check objects for own properties. */
var _baseKeysIn_hasOwnProperty = _baseKeysIn_objectProto.hasOwnProperty;

/**
 * The base implementation of `_.keysIn` which doesn't treat sparse arrays as dense.
 *
 * @private
 * @param {Object} object The object to query.
 * @returns {Array} Returns the array of property names.
 */
function baseKeysIn(object) {
  if (!(0,isObject/* default */.Z)(object)) {
    return _nativeKeysIn(object);
  }
  var isProto = (0,_isPrototype/* default */.Z)(object),
      result = [];

  for (var key in object) {
    if (!(key == 'constructor' && (isProto || !_baseKeysIn_hasOwnProperty.call(object, key)))) {
      result.push(key);
    }
  }
  return result;
}

/* harmony default export */ const _baseKeysIn = (baseKeysIn);

;// CONCATENATED MODULE: ./node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/keysIn.js




/**
 * Creates an array of the own and inherited enumerable property names of `object`.
 *
 * **Note:** Non-object values are coerced to objects.
 *
 * @static
 * @memberOf _
 * @since 3.0.0
 * @category Object
 * @param {Object} object The object to query.
 * @returns {Array} Returns the array of property names.
 * @example
 *
 * function Foo() {
 *   this.a = 1;
 *   this.b = 2;
 * }
 *
 * Foo.prototype.c = 3;
 *
 * _.keysIn(new Foo);
 * // => ['a', 'b', 'c'] (iteration order is not guaranteed)
 */
function keysIn(object) {
  return (0,isArrayLike/* default */.Z)(object) ? (0,_arrayLikeKeys/* default */.Z)(object, true) : _baseKeysIn(object);
}

/* harmony default export */ const lodash_es_keysIn = (keysIn);

;// CONCATENATED MODULE: ./node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/toPlainObject.js



/**
 * Converts `value` to a plain object flattening inherited enumerable string
 * keyed properties of `value` to own properties of the plain object.
 *
 * @static
 * @memberOf _
 * @since 3.0.0
 * @category Lang
 * @param {*} value The value to convert.
 * @returns {Object} Returns the converted plain object.
 * @example
 *
 * function Foo() {
 *   this.b = 2;
 * }
 *
 * Foo.prototype.c = 3;
 *
 * _.assign({ 'a': 1 }, new Foo);
 * // => { 'a': 1, 'b': 2 }
 *
 * _.assign({ 'a': 1 }, _.toPlainObject(new Foo));
 * // => { 'a': 1, 'b': 2, 'c': 3 }
 */
function toPlainObject(value) {
  return _copyObject(value, lodash_es_keysIn(value));
}

/* harmony default export */ const lodash_es_toPlainObject = (toPlainObject);

;// CONCATENATED MODULE: ./node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/_baseMergeDeep.js
















/**
 * A specialized version of `baseMerge` for arrays and objects which performs
 * deep merges and tracks traversed objects enabling objects with circular
 * references to be merged.
 *
 * @private
 * @param {Object} object The destination object.
 * @param {Object} source The source object.
 * @param {string} key The key of the value to merge.
 * @param {number} srcIndex The index of `source`.
 * @param {Function} mergeFunc The function to merge values.
 * @param {Function} [customizer] The function to customize assigned values.
 * @param {Object} [stack] Tracks traversed source values and their merged
 *  counterparts.
 */
function baseMergeDeep(object, source, key, srcIndex, mergeFunc, customizer, stack) {
  var objValue = _safeGet(object, key),
      srcValue = _safeGet(source, key),
      stacked = stack.get(srcValue);

  if (stacked) {
    _assignMergeValue(object, key, stacked);
    return;
  }
  var newValue = customizer
    ? customizer(objValue, srcValue, (key + ''), object, source, stack)
    : undefined;

  var isCommon = newValue === undefined;

  if (isCommon) {
    var isArr = (0,isArray/* default */.Z)(srcValue),
        isBuff = !isArr && (0,isBuffer/* default */.Z)(srcValue),
        isTyped = !isArr && !isBuff && (0,isTypedArray/* default */.Z)(srcValue);

    newValue = srcValue;
    if (isArr || isBuff || isTyped) {
      if ((0,isArray/* default */.Z)(objValue)) {
        newValue = objValue;
      }
      else if (lodash_es_isArrayLikeObject(objValue)) {
        newValue = _copyArray(objValue);
      }
      else if (isBuff) {
        isCommon = false;
        newValue = _cloneBuffer(srcValue, true);
      }
      else if (isTyped) {
        isCommon = false;
        newValue = _cloneTypedArray(srcValue, true);
      }
      else {
        newValue = [];
      }
    }
    else if (lodash_es_isPlainObject(srcValue) || (0,isArguments/* default */.Z)(srcValue)) {
      newValue = objValue;
      if ((0,isArguments/* default */.Z)(objValue)) {
        newValue = lodash_es_toPlainObject(objValue);
      }
      else if (!(0,isObject/* default */.Z)(objValue) || (0,isFunction/* default */.Z)(objValue)) {
        newValue = _initCloneObject(srcValue);
      }
    }
    else {
      isCommon = false;
    }
  }
  if (isCommon) {
    // Recursively merge objects and arrays (susceptible to call stack limits).
    stack.set(srcValue, newValue);
    mergeFunc(newValue, srcValue, srcIndex, customizer, stack);
    stack['delete'](srcValue);
  }
  _assignMergeValue(object, key, newValue);
}

/* harmony default export */ const _baseMergeDeep = (baseMergeDeep);

;// CONCATENATED MODULE: ./node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/_baseMerge.js








/**
 * The base implementation of `_.merge` without support for multiple sources.
 *
 * @private
 * @param {Object} object The destination object.
 * @param {Object} source The source object.
 * @param {number} srcIndex The index of `source`.
 * @param {Function} [customizer] The function to customize merged values.
 * @param {Object} [stack] Tracks traversed source values and their merged
 *  counterparts.
 */
function baseMerge(object, source, srcIndex, customizer, stack) {
  if (object === source) {
    return;
  }
  (0,_baseFor/* default */.Z)(source, function(srcValue, key) {
    stack || (stack = new _Stack/* default */.Z);
    if ((0,isObject/* default */.Z)(srcValue)) {
      _baseMergeDeep(object, source, key, srcIndex, baseMerge, customizer, stack);
    }
    else {
      var newValue = customizer
        ? customizer(_safeGet(object, key), srcValue, (key + ''), object, source, stack)
        : undefined;

      if (newValue === undefined) {
        newValue = srcValue;
      }
      _assignMergeValue(object, key, newValue);
    }
  }, lodash_es_keysIn);
}

/* harmony default export */ const _baseMerge = (baseMerge);

// EXTERNAL MODULE: ./node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/_baseRest.js
var _baseRest = __webpack_require__(39185);
// EXTERNAL MODULE: ./node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/_isIterateeCall.js
var _isIterateeCall = __webpack_require__(32554);
;// CONCATENATED MODULE: ./node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/_createAssigner.js



/**
 * Creates a function like `_.assign`.
 *
 * @private
 * @param {Function} assigner The function to assign values.
 * @returns {Function} Returns the new assigner function.
 */
function createAssigner(assigner) {
  return (0,_baseRest/* default */.Z)(function(object, sources) {
    var index = -1,
        length = sources.length,
        customizer = length > 1 ? sources[length - 1] : undefined,
        guard = length > 2 ? sources[2] : undefined;

    customizer = (assigner.length > 3 && typeof customizer == 'function')
      ? (length--, customizer)
      : undefined;

    if (guard && (0,_isIterateeCall/* default */.Z)(sources[0], sources[1], guard)) {
      customizer = length < 3 ? undefined : customizer;
      length = 1;
    }
    object = Object(object);
    while (++index < length) {
      var source = sources[index];
      if (source) {
        assigner(object, source, index, customizer);
      }
    }
    return object;
  });
}

/* harmony default export */ const _createAssigner = (createAssigner);

;// CONCATENATED MODULE: ./node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/merge.js



/**
 * This method is like `_.assign` except that it recursively merges own and
 * inherited enumerable string keyed properties of source objects into the
 * destination object. Source properties that resolve to `undefined` are
 * skipped if a destination value exists. Array and plain object properties
 * are merged recursively. Other objects and value types are overridden by
 * assignment. Source objects are applied from left to right. Subsequent
 * sources overwrite property assignments of previous sources.
 *
 * **Note:** This method mutates `object`.
 *
 * @static
 * @memberOf _
 * @since 0.5.0
 * @category Object
 * @param {Object} object The destination object.
 * @param {...Object} [sources] The source objects.
 * @returns {Object} Returns `object`.
 * @example
 *
 * var object = {
 *   'a': [{ 'b': 2 }, { 'd': 4 }]
 * };
 *
 * var other = {
 *   'a': [{ 'c': 3 }, { 'e': 5 }]
 * };
 *
 * _.merge(object, other);
 * // => { 'a': [{ 'b': 2, 'c': 3 }, { 'd': 4, 'e': 5 }] }
 */
var merge = _createAssigner(function(object, source, srcIndex) {
  _baseMerge(object, source, srcIndex);
});

/* harmony default export */ const lodash_es_merge = (merge);

// EXTERNAL MODULE: ./node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/_arraySome.js
var _arraySome = __webpack_require__(33909);
// EXTERNAL MODULE: ./node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/_baseIteratee.js + 29 modules
var _baseIteratee = __webpack_require__(45981);
// EXTERNAL MODULE: ./node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/_baseEach.js + 2 modules
var _baseEach = __webpack_require__(65758);
;// CONCATENATED MODULE: ./node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/_baseSome.js


/**
 * The base implementation of `_.some` without support for iteratee shorthands.
 *
 * @private
 * @param {Array|Object} collection The collection to iterate over.
 * @param {Function} predicate The function invoked per iteration.
 * @returns {boolean} Returns `true` if any element passes the predicate check,
 *  else `false`.
 */
function baseSome(collection, predicate) {
  var result;

  (0,_baseEach/* default */.Z)(collection, function(value, index, collection) {
    result = predicate(value, index, collection);
    return !result;
  });
  return !!result;
}

/* harmony default export */ const _baseSome = (baseSome);

;// CONCATENATED MODULE: ./node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/some.js






/**
 * Checks if `predicate` returns truthy for **any** element of `collection`.
 * Iteration is stopped once `predicate` returns truthy. The predicate is
 * invoked with three arguments: (value, index|key, collection).
 *
 * @static
 * @memberOf _
 * @since 0.1.0
 * @category Collection
 * @param {Array|Object} collection The collection to iterate over.
 * @param {Function} [predicate=_.identity] The function invoked per iteration.
 * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
 * @returns {boolean} Returns `true` if any element passes the predicate check,
 *  else `false`.
 * @example
 *
 * _.some([null, 0, 'yes', false], Boolean);
 * // => true
 *
 * var users = [
 *   { 'user': 'barney', 'active': true },
 *   { 'user': 'fred',   'active': false }
 * ];
 *
 * // The `_.matches` iteratee shorthand.
 * _.some(users, { 'user': 'barney', 'active': false });
 * // => false
 *
 * // The `_.matchesProperty` iteratee shorthand.
 * _.some(users, ['active', false]);
 * // => true
 *
 * // The `_.property` iteratee shorthand.
 * _.some(users, 'active');
 * // => true
 */
function some(collection, predicate, guard) {
  var func = (0,isArray/* default */.Z)(collection) ? _arraySome/* default */.Z : _baseSome;
  if (guard && (0,_isIterateeCall/* default */.Z)(collection, predicate, guard)) {
    predicate = undefined;
  }
  return func(collection, (0,_baseIteratee/* default */.Z)(predicate, 3));
}

/* harmony default export */ const lodash_es_some = (some);

// EXTERNAL MODULE: ./node_modules/.pnpm/bowser@2.11.0/node_modules/bowser/es5.js
var es5 = __webpack_require__(63596);
var es5_default = /*#__PURE__*/__webpack_require__.n(es5);
// EXTERNAL MODULE: ./node_modules/.pnpm/@adguard+scriptlets@1.12.1/node_modules/@adguard/scriptlets/dist/umd/scriptlets.umd.js
var scriptlets_umd = __webpack_require__(97730);
// EXTERNAL MODULE: ./node_modules/.pnpm/lru_map@0.4.1/node_modules/lru_map/dist/lru.js
var lru = __webpack_require__(8178);
;// CONCATENATED MODULE: ./node_modules/.pnpm/@adguard+tswebextension@2.4.0-alpha.11_@adguard+re2-wasm@1.2.0/node_modules/@adguard/tswebextension/dist/index.js












/**
 * Filter ID which is used for User rules.
 */
const USER_FILTER_ID = 0;
/**
 * Filter ID which is used for Allowlist.
 */
const ALLOWLIST_FILTER_ID = 100;
/**
 * Custom filters identifiers starts from this number.
 */
const CUSTOM_FILTERS_START_ID = 1000;
/**
 * Filter ID for AdGuard Quick Fixes filter.
 *
 * @see {@link https://github.com/AdguardTeam/FiltersRegistry/blob/master/filters/filter_24_QuickFixes/metadata.json}
 */
const QUICK_FIXES_FILTER_ID = 24;
/**
 * Tab ID for background page.
 */
const BACKGROUND_TAB_ID = (/* unused pure expression or super */ null && (-1));
/**
 * Line feed character.
 */
const LF$1 = '\n';
/**
 * Timeout used for deletion of request context data and frame context data from the storage.
 */
const FRAME_DELETION_TIMEOUT_MS = 3000;
/**
 * Document level frame id.
 */
const MAIN_FRAME_ID = 0;

/**
 * The allowlist is used to exclude certain websites from filtering.
 * Blocking rules are not applied to the sites in the list.
 * The allow list can also be inverted.
 * In inverted mode, the application will unblock ads everywhere except for the
 * sites added to this list.
 */
let Allowlist$1 = class Allowlist {
    /**
     * Indicates whether the allowlist is enabled.
     */
    enabled = false;
    /**
     * If true, ads will be blocked only on sites listed in the allowlist,
     * like "blocklist" mode.
     */
    inverted = false;
    /**
     * List of domains which are allowed (by default)
     * or blocked (if the allowlist is inverted).
     */
    domains = [];
    /**
     * Configures allowlist state based on app configuration.
     *
     * @param configuration App configuration.
     */
    configure(configuration) {
        const { allowlist, settings, } = configuration;
        const { allowlistEnabled, allowlistInverted, } = settings;
        this.enabled = allowlistEnabled;
        this.inverted = allowlistInverted;
        this.domains = allowlist.map((hostname) => {
            return hostname.startsWith('www.') ? hostname.substring(4).trim() : hostname.trim();
        });
    }
    /**
     * Returns a list of rules to be loaded into the engine based on allowlist state.
     *
     * @returns List of allowlist rules or null.
     */
    getAllowlistRules() {
        if (!this.enabled || this.inverted) {
            return null;
        }
        return (0,es/* createAllowlistRuleList */.kz)(ALLOWLIST_FILTER_ID, this.domains);
    }
    /**
     * Creates an allowlist rule for a domain which will be passed to our engine
     * to unblock requests. In MV3 we will pass this rule to TsUrlFilter engine,
     * because it do work with cosmetic rules.
     *
     * @param domain Domain name.
     *
     * @returns Allowlist rule or null.
     */
    static createAllowlistRule(domain) {
        if (!domain) {
            return null;
        }
        return es/* RuleFactory.createAllowlistRule */.Nr.createAllowlistRule(domain, ALLOWLIST_FILTER_ID);
    }
};

/**
 * The allowlist is used to exclude certain websites from filtering.
 * Blocking rules are not applied to the sites in the list.
 * The allow list can also be inverted.
 * In inverted mode, the application will unblock ads everywhere except for the sites added to this list.
 */
class Allowlist extends Allowlist$1 {
}

/**
 * Checks if url is http request.
 *
 * @param url Request url.
 * @returns True if url starts with http{s?}.
 */
function isHttpRequest(url) {
    return typeof url === 'string' && !!url && url.startsWith('http');
}
/**
 * Checks if url is http or websocket.
 *
 * @param url Request url.
 * @returns True if url starts with http{s?} or ws.
 */
function isHttpOrWsRequest(url) {
    return !!url && (url.startsWith('http') || url.startsWith('ws'));
}
/**
 * Extract host from url.
 *
 * @param url Url.
 * @returns Host of the url or null.
 */
function getHost(url) {
    let firstIdx = url.indexOf('//');
    if (firstIdx === -1) {
        /**
         * It's non-hierarchical structured URL (stun: or turn:).
         *
         * @see {@link https://tools.ietf.org/html/rfc4395#section-2.2}
         * @see {@link https://tools.ietf.org/html/draft-nandakumar-rtcweb-stun-uri-08#appendix-B}
         */
        firstIdx = url.indexOf(':');
        if (firstIdx === -1) {
            return null;
        }
        firstIdx -= 1;
    }
    const nextSlashIdx = url.indexOf('/', firstIdx + 2);
    const startParamsIdx = url.indexOf('?', firstIdx + 2);
    let lastIdx = nextSlashIdx;
    if (startParamsIdx > 0 && (startParamsIdx < nextSlashIdx || nextSlashIdx < 0)) {
        lastIdx = startParamsIdx;
    }
    let host = lastIdx === -1 ? url.substring(firstIdx + 2) : url.substring(firstIdx + 2, lastIdx);
    const portIndex = host.indexOf(':');
    host = portIndex === -1 ? host : host.substring(0, portIndex);
    const lastChar = host.charAt(host.length - 1);
    if (lastChar === '.') {
        host = host.slice(0, -1);
    }
    return host;
}
/**
 * Extracts domain name from url.
 *
 * @param url Url.
 * @returns Domain name or null.
 */
function getDomain(url) {
    const host = getHost(url);
    if (!host) {
        return null;
    }
    return host.startsWith('www.') ? host.substring(4) : host;
}
/**
 * If referrer of request contains full url of extension, then this request is considered as extension's own request.
 * Example: request for filter downloading.
 * Related issue: @see {@link https://github.com/AdguardTeam/AdguardBrowserExtension/issues/1437}.
 *
 * @param url Request url.
 * @returns True if request is extension's own.
 */
function isExtensionUrl(url) {
    return url.indexOf(browser.runtime.getURL('')) === 0;
}
/**
 * Checks third party relation.
 *
 * @param requestUrl Request url.
 * @param referrer Referrer url.
 * @returns True if request is third-party.
 */
function isThirdPartyRequest(requestUrl, referrer) {
    const tldResult = (0,es6/* parse */.Qc)(requestUrl);
    const sourceTldResult = (0,es6/* parse */.Qc)(referrer);
    return tldResult.domain !== sourceTldResult.domain;
}
/**
 * Extracts upper level domain from domain.
 *
 * @param domain Domain.
 *
 * @example getUpperLevelDomain('www.example.com') => 'example.com'
 * @example getUpperLevelDomain('test.pages.dev') => 'pages.dev'
 * @example getUpperLevelDomain('allowlist.test.pages.dev') => 'test.pages.dev'
 *
 * @returns Upper level domain.
 */
function getUpperLevelDomain(domain) {
    const parts = domain.split('.');
    parts.shift();
    return parts.join('.');
}

/**
 * TSUrlFilter Engine wrapper.
 */
class EngineApi {
    allowlist;
    appContext;
    stealthApi;
    static ASYNC_LOAD_CHINK_SIZE = 5000;
    engine;
    dynamicFilters = new Map();
    /**
     * Gets app filtering status.
     *
     * @returns True if filtering is enabled, otherwise returns false.
     */
    get isFilteringEnabled() {
        // TODO: Remove this check after moving call of storage initialization in extension code.
        // Check this flag before access storage values, because engine methods
        // can by triggered before initialization by content script requests.
        if (!this.appContext.isStorageInitialized) {
            return false;
        }
        return Boolean(this.appContext.configuration?.settings.filteringEnabled);
    }
    /**
     * Creates Engine Api instance.
     *
     * @param allowlist Allowlist.
     * @param appContext App context.
     * @param stealthApi Stealth Api.
     */
    constructor(allowlist, appContext, stealthApi) {
        this.allowlist = allowlist;
        this.appContext = appContext;
        this.stealthApi = stealthApi;
    }
    /**
     * Starts engine.
     *
     * @param configuration Engine configuration.
     */
    async startEngine(configuration) {
        const { filters, userrules, verbose, } = configuration;
        this.allowlist.configure(configuration);
        const lists = [];
        for (let i = 0; i < filters.length; i += 1) {
            const { filterId, content, trusted, sourceMap, } = filters[i];
            lists.push(new es/* BufferRuleList */.bm(filterId, content, false, !trusted, !trusted, sourceMap));
        }
        if (userrules.content.length > 0) {
            lists.push(new es/* BufferRuleList */.bm(USER_FILTER_ID, userrules.content, false, false, false, userrules.sourceMap));
        }
        const allowlistRulesList = this.allowlist.getAllowlistRules();
        if (allowlistRulesList) {
            lists.push(allowlistRulesList);
            this.dynamicFilters.set(ALLOWLIST_FILTER_ID, allowlistRulesList);
        }
        const stealthModeList = this.stealthApi.getStealthModeRuleList();
        if (stealthModeList) {
            lists.push(stealthModeList);
            this.dynamicFilters.set(es/* STEALTH_MODE_FILTER_ID */.AG, stealthModeList);
        }
        const ruleStorage = new es/* RuleStorage */.qc(lists);
        (0,es/* setConfiguration */.Dg)({
            engine: 'extension',
            version: browser_polyfill_default().runtime.getManifest().version,
            verbose,
            compatibility: es/* CompatibilityTypes.Extension */.cC.Extension,
        });
        /*
         * UI thread becomes blocked on the options page while request filter is created
         * that's why we create filter rules using chunks of the specified length
         * Request filter creation is rather slow operation so we should
         * use setTimeout calls to give UI thread some time.
        */
        const engine = new es/* Engine */.D4(ruleStorage, true);
        await engine.loadRulesAsync(EngineApi.ASYNC_LOAD_CHINK_SIZE);
        this.engine = engine;
    }
    /**
     * Searched for rules by match query.
     *
     * @param matchQuery Query against which the request would be matched.
     * @returns Matching result or null.
     */
    matchRequest(matchQuery) {
        if (!this.engine || !this.isFilteringEnabled) {
            return null;
        }
        const { requestUrl, frameUrl, requestType, method, } = matchQuery;
        let { frameRule } = matchQuery;
        const request = new es/* Request */.cf(requestUrl, frameUrl, requestType, method);
        if (!frameRule) {
            frameRule = null;
        }
        return this.engine.matchRequest(request, frameRule);
    }
    /**
     * Searched for cosmetic rules by match query.
     *
     * @param matchQuery Query against which the request would be matched.
     * @returns Cosmetic result.
     */
    matchCosmetic(matchQuery) {
        if (!this.engine || !this.isFilteringEnabled || !isHttpRequest(matchQuery.frameUrl)) {
            return new es/* CosmeticResult */.cT();
        }
        const matchingResult = this.matchRequest(matchQuery);
        if (!matchingResult) {
            return new es/* CosmeticResult */.cT();
        }
        const cosmeticOption = matchingResult.getCosmeticOption();
        return this.getCosmeticResult(matchQuery.requestUrl, cosmeticOption);
    }
    /**
     * Matches current frame url and returns rule if found.
     *
     * @param frameUrl Frame url.
     * @returns NetworkRule or null.
     */
    matchFrame(frameUrl) {
        if (!this.engine || !this.isFilteringEnabled || !isHttpRequest(frameUrl)) {
            return null;
        }
        return this.engine.matchFrame(frameUrl);
    }
    /**
     * Gets cosmetic result for the specified hostname and cosmetic options.
     *
     * @param url Request url.
     * @param option Cosmetic options.
     * @returns Cosmetic result.
     */
    getCosmeticResult(url, option) {
        if (!this.engine || !this.isFilteringEnabled) {
            return new es/* CosmeticResult */.cT();
        }
        const frameUrl = getHost(url);
        const request = new es/* Request */.cf(url, frameUrl, es/* RequestType.Document */.xd.Document);
        return this.engine.getCosmeticResult(request, option);
    }
    /**
     * Retrieves rule node from a dynamic filter.
     * Dynamic filters are filters that are not loaded from the storage but created on the fly.
     *
     * @param filterId Filter id.
     * @param ruleIndex Rule index.
     * @returns Rule node or null.
     */
    retrieveDynamicRuleNode(filterId, ruleIndex) {
        const ruleList = this.dynamicFilters.get(filterId);
        if (!ruleList) {
            return null;
        }
        return ruleList.retrieveRuleNode(ruleIndex);
    }
    /**
     * Simple getter for rules count.
     *
     * @returns Number of rules in the engine.
     */
    getRulesCount() {
        return this.engine ? this.engine.getRulesCount() : 0;
    }
}

/**
 * Matches rules from {@link EngineApi} based on current {@link Allowlist} state.
 */
class DocumentApi {
    allowlist;
    engineApi;
    /**
     * Creates new DocumentApi instance.
     *
     * @param allowlist Allowlist API.
     * @param engineApi Engine API.
     */
    constructor(allowlist, engineApi) {
        this.allowlist = allowlist;
        this.engineApi = engineApi;
    }
    /**
     * Match frame rule based on allowlist state.
     *
     * @param frameUrl Frame url.
     * @returns Matched rule or null.
     */
    matchFrame(frameUrl) {
        const { enabled, inverted } = this.allowlist;
        /**
         * If inverted allowlist enabled, use specific matching strategy.
         */
        if (enabled && inverted) {
            return this.matchFrameInverted(frameUrl);
        }
        /**
         * If allowlist mode is default, request rule from engine.
         * If allowlist is enabled, rules have already loaded.
         */
        return this.engineApi.matchFrame(frameUrl);
    }
    /**
     * Creates allowlist rule for domains that are not in the inverted list.
     * In other cases returns engine matched rule.
     *
     * @param frameUrl Frame url.
     * @returns Matched rule or null.
     */
    matchFrameInverted(frameUrl) {
        const domain = getDomain(frameUrl);
        if (!domain) {
            return null;
        }
        const upperDomain = getUpperLevelDomain(domain);
        if (!this.allowlist.domains.includes(domain) && !this.allowlist.domains.includes(`*.${upperDomain}`)) {
            return Allowlist.createAllowlistRule(domain);
        }
        return this.engineApi.matchFrame(frameUrl);
    }
}

/**
 * Simple pub-sub implementation.
 */
class EventChannel {
    listeners = [];
    /**
     * Dispatch event.
     *
     * @param data Event data.
     */
    dispatch(data) {
        this.listeners.forEach((listener) => listener(data));
    }
    /**
     * Subscribe to events channel.
     *
     * @param listener Callback to be called on event.
     */
    subscribe(listener) {
        this.listeners.push(listener);
    }
    /**
     * Unsubscribe from events channel.
     *
     * @param listener Callback to be removed from listeners.
     */
    unsubscribe(listener) {
        const index = this.listeners.indexOf(listener);
        if (index !== -1) {
            this.listeners.splice(index, 1);
        }
    }
}

var RequestType = {
    NotSet: 0,
    Document: 1,
    SubDocument: 2,
    Script: 4,
    Stylesheet: 8,
    Object: 16,
    Image: 32,
    XmlHttpRequest: 64,
    Media: 128,
    Font: 256,
    WebSocket: 512,
    Ping: 1024,
    CspReport: 2048,
    Other: 4096,
};

/**
 * Frame context data.
 * We store {@link MatchingResult} and {@link CosmeticResult} in the frame context
 * to apply rules that cannot be handled during request processing.
 * The frame data is deleted after the {@link browser.webNavigation.onCompleted} event.
 * @see {@link WebRequestApi.deleteFrameContext}
 */
class Frame {
    /**
     * Frame url.
     */
    url;
    /**
     * Frame request id.
     */
    requestId;
    /**
     * Frame cosmetic result.
     * This data is saved in the frame because we need to access it for css injection
     * after deleting request context data.
     *
     * @see {@link WebRequestApi.injectCosmetic}
     */
    cosmeticResult;
    /**
     * Frame matching result.
     * This data is saved in frame, because we need for access it for script rules injection
     * after deleting request context data.
     */
    matchingResult;
    /**
     * Creates frame instance.
     *
     * @param url Frame url.
     * @param requestId Request id.
     */
    constructor(url, requestId) {
        this.url = url;
        this.requestId = requestId;
    }
}

function isErrorWithMessage$2(error) {
    return (typeof error === 'object'
        && error !== null
        && 'message' in error
        && typeof error.message === 'string');
}
function toErrorWithMessage$2(maybeError) {
    if (isErrorWithMessage$2(maybeError)) {
        return maybeError;
    }
    try {
        return new Error(JSON.stringify(maybeError));
    }
    catch {
        return new Error(String(maybeError));
    }
}
function getErrorMessage$2(error) {
    return toErrorWithMessage$2(error).message;
}
const pad = (num, size = 2) => {
    return num.toString().padStart(size, '0');
};
const formatTime = (date) => {
    const d = (date instanceof Date) ? date : new Date(date);
    const year = d.getFullYear();
    const month = pad(d.getMonth() + 1);
    const day = pad(d.getDate());
    const hour = pad(d.getHours());
    const minute = pad(d.getMinutes());
    const second = pad(d.getSeconds());
    const millisecond = pad(d.getMilliseconds(), 3);
    return `${year}-${month}-${day}T${hour}:${minute}:${second}:${millisecond}`;
};
var LogLevel;
(function (LogLevel) {
    LogLevel["Error"] = "error";
    LogLevel["Warn"] = "warn";
    LogLevel["Info"] = "info";
    LogLevel["Debug"] = "debug";
    LogLevel["Trace"] = "trace";
})(LogLevel || (LogLevel = {}));
const levelMapNumToString = {
    [1 ]: LogLevel.Error,
    [2 ]: LogLevel.Warn,
    [3 ]: LogLevel.Info,
    [4 ]: LogLevel.Debug,
    [5 ]: LogLevel.Trace,
};
const levelMapStringToNum = Object.entries(levelMapNumToString)
    .reduce((acc, [key, value]) => {
    const numericKey = Number(key);
    if (!Number.isNaN(numericKey)) {
        acc[value] = numericKey;
    }
    return acc;
}, {});
class Logger {
    currentLevelValue = 3 ;
    writer;
    constructor(writer = console) {
        this.writer = writer;
        this.debug = this.debug.bind(this);
        this.info = this.info.bind(this);
        this.warn = this.warn.bind(this);
        this.error = this.error.bind(this);
    }
    debug(...args) {
        this.print(4 , "log" , args);
    }
    info(...args) {
        this.print(3 , "info" , args);
    }
    warn(...args) {
        this.print(2 , "info" , args);
    }
    error(...args) {
        this.print(1 , "error" , args);
    }
    get currentLevel() {
        return levelMapNumToString[this.currentLevelValue];
    }
    set currentLevel(logLevel) {
        const level = levelMapStringToNum[logLevel];
        if (level === undefined) {
            throw new Error(`Logger supports only the following levels: ${[Object.values(LogLevel).join(', ')]}`);
        }
        this.currentLevelValue = level;
    }
    static errorToString(error) {
        const message = getErrorMessage$2(error);
        return `${message}\nStack trace:\n${error.stack}`;
    }
    print(level, method, args) {
        if (this.currentLevelValue < level) {
            return;
        }
        if (!args || args.length === 0 || !args[0]) {
            return;
        }
        const formattedArgs = args.map((value) => {
            if (value instanceof Error) {
                return Logger.errorToString(value);
            }
            if (value && typeof value.message === 'string') {
                return value.message;
            }
            if (typeof value === 'object' && value !== null) {
                return JSON.stringify(value);
            }
            return String(value);
        });
        const formattedTime = `${formatTime(new Date())}:`;
        if (method === "error"
            || this.currentLevelValue < levelMapStringToNum[LogLevel.Trace]
            || !this.writer.trace) {
            this.writer[method](formattedTime, ...formattedArgs);
            return;
        }
        if (!this.writer.groupCollapsed || !this.writer.groupEnd) {
            this.writer.trace(formattedTime, ...formattedArgs);
            return;
        }
        this.writer.groupCollapsed(formattedTime, ...formattedArgs);
        this.writer.trace();
        this.writer.groupEnd();
    }
}

/**
 * Export logger implementation.
 */
const logger = new Logger(console);
/**
 * Stringify object via JSON.stringify without specified keys.
 *
 * @param obj Object to stringify.
 * @param excludedKeys Keys to exclude.
 *
 * @returns Stringified object without excludedKeys (checking nested keys too).
 */
const stringifyObjectWithoutKeys = (obj, excludedKeys) => {
    return JSON.stringify(obj, (key, value) => (excludedKeys.includes(key) ? undefined : value), 2);
};

/**
 * Finds header object by header name (case-insensitive).
 *
 * @param headers Headers collection.
 * @param headerName Header name.
 * @returns Found header, or null if not found.
 */
function findHeaderByName$1(headers, headerName) {
    const lowerCaseHeaderName = headerName.toLowerCase();
    for (const header of headers) {
        if (header.name.toLowerCase() === lowerCaseHeaderName) {
            return header;
        }
    }
    return null;
}

/**
 * Check if the frame URL is about:blank or about:srcdoc.
 *
 * @param frameUrl Frame URL.
 *
 * @returns True if frame URL is about:blank or about:srcdoc, otherwise false.
 */
const isEmptySrcFrame = (frameUrl) => {
    return frameUrl === 'about:blank'
        || frameUrl === 'about:srcdoc';
};

// TODO: Add 'is' prefix to cssRule, scriptRule and contentRule properties.
/**
 * Types of filtering events that can occur during request processing.
 */
var FilteringEventType;
(function (FilteringEventType) {
    FilteringEventType["SendRequest"] = "sendRequest";
    FilteringEventType["TabReload"] = "tabReload";
    FilteringEventType["ApplyBasicRule"] = "applyBasicRule";
    FilteringEventType["ApplyCosmeticRule"] = "applyCosmeticRule";
    FilteringEventType["ApplyCspRule"] = "applyCspRule";
    FilteringEventType["ApplyPermissionsRule"] = "applyPermissionsRule";
    FilteringEventType["ReceiveResponse"] = "receiveResponse";
    FilteringEventType["Cookie"] = "cookie";
    FilteringEventType["RemoveHeader"] = "removeHeader";
    FilteringEventType["RemoveParam"] = "removeParam";
    FilteringEventType["ReplaceRuleApply"] = "replaceRuleApply";
    FilteringEventType["ContentFilteringStart"] = "contentFilteringStart";
    FilteringEventType["ContentFilteringFinish"] = "contentFilteringFinish";
    FilteringEventType["StealthAction"] = "stealthAction";
    FilteringEventType["StealthAllowlistAction"] = "stealthAllowlistAction";
    FilteringEventType["JsInject"] = "jsInject";
    FilteringEventType["CspReportBlocked"] = "cspReportBlocked";
    /**
     * Used only in unpacked MV3.
     */
    FilteringEventType["MatchedDeclarativeRule"] = "matchedDeclarativeRule";
})(FilteringEventType || (FilteringEventType = {}));
/**
 * {@link FilteringLogInterface} Default implementation.
 */
class FilteringLog {
    onLogEvent = new EventChannel();
    channels = [];
    /**
     * Registers listener for specified {@link FilteringLogEvent}.
     *
     * @param type Filtering log type.
     * @param listener Filtering log listener.
     */
    addEventListener(type, listener) {
        const channel = { type, listener };
        this.channels.push(channel);
    }
    /**
     * Publishes event to attached listeners.
     *
     * @param event Filtering log event.
     */
    publishEvent(event) {
        const listeners = this.channels
            .filter(({ type }) => type === event.type)
            .map(({ listener }) => listener);
        for (const listener of listeners) {
            listener(event);
        }
        this.onLogEvent.dispatch(event);
    }
}
/**
 * Shared {@link FilteringLog} instance.
 */
const defaultFilteringLog = new FilteringLog();

/**
 * Tab context.
 */
class TabContext {
    info;
    documentApi;
    filteringLog;
    /**
     * Frames context.
     * NOTE: this is temporary storage for frames data.
     * Each frame context is deleted after navigation is complete.
     * Storage is cleared on tab reload.
     * Do not use it as a data source out of request or navigation processing.
     */
    frames = new Map();
    /**
     * Blocked request count.
     */
    blockedRequestCount = 0;
    /**
     * Document level rule, applied to the tab.
     */
    mainFrameRule = null;
    /**
     * We mark these tabs as synthetic because they may not actually exist.
     */
    isSyntheticTab = true;
    /**
     * Is document page request handled by memory cache or sw.
     */
    isDocumentRequestCached = false;
    /**
     * Timestamp of the assistant initialization.
     *
     * Needed to avoid cosmetic rules injection into the assistant frame.
     *
     * @see {@link https://github.com/AdguardTeam/AdguardBrowserExtension/issues/1848}
     */
    assistantInitTimestamp = null;
    /**
     * Tab creation timestamp in milliseconds.
     */
    createdAtMs;
    /**
     * Context constructor.
     *
     * @param info Webextension API tab data.
     * @param documentApi Document API.
     * @param filteringLog Filtering Log API.
     */
    constructor(info, documentApi, filteringLog = defaultFilteringLog) {
        this.info = info;
        this.documentApi = documentApi;
        this.filteringLog = filteringLog;
        this.info = info;
        this.createdAtMs = Date.now();
    }
    /**
     * Updates tab info.
     *
     * @param changeInfo Tab change info.
     * @param tabInfo Tab info.
     */
    updateTabInfo(changeInfo, tabInfo) {
        this.info = tabInfo;
        // If the tab was updated it means that it wasn't used to send requests in the background.
        this.isSyntheticTab = false;
        /**
         * When the cached page is reloaded, we need to manually update
         * the main frame rule for correct document-level rule processing.
         *
         * Prop `isDocumentRequestCached` is being set at {@link updateMainFrameData} method,
         * which is fired on main frame update before first {@link browser.tabs.onUpdated} event.
         */
        if (!changeInfo.url
            && changeInfo.status === 'loading'
            && this.isDocumentRequestCached
            && this.info.url) {
            this.handleMainFrameRequest(this.info.url);
        }
    }
    /**
     * Updates main frame data.
     *
     * Note: this method will be called on tab reload before the first {@link browser.tabs.onUpdated} event
     * and {@link handleTabUpdate} and {@link updateTabInfo} calls.
     *
     * @param tabId Tab ID.
     * @param url Url.
     */
    updateMainFrameData(tabId, url) {
        this.info.url = url;
        this.info.id = tabId;
        // Get current main frame.
        const frame = this.frames.get(MAIN_FRAME_ID);
        // If main frame url is the same as request url, do nothing.
        if (frame?.url === url) {
            return;
        }
        /**
         * If the main frame doesn't exist or its URL is different from the request URL,
         * we mark the tab as using the cache and update its context using the tabsApi,
         * as it means that the document request hasn't been processed by the WebRequestApi yet.
         */
        this.isDocumentRequestCached = true;
        // Update main frame data.
        this.handleMainFrameRequest(url);
    }
    /**
     * Increments blocked requests count.
     */
    incrementBlockedRequestCount() {
        this.blockedRequestCount += 1;
    }
    /**
     * Handles document or subdocument request and stores data in specified frame context.
     * If the request is a document request, will also match the main frame rule
     * and store it in the {@link mainFrameRule} property.
     * This method is called before filtering processing in WebRequest onBeforeRequest handler.
     * MatchingResult is handled in {@link handleFrameMatchingResult}.
     *
     * CosmeticResult is handled in {@link handleFrameCosmeticResult}.
     *
     * @param requestContext Request context data.
     */
    handleFrameRequest(requestContext) {
        // This method is called in the WebRequest onBeforeRequest handler.
        // It means that the request is being processed.
        this.isDocumentRequestCached = false;
        const { frameId, requestId, requestUrl, requestType, } = requestContext;
        // Ignore non-http requests.
        if (!isHttpRequest(requestUrl)) {
            return;
        }
        if (requestType === RequestType.Document) {
            this.handleMainFrameRequest(requestUrl, requestId);
        }
        else {
            this.frames.set(frameId, new Frame(requestUrl, requestId));
        }
    }
    /**
     * Handles request {@link MatchingResult} from WebRequest onBeforeRequest handler
     * and stores it in specified frame context.
     *
     * @param frameId Frame id.
     * @param matchingResult Matching result.
     */
    handleFrameMatchingResult(frameId, matchingResult) {
        const frame = this.frames.get(frameId);
        if (frame) {
            frame.matchingResult = matchingResult;
        }
    }
    /**
     * Handles frame {@link CosmeticResult} from WebRequest onBeforeRequest handler
     * and stores it in specified frame context.
     *
     * @param frameId Frame id.
     * @param cosmeticResult Cosmetic result.
     */
    handleFrameCosmeticResult(frameId, cosmeticResult) {
        const frame = this.frames.get(frameId);
        if (frame) {
            frame.cosmeticResult = cosmeticResult;
        }
    }
    /**
     * Handles document request and updates main frame context.
     *
     * Also matches document level rule and store it {@link mainFrameRule}.
     *
     * MatchingResult handles in {@link handleFrameMatchingResult}.
     * CosmeticResult handles in {@link handleFrameCosmeticResult}.
     *
     * @param requestUrl Request url.
     * @param requestId Request id.
     */
    handleMainFrameRequest(requestUrl, requestId) {
        // Clear frames data on tab reload.
        this.frames.clear();
        // Set new main frame data.
        this.frames.set(MAIN_FRAME_ID, new Frame(requestUrl, requestId));
        // Calculate new main frame rule.
        this.mainFrameRule = this.documentApi.matchFrame(requestUrl);
        // Reset tab blocked count.
        this.blockedRequestCount = 0;
    }
    /**
     * Creates context for new tab.
     *
     * @param tab Webextension API tab data.
     * @param documentApi Document API.
     * @returns Tab context for new tab.
     */
    static createNewTabContext(tab, documentApi) {
        const tabContext = new TabContext(tab, documentApi);
        // In some cases, tab is created while browser navigation processing.
        // For example: when you navigate outside the browser or create new empty tab.
        // `pendingUrl` represent url navigated to. We check it first.
        // If server returns redirect, new main frame url will be processed in WebRequestApi.
        const url = tab.pendingUrl || tab.url;
        if (url && isHttpOrWsRequest(url)) {
            tabContext.mainFrameRule = documentApi.matchFrame(url);
            tabContext.frames.set(MAIN_FRAME_ID, new Frame(url));
        }
        return tabContext;
    }
    /**
     * Checks if passed {@link Tabs.Tab} details represent a browser tab.
     *
     * @see https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/tabs/Tab#type
     * @see https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/tabs/TAB_ID_NONE
     *
     * @param tab Tab details.
     * @returns True if the tab is a browser tab, otherwise returns false.
     */
    static isBrowserTab(tab) {
        return typeof tab.id === 'number' && tab.id !== (browser_polyfill_default()).tabs.TAB_ID_NONE;
    }
}

/**
 * Tabs API. Wrapper around browser.tabs API.
 */
class TabsApi {
    documentApi;
    // TODO: Use a persistent map when the extended serialization is implemented. (AG-27098)
    context = new Map();
    onCreate = new EventChannel();
    onUpdate = new EventChannel();
    onDelete = new EventChannel();
    onActivate = new EventChannel();
    onReplace = new EventChannel();
    /**
     * Timeout for popup tabs in milliseconds. We consider a tab as a popup if it was created within this time period.
     */
    static POPUP_TAB_TIMEOUT_MS = 250;
    /**
     * Tabs API constructor.
     *
     * @param documentApi Document API.
     */
    constructor(documentApi) {
        this.documentApi = documentApi;
        this.handleTabCreate = this.handleTabCreate.bind(this);
        this.handleTabUpdate = this.handleTabUpdate.bind(this);
        this.handleTabActivate = this.handleTabActivate.bind(this);
        this.handleTabDelete = this.handleTabDelete.bind(this);
        this.handleTabReplace = this.handleTabReplace.bind(this);
        this.handleFrameRequest = this.handleFrameRequest.bind(this);
        this.handleFrameCosmeticResult = this.handleFrameCosmeticResult.bind(this);
        this.handleFrameMatchingResult = this.handleFrameMatchingResult.bind(this);
        this.getTabContext = this.getTabContext.bind(this);
        this.getTabFrameRule = this.getTabFrameRule.bind(this);
        this.getTabFrame = this.getTabFrame.bind(this);
        this.getTabMainFrame = this.getTabMainFrame.bind(this);
        this.onWindowFocusChanged = this.onWindowFocusChanged.bind(this);
    }
    /**
     * Initializes tabs API and starts listening for tab & window events.
     */
    async start() {
        browser_polyfill_default().tabs.onCreated.addListener(this.handleTabCreate);
        browser_polyfill_default().tabs.onRemoved.addListener(this.handleTabDelete);
        browser_polyfill_default().tabs.onUpdated.addListener(this.handleTabUpdate);
        browser_polyfill_default().tabs.onActivated.addListener(this.handleTabActivate);
        browser_polyfill_default().tabs.onReplaced.addListener(this.handleTabReplace);
        // Firefox for android doesn't support windows API
        // https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/windows#browser_compatibility
        if ((browser_polyfill_default()).windows) {
            browser_polyfill_default().windows.onFocusChanged.addListener(this.onWindowFocusChanged);
        }
    }
    /**
     * Stops listening for tab & window events and clears tabs context.
     */
    stop() {
        browser_polyfill_default().tabs.onCreated.removeListener(this.handleTabCreate);
        browser_polyfill_default().tabs.onRemoved.removeListener(this.handleTabDelete);
        browser_polyfill_default().tabs.onUpdated.removeListener(this.handleTabUpdate);
        browser_polyfill_default().tabs.onActivated.removeListener(this.handleTabActivate);
        browser_polyfill_default().tabs.onReplaced.removeListener(this.handleTabReplace);
        // Firefox for android doesn't support windows API
        if ((browser_polyfill_default()).windows) {
            browser_polyfill_default().windows.onFocusChanged.removeListener(this.onWindowFocusChanged);
        }
        this.context.clear();
    }
    /**
     * Retrieves frame rule for the tab context.
     *
     * @param tabId Tab ID.
     * @returns Frame rule or null if not found.
     */
    getTabFrameRule(tabId) {
        const tabContext = this.context.get(tabId);
        if (!tabContext) {
            return null;
        }
        return tabContext.mainFrameRule;
    }
    /**
     * Retrieves frame data for the frame in the tab context.
     *
     * @param tabId Tab ID.
     * @param frameId Frame ID.
     * @returns Frame data or null if not found.
     */
    getTabFrame(tabId, frameId) {
        const tabContext = this.context.get(tabId);
        if (!tabContext) {
            return null;
        }
        const frame = tabContext.frames.get(frameId);
        if (!frame) {
            return null;
        }
        return frame;
    }
    /**
     * Retrieves main frame data for the tab context.
     *
     * @param tabId Tab ID.
     * @returns Frame data or null if not found.
     */
    getTabMainFrame(tabId) {
        return this.getTabFrame(tabId, MAIN_FRAME_ID);
    }
    /**
     * Records request context to the tab context.
     *
     * @param requestContext Tab's frame's request context.
     */
    handleFrameRequest(requestContext) {
        const { tabId } = requestContext;
        const tabContext = this.context.get(tabId);
        if (!tabContext) {
            return;
        }
        tabContext.handleFrameRequest(requestContext);
    }
    /**
     * Records frame cosmetic result to the tab context.
     *
     * @param tabId Tab id.
     * @param frameId Frame id.
     * @param cosmeticResult Frame {@link CosmeticResult}.
     */
    handleFrameCosmeticResult(tabId, frameId, cosmeticResult) {
        const tabContext = this.context.get(tabId);
        if (!tabContext) {
            return;
        }
        tabContext.handleFrameCosmeticResult(frameId, cosmeticResult);
    }
    /**
     * Records frame matching result to the tab context.
     *
     * @param tabId Tab id.
     * @param frameId Frame id.
     * @param matchingResult Frame {@link MatchingResult}.
     */
    handleFrameMatchingResult(tabId, frameId, matchingResult) {
        const tabContext = this.context.get(tabId);
        if (!tabContext) {
            return;
        }
        tabContext.handleFrameMatchingResult(frameId, matchingResult);
    }
    /**
     * Retrieves tab context by tab ID.
     *
     * @param tabId Tab ID.
     * @returns Tab context or undefined if not found.
     */
    getTabContext(tabId) {
        return this.context.get(tabId);
    }
    /**
     * Sets a current timestamp as `assistantInitTimestamp` of the tab context.
     *
     * Needed to determine later if a newly created frame is an assistant frame.
     *
     * @param tabId Tab id.
     */
    setAssistantInitTimestamp(tabId) {
        const tabContext = this.context.get(tabId);
        if (!tabContext) {
            return;
        }
        tabContext.assistantInitTimestamp = Date.now();
    }
    /**
     * Resets tab context's `assistantInitTimestamp` to null.
     *
     * @param tabId Tab id.
     */
    resetAssistantInitTimestamp(tabId) {
        const tabContext = this.context.get(tabId);
        if (!tabContext) {
            return;
        }
        tabContext.assistantInitTimestamp = null;
    }
    /**
     * Checks whether the tab with the specified ID is open in incognito mode
     * or not.
     *
     * @param tabId Tab ID.
     * @returns True if the tab is open in incognito mode, and false
     * if otherwise.
     */
    isIncognitoTab(tabId) {
        const tabContext = this.getTabContext(tabId);
        if (!tabContext) {
            return false;
        }
        return tabContext.info.incognito;
    }
    /**
     * Increments tab context blocked request count.
     *
     * @param tabId Tab ID.
     * @param referrerUrl Request initiator url.
     */
    incrementTabBlockedRequestCount(tabId, referrerUrl) {
        const tabContext = this.context.get(tabId);
        if (!tabContext) {
            return;
        }
        const tabUrl = tabContext.info?.url;
        /**
         * Only increment count for requests that are initiated from the same domain as the tab.
         *
         * This prevents count 'leaks' when moving between main frames due to async nature of
         * {@link browser.webRequest.onBeforeRequest} and {@link browser.tabs.onUpdated} events.
         */
        if (!tabUrl || !referrerUrl || getDomain(tabUrl) !== getDomain(referrerUrl)) {
            return;
        }
        tabContext.incrementBlockedRequestCount();
    }
    /**
     * Updates tab's main frame rule.
     *
     * @param tabId Tab ID.
     */
    updateTabMainFrameRule(tabId) {
        const tabContext = this.context.get(tabId);
        if (!tabContext?.info.url || !isHttpRequest(tabContext.info.url)) {
            return;
        }
        tabContext.mainFrameRule = this.documentApi.matchFrame(tabContext.info.url);
    }
    /**
     * Updates tab context data after filter engine load.
     */
    async updateCurrentTabsMainFrameRules() {
        const currentTabs = await browser_polyfill_default().tabs.query({});
        if (!Array.isArray(currentTabs)) {
            return;
        }
        for (const tab of currentTabs) {
            if (typeof tab.id === 'number') {
                this.updateTabMainFrameRule(tab.id);
            }
        }
    }
    /**
     * Checks if tab is a new tab.
     *
     * @param tabId Tab ID.
     * @returns True if tab is a new tab.
     */
    // TODO: Improve popup detection
    isNewPopupTab(tabId) {
        const tab = this.context.get(tabId);
        if (!tab) {
            return false;
        }
        const createdAt = tab.createdAtMs;
        const tabAgeMs = Date.now() - createdAt;
        return tabAgeMs < TabsApi.POPUP_TAB_TIMEOUT_MS;
    }
    /**
     * Creates a new tab context.
     *
     * @param tab Tab info.
     * @param tab.id Tab id.
     *
     * @returns Created tab context, or null if tab is not browser tab.
     */
    handleTabCreate(tab) {
        if (!TabContext.isBrowserTab(tab)) {
            return null;
        }
        const tabContext = TabContext.createNewTabContext(tab, this.documentApi);
        this.context.set(tab.id, tabContext);
        this.onCreate.dispatch(tabContext);
        return tabContext;
    }
    /**
     * Removes tab context by tab ID.
     *
     * @param tabId Tab ID.
     */
    handleTabDelete(tabId) {
        const tabContext = this.context.get(tabId);
        if (!tabContext) {
            return;
        }
        this.context.delete(tabId);
        this.onDelete.dispatch(tabContext);
    }
    /**
     * Uses {@link browser.webNavigation.onBeforeNavigate} event data
     * to update tab context data in conjunction with {@link handleTabUpdate}.
     *
     * Note: it is being specifically called at onBeforeNavigate
     * to handle initial tab update before {@link browser.tab.onUpdate} and {@link handleTabUpdate}.
     *
     * @param tabId Tab ID.
     * @param url Url.
     */
    handleTabNavigation(tabId, url) {
        const tabContext = this.context.get(tabId);
        if (!tabContext) {
            return;
        }
        if (!isHttpRequest(url)) {
            return;
        }
        tabContext.updateMainFrameData(tabId, url);
    }
    /**
     * Updates tab context data on tab update.
     * Works in conjunction with {@link handleTabNavigation}.
     *
     * If the tab context is not found, creates a new tab context.
     *
     * @param tabId Tab ID.
     * @param changeInfo Tab change info.
     * @param tabInfo Tab info.
     */
    handleTabUpdate(tabId, changeInfo, tabInfo) {
        if (!TabContext.isBrowserTab(tabInfo)) {
            return;
        }
        if (changeInfo.url && !isHttpRequest(changeInfo.url)) {
            return;
        }
        // TODO: we can ignore some events (favicon url update etc.)
        const tabContext = this.context.get(tabId);
        if (!tabContext) {
            return;
        }
        tabContext.updateTabInfo(changeInfo, tabInfo);
        this.onUpdate.dispatch(tabContext);
    }
    /**
     * Dispatches tab on activated event.
     *
     * @param info Tab activated info.
     * @param info.tabId Tab ID.
     */
    handleTabActivate({ tabId }) {
        const tabContext = this.context.get(tabId);
        if (!tabContext) {
            return;
        }
        this.onActivate.dispatch(tabContext);
    }
    /**
     * The browser tab may be replaced by another when the discarded tab wakes up.
     * We handle this case on {@link browser.tabs.onReplaced} event.
     * It fires before the tab details are updated,
     * so we just move the existing tab context to the new key.
     *
     * @param addedTabId - Id of the new tab context moved to.
     * @param removedTabId - Id of removed tab.
     */
    handleTabReplace(addedTabId, removedTabId) {
        const tabContext = this.context.get(removedTabId);
        if (!tabContext) {
            return;
        }
        this.context.delete(removedTabId);
        this.context.set(addedTabId, tabContext);
        this.onReplace.dispatch(tabContext);
    }
    /**
     * Called when focus state of window changed.
     *
     * @param windowId Window ID.
     */
    async onWindowFocusChanged(windowId) {
        // If all browser windows have lost focus.
        if (windowId === (browser_polyfill_default()).windows.WINDOW_ID_NONE) {
            return;
        }
        const [activeTab] = await browser_polyfill_default().tabs.query({
            active: true,
            windowId,
        });
        if (!activeTab || !activeTab.id) {
            return;
        }
        const tabContext = this.context.get(activeTab.id);
        if (!tabContext) {
            return;
        }
        this.onActivate.dispatch(tabContext);
    }
    /**
     * Injects script to the frame by tab id and frame id.
     *
     * @param code Script to be injected.
     * @param tabId Tab ID.
     * @param frameId Frame ID.
     */
    static async injectScript(code, tabId, frameId) {
        const injectDetails = {
            code,
            frameId,
            runAt: 'document_start',
            matchAboutBlank: true,
        };
        await browser_polyfill_default().tabs.executeScript(tabId, injectDetails);
    }
    /**
     * Injects css styles to the frame by tab id and frame id.
     *
     * @param code CSS styles to be injected.
     * @param tabId Tab ID.
     * @param frameId Frame ID.
     */
    static async injectCss(code, tabId, frameId) {
        const injectDetails = {
            code,
            frameId,
            runAt: 'document_start',
            matchAboutBlank: true,
            cssOrigin: 'user',
        };
        await browser_polyfill_default().tabs.insertCSS(tabId, injectDetails);
    }
}

/**
 * Implementation of the request context storage.
 */
class RequestContextStorage extends Map {
    /**
     * The request storage cleanup timeout.
     */
    static CLEANUP_TIMEOUT_MS = 60_000; // 1 min
    /**
     * The request context data lifetime.
     * It is based on the default browser 5 minutes request idle timeout + 1 second.
     *
     * @see https://source.chromium.org/chromium/chromium/src/+/main:net/socket/client_socket_pool.cc;l=41
     */
    static REQUEST_CONTEXT_LIFETIME_MS = 301_000;
    cleanupTimerId;
    /** @inheritdoc */
    constructor() {
        super();
        this.scheduleCleanup = this.scheduleCleanup.bind(this);
    }
    /**
     * Create new request context.
     *
     * @param requestId Request id.
     * @param data Request context with a omitted eventId field. It is automatically generated.
     * @returns Request context storage instance.
     */
    create(requestId, data) {
        const requestContext = {
            eventId: index_browser_nanoid(),
            ...data,
        };
        super.set(requestId, requestContext);
        return requestContext;
    }
    /**
     * Update request context fields. Can be done partially.
     *
     * @param requestId Request id.
     * @param data Partial request context.
     * @returns Updated request context.
     */
    update(requestId, data) {
        const requestContext = super.get(requestId);
        if (requestContext) {
            Object.assign(requestContext, data);
            return requestContext;
        }
        if (!data.timestamp) {
            // Incomplete event. Adding timestamp so that the clean up logic could work for it.
            data.timestamp = Date.now();
        }
        // TODO: Throws error if request context not found after RequestEvents refactoring.
        logger.error(`Request context not found for requestId: ${requestId}`);
        super.set(requestId, data);
        return undefined;
    }
    /**
     * Some requests may not trigger the onCompleted event and therefore will not be removed from the store.
     * This can occur, for example, with program redirects in the {@link ResourcesService}.
     * To solve this issue, we clean up the store by checking the records timestamps every
     * {@link CLEANUP_TIMEOUT_MS} milliseconds and deleting the expired records.
     */
    scheduleCleanup() {
        // If cleanup has already scheduled, clear previous timer.
        this.clearCleanupTimer();
        this.cleanupTimerId = window.setTimeout(() => {
            const now = Date.now();
            super.forEach(({ timestamp }, key) => {
                if (now > timestamp + RequestContextStorage.REQUEST_CONTEXT_LIFETIME_MS) {
                    super.delete(key);
                }
            });
            this.scheduleCleanup();
        }, RequestContextStorage.CLEANUP_TIMEOUT_MS);
    }
    /**
     * Clears cleanup timer, if it exists.
     */
    clearCleanupTimer() {
        if (this.cleanupTimerId) {
            window.clearTimeout(this.cleanupTimerId);
            this.cleanupTimerId = undefined;
        }
    }
}
// TODO: do not create global instance of storage.
const requestContextStorage = new RequestContextStorage();
requestContextStorage.scheduleCleanup();

const debug = (
  typeof process === 'object' &&
  process.env &&
  process.env.NODE_DEBUG &&
  /\bsemver\b/i.test(process.env.NODE_DEBUG)
) ? (...args) => console.error('SEMVER', ...args)
  : () => {};
var debug_1 = debug;

const SEMVER_SPEC_VERSION = '2.0.0';
const MAX_LENGTH = 256;
const MAX_SAFE_INTEGER = Number.MAX_SAFE_INTEGER ||
 9007199254740991;
const MAX_SAFE_COMPONENT_LENGTH = 16;
const MAX_SAFE_BUILD_LENGTH = MAX_LENGTH - 6;
const RELEASE_TYPES = [
  'major',
  'premajor',
  'minor',
  'preminor',
  'patch',
  'prepatch',
  'prerelease',
];
var constants = {
  MAX_LENGTH,
  MAX_SAFE_COMPONENT_LENGTH,
  MAX_SAFE_BUILD_LENGTH,
  MAX_SAFE_INTEGER,
  RELEASE_TYPES,
  SEMVER_SPEC_VERSION,
  FLAG_INCLUDE_PRERELEASE: 0b001,
  FLAG_LOOSE: 0b010,
};

var re = {exports: {}};

(function (module, exports) {
	const {
	  MAX_SAFE_COMPONENT_LENGTH,
	  MAX_SAFE_BUILD_LENGTH,
	  MAX_LENGTH,
	} = constants;
	const debug = debug_1;
	exports = module.exports = {};
	const re = exports.re = [];
	const safeRe = exports.safeRe = [];
	const src = exports.src = [];
	const t = exports.t = {};
	let R = 0;
	const LETTERDASHNUMBER = '[a-zA-Z0-9-]';
	const safeRegexReplacements = [
	  ['\\s', 1],
	  ['\\d', MAX_LENGTH],
	  [LETTERDASHNUMBER, MAX_SAFE_BUILD_LENGTH],
	];
	const makeSafeRegex = (value) => {
	  for (const [token, max] of safeRegexReplacements) {
	    value = value
	      .split(`${token}*`).join(`${token}{0,${max}}`)
	      .split(`${token}+`).join(`${token}{1,${max}}`);
	  }
	  return value
	};
	const createToken = (name, value, isGlobal) => {
	  const safe = makeSafeRegex(value);
	  const 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);
	};
	createToken('NUMERICIDENTIFIER', '0|[1-9]\\d*');
	createToken('NUMERICIDENTIFIERLOOSE', '\\d+');
	createToken('NONNUMERICIDENTIFIER', `\\d*[a-zA-Z-]${LETTERDASHNUMBER}*`);
	createToken('MAINVERSION', `(${src[t.NUMERICIDENTIFIER]})\\.` +
	                   `(${src[t.NUMERICIDENTIFIER]})\\.` +
	                   `(${src[t.NUMERICIDENTIFIER]})`);
	createToken('MAINVERSIONLOOSE', `(${src[t.NUMERICIDENTIFIERLOOSE]})\\.` +
	                        `(${src[t.NUMERICIDENTIFIERLOOSE]})\\.` +
	                        `(${src[t.NUMERICIDENTIFIERLOOSE]})`);
	createToken('PRERELEASEIDENTIFIER', `(?:${src[t.NUMERICIDENTIFIER]
	}|${src[t.NONNUMERICIDENTIFIER]})`);
	createToken('PRERELEASEIDENTIFIERLOOSE', `(?:${src[t.NUMERICIDENTIFIERLOOSE]
	}|${src[t.NONNUMERICIDENTIFIER]})`);
	createToken('PRERELEASE', `(?:-(${src[t.PRERELEASEIDENTIFIER]
	}(?:\\.${src[t.PRERELEASEIDENTIFIER]})*))`);
	createToken('PRERELEASELOOSE', `(?:-?(${src[t.PRERELEASEIDENTIFIERLOOSE]
	}(?:\\.${src[t.PRERELEASEIDENTIFIERLOOSE]})*))`);
	createToken('BUILDIDENTIFIER', `${LETTERDASHNUMBER}+`);
	createToken('BUILD', `(?:\\+(${src[t.BUILDIDENTIFIER]
	}(?:\\.${src[t.BUILDIDENTIFIER]})*))`);
	createToken('FULLPLAIN', `v?${src[t.MAINVERSION]
	}${src[t.PRERELEASE]}?${
	  src[t.BUILD]}?`);
	createToken('FULL', `^${src[t.FULLPLAIN]}$`);
	createToken('LOOSEPLAIN', `[v=\\s]*${src[t.MAINVERSIONLOOSE]
	}${src[t.PRERELEASELOOSE]}?${
	  src[t.BUILD]}?`);
	createToken('LOOSE', `^${src[t.LOOSEPLAIN]}$`);
	createToken('GTLT', '((?:<|>)?=?)');
	createToken('XRANGEIDENTIFIERLOOSE', `${src[t.NUMERICIDENTIFIERLOOSE]}|x|X|\\*`);
	createToken('XRANGEIDENTIFIER', `${src[t.NUMERICIDENTIFIER]}|x|X|\\*`);
	createToken('XRANGEPLAIN', `[v=\\s]*(${src[t.XRANGEIDENTIFIER]})` +
	                   `(?:\\.(${src[t.XRANGEIDENTIFIER]})` +
	                   `(?:\\.(${src[t.XRANGEIDENTIFIER]})` +
	                   `(?:${src[t.PRERELEASE]})?${
	                     src[t.BUILD]}?` +
	                   `)?)?`);
	createToken('XRANGEPLAINLOOSE', `[v=\\s]*(${src[t.XRANGEIDENTIFIERLOOSE]})` +
	                        `(?:\\.(${src[t.XRANGEIDENTIFIERLOOSE]})` +
	                        `(?:\\.(${src[t.XRANGEIDENTIFIERLOOSE]})` +
	                        `(?:${src[t.PRERELEASELOOSE]})?${
	                          src[t.BUILD]}?` +
	                        `)?)?`);
	createToken('XRANGE', `^${src[t.GTLT]}\\s*${src[t.XRANGEPLAIN]}$`);
	createToken('XRANGELOOSE', `^${src[t.GTLT]}\\s*${src[t.XRANGEPLAINLOOSE]}$`);
	createToken('COERCEPLAIN', `${'(^|[^\\d])' +
	              '(\\d{1,'}${MAX_SAFE_COMPONENT_LENGTH}})` +
	              `(?:\\.(\\d{1,${MAX_SAFE_COMPONENT_LENGTH}}))?` +
	              `(?:\\.(\\d{1,${MAX_SAFE_COMPONENT_LENGTH}}))?`);
	createToken('COERCE', `${src[t.COERCEPLAIN]}(?:$|[^\\d])`);
	createToken('COERCEFULL', src[t.COERCEPLAIN] +
	              `(?:${src[t.PRERELEASE]})?` +
	              `(?:${src[t.BUILD]})?` +
	              `(?:$|[^\\d])`);
	createToken('COERCERTL', src[t.COERCE], true);
	createToken('COERCERTLFULL', src[t.COERCEFULL], true);
	createToken('LONETILDE', '(?:~>?)');
	createToken('TILDETRIM', `(\\s*)${src[t.LONETILDE]}\\s+`, true);
	exports.tildeTrimReplace = '$1~';
	createToken('TILDE', `^${src[t.LONETILDE]}${src[t.XRANGEPLAIN]}$`);
	createToken('TILDELOOSE', `^${src[t.LONETILDE]}${src[t.XRANGEPLAINLOOSE]}$`);
	createToken('LONECARET', '(?:\\^)');
	createToken('CARETTRIM', `(\\s*)${src[t.LONECARET]}\\s+`, true);
	exports.caretTrimReplace = '$1^';
	createToken('CARET', `^${src[t.LONECARET]}${src[t.XRANGEPLAIN]}$`);
	createToken('CARETLOOSE', `^${src[t.LONECARET]}${src[t.XRANGEPLAINLOOSE]}$`);
	createToken('COMPARATORLOOSE', `^${src[t.GTLT]}\\s*(${src[t.LOOSEPLAIN]})$|^$`);
	createToken('COMPARATOR', `^${src[t.GTLT]}\\s*(${src[t.FULLPLAIN]})$|^$`);
	createToken('COMPARATORTRIM', `(\\s*)${src[t.GTLT]
	}\\s*(${src[t.LOOSEPLAIN]}|${src[t.XRANGEPLAIN]})`, true);
	exports.comparatorTrimReplace = '$1$2$3';
	createToken('HYPHENRANGE', `^\\s*(${src[t.XRANGEPLAIN]})` +
	                   `\\s+-\\s+` +
	                   `(${src[t.XRANGEPLAIN]})` +
	                   `\\s*$`);
	createToken('HYPHENRANGELOOSE', `^\\s*(${src[t.XRANGEPLAINLOOSE]})` +
	                        `\\s+-\\s+` +
	                        `(${src[t.XRANGEPLAINLOOSE]})` +
	                        `\\s*$`);
	createToken('STAR', '(<|>)?=?\\s*\\*');
	createToken('GTE0', '^\\s*>=\\s*0\\.0\\.0\\s*$');
	createToken('GTE0PRE', '^\\s*>=\\s*0\\.0\\.0-0\\s*$'); 
} (re, re.exports));

var sprintf = {};

(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) {
	        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];
	                if (ph.keys) {
	                    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) {
	                    arg = argv[ph.param_no];
	                }
	                else {
	                    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
	    }
	    {
	        exports['sprintf'] = sprintf;
	        exports['vsprintf'] = vsprintf;
	    }
	    if (typeof window !== 'undefined') {
	        window['sprintf'] = sprintf;
	        window['vsprintf'] = vsprintf;
	    }
	}(); 
} (sprintf));

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 = {}));
const UNKNOWN_TOKEN_NAME = 'unknown';
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',
});
const getBaseTokenName = (type) => {
    return TOKEN_NAMES[type] ?? UNKNOWN_TOKEN_NAME;
};
const getFormattedTokenName = (type) => {
    return `<${getBaseTokenName(type)}-token>`;
};

const word = '[a-fA-F\\d:]';
const b = options => options && options.includeBoundaries ?
	`(?:(?<=\\s|^)(?=${word})|(?<=${word})(?=\\s|$))` :
	'';
const 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}';
const v6seg = '[a-fA-F\\d]{1,4}';
const v6 = `
(?:
(?:${v6seg}:){7}(?:${v6seg}|:)|                                    // 1:2:3:4:5:6:7::  1:2:3:4:5:6:7:8
(?:${v6seg}:){6}(?:${v4}|:${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
(?:${v6seg}:){5}(?::${v4}|(?::${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
(?:${v6seg}:){4}(?:(?::${v6seg}){0,1}:${v4}|(?::${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
(?:${v6seg}:){3}(?:(?::${v6seg}){0,2}:${v4}|(?::${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
(?:${v6seg}:){2}(?:(?::${v6seg}){0,3}:${v4}|(?::${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
(?:${v6seg}:){1}(?:(?::${v6seg}){0,4}:${v4}|(?::${v6seg}){1,6}|:)| // 1::              1::3:4:5:6:7:8   1::8            1::3:4:5:6:7:1.2.3.4
(?::(?:(?::${v6seg}){0,5}:${v4}|(?::${v6seg}){1,7}|:))             // ::2:3:4:5:6:7:8  ::2:3:4:5:6:7:8  ::8             ::1.2.3.4
)(?:%[0-9a-zA-Z]{1,})?                                             // %eth0            %1
`.replace(/\s*\/\/.*$/gm, '').replace(/\n/g, '').trim();
const v46Exact = new RegExp(`(?:^${v4}$)|(?:^${v6}$)`);
const v4exact = new RegExp(`^${v4}$`);
const v6exact = new RegExp(`^${v6}$`);
const ip = options => options && options.exact ?
	v46Exact :
	new RegExp(`(?:${b(options)}${v4}${b(options)})|(?:${b(options)}${v6}${b(options)})`, 'g');
ip.v4 = options => options && options.exact ? v4exact : new RegExp(`${b(options)}${v4}${b(options)}`, 'g');
ip.v6 = options => options && options.exact ? v6exact : new RegExp(`${b(options)}${v6}${b(options)}`, 'g');
var ipRegex$1 = ip;

const ipRegex = ipRegex$1;
const isIp = string => ipRegex({exact: true}).test(string);
isIp.v4 = string => ipRegex.v4({exact: true}).test(string);
isIp.v6 = string => ipRegex.v6({exact: true}).test(string);
isIp.version = string => isIp(string) ? (isIp.v4(string) ? 4 : 6) : undefined;

const REGEX_DATA = 'xregexp';
const features = {
    astral: false,
    namespacing: true
};
const fixed = {};
let regexCache = {};
let patternCache = {};
const tokens = [];
const defaultScope = 'default';
const classScope = 'class';
const nativeTokens = {
    '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]/,
    '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]/
};
const replacementToken = /\$(?:\{([^\}]+)\}|<([^>]+)>|(\d\d?|[\s\S]?))/g;
const correctExecNpcg = /()??/.exec('')[1] === undefined;
const hasFlagsProp = /x/.flags !== undefined;
function hasNativeFlag(flag) {
    let isSupported = true;
    try {
        new RegExp('', flag);
        if (flag === 'y') {
            const gy = (() => 'gy')();
            const incompleteY = '.a'.replace(new RegExp('a', gy), '.') === '..';
            if (incompleteY) {
                isSupported = false;
            }
        }
    } catch (exception) {
        isSupported = false;
    }
    return isSupported;
}
const hasNativeD = hasNativeFlag('d');
const hasNativeS = hasNativeFlag('s');
const hasNativeU = hasNativeFlag('u');
const hasNativeY = hasNativeFlag('y');
const registeredFlags = {
    d: hasNativeD,
    g: true,
    i: true,
    m: true,
    s: hasNativeS,
    u: hasNativeU,
    y: hasNativeY
};
const nonnativeFlags = hasNativeS ? /[^dgimsuy]+/g : /[^dgimuy]+/g;
function augment(regex, captureNames, xSource, xFlags, isInternalOnly) {
    regex[REGEX_DATA] = {
        captureNames
    };
    if (isInternalOnly) {
        return regex;
    }
    if (regex.__proto__) {
        regex.__proto__ = XRegExp.prototype;
    } else {
        for (const p in XRegExp.prototype) {
            regex[p] = XRegExp.prototype[p];
        }
    }
    regex[REGEX_DATA].source = xSource;
    regex[REGEX_DATA].flags = xFlags ? xFlags.split('').sort().join('') : xFlags;
    return regex;
}
function clipDuplicates(str) {
    return str.replace(/([\s\S])(?=[\s\S]*\1)/g, '');
}
function copyRegex(regex, options) {
    if (!XRegExp.isRegExp(regex)) {
        throw new TypeError('Type RegExp expected');
    }
    const xData = regex[REGEX_DATA] || {};
    let flags = getNativeFlags(regex);
    let flagsToAdd = '';
    let flagsToRemove = '';
    let xregexpSource = null;
    let xregexpFlags = null;
    options = options || {};
    if (options.removeG) {flagsToRemove += 'g';}
    if (options.removeY) {flagsToRemove += 'y';}
    if (flagsToRemove) {
        flags = flags.replace(new RegExp(`[${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;
        }
        if (xData.flags != null) {
            xregexpFlags = flagsToAdd ? clipDuplicates(xData.flags + flagsToAdd) : xData.flags;
        }
    }
    regex = augment(
        new RegExp(options.source || regex.source, flags),
        hasNamedCapture(regex) ? xData.captureNames.slice(0) : null,
        xregexpSource,
        xregexpFlags,
        options.isInternalOnly
    );
    return regex;
}
function dec(hex) {
    return parseInt(hex, 16);
}
function getContextualTokenSeparator(match, scope, flags) {
    const matchEndPos = match.index + match[0].length;
    const precedingChar = match.input[match.index - 1];
    const followingChar = match.input[matchEndPos];
    if (
        /^[()|]$/.test(precedingChar) ||
        /^[()|]$/.test(followingChar) ||
        match.index === 0 ||
        matchEndPos === match.input.length ||
        /\(\?(?:[:=!]|<[=!])$/.test(match.input.substring(match.index - 4, match.index)) ||
        isQuantifierNext(match.input, matchEndPos, flags)
    ) {
        return '';
    }
    return '(?:)';
}
function getNativeFlags(regex) {
    return hasFlagsProp ?
        regex.flags :
        /\/([a-z]*)$/i.exec(RegExp.prototype.toString.call(regex))[1];
}
function hasNamedCapture(regex) {
    return !!(regex[REGEX_DATA] && regex[REGEX_DATA].captureNames);
}
function hex(dec) {
    return parseInt(dec, 10).toString(16);
}
function isQuantifierNext(pattern, pos, flags) {
    const inlineCommentPattern = '\\(\\?#[^)]*\\)';
    const lineCommentPattern = '#[^#\\n]*';
    const quantifierPattern = '[?*+]|{\\d+(?:,\\d*)?}';
    const regex = flags.includes('x') ?
        new RegExp(`^(?:\\s|${lineCommentPattern}|${inlineCommentPattern})*(?:${quantifierPattern})`) :
        new RegExp(`^(?:${inlineCommentPattern})*(?:${quantifierPattern})`);
    return regex.test(pattern.slice(pos));
}
function isType(value, type) {
    return Object.prototype.toString.call(value) === `[object ${type}]`;
}
function nullThrows(value) {
    if (value == null) {
        throw new TypeError('Cannot convert null or undefined to object');
    }
    return value;
}
function pad4(str) {
    while (str.length < 4) {
        str = `0${str}`;
    }
    return str;
}
function prepareFlags(pattern, flags) {
    if (clipDuplicates(flags) !== flags) {
        throw new SyntaxError(`Invalid duplicate regex flag ${flags}`);
    }
    pattern = pattern.replace(/^\(\?([\w$]+)\)/, ($0, $1) => {
        if (/[dgy]/.test($1)) {
            throw new SyntaxError(`Cannot use flags dgy in mode modifier ${$0}`);
        }
        flags = clipDuplicates(flags + $1);
        return '';
    });
    for (const flag of flags) {
        if (!registeredFlags[flag]) {
            throw new SyntaxError(`Unknown regex flag ${flag}`);
        }
    }
    return {
        pattern,
        flags
    };
}
function prepareOptions(value) {
    const options = {};
    if (isType(value, 'String')) {
        XRegExp.forEach(value, /[^\s,]+/, (match) => {
            options[match] = true;
        });
        return options;
    }
    return value;
}
function registerFlag(flag) {
    if (!/^[\w$]$/.test(flag)) {
        throw new Error('Flag must be a single character A-Za-z0-9_$');
    }
    registeredFlags[flag] = true;
}
function runTokens(pattern, flags, pos, scope, context) {
    let i = tokens.length;
    const leadChar = pattern[pos];
    let result = null;
    let match;
    let t;
    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
            };
            break;
        }
    }
    return result;
}
function setAstral(on) {
    features.astral = on;
}
function setNamespacing(on) {
    features.namespacing = on;
}
function XRegExp(pattern, flags) {
    if (XRegExp.isRegExp(pattern)) {
        if (flags !== undefined) {
            throw new TypeError('Cannot supply flags when copying a RegExp');
        }
        return copyRegex(pattern);
    }
    pattern = pattern === undefined ? '' : String(pattern);
    flags = flags === undefined ? '' : String(flags);
    if (XRegExp.isInstalled('astral') && !flags.includes('A')) {
        flags += 'A';
    }
    if (!patternCache[pattern]) {
        patternCache[pattern] = {};
    }
    if (!patternCache[pattern][flags]) {
        const context = {
            hasNamedCapture: false,
            captureNames: []
        };
        let scope = defaultScope;
        let output = '';
        let pos = 0;
        let result;
        const applied = prepareFlags(pattern, flags);
        let appliedPattern = applied.pattern;
        const appliedFlags = applied.flags;
        while (pos < appliedPattern.length) {
            do {
                result = runTokens(appliedPattern, appliedFlags, pos, scope, context);
                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 {
                const [token] = XRegExp.exec(appliedPattern, nativeTokens[scope], pos, 'sticky');
                output += token;
                pos += token.length;
                if (token === '[' && scope === defaultScope) {
                    scope = classScope;
                } else if (token === ']' && scope === classScope) {
                    scope = defaultScope;
                }
            }
        }
        patternCache[pattern][flags] = {
            pattern: output.replace(/(?:\(\?:\))+/g, '(?:)'),
            flags: appliedFlags.replace(nonnativeFlags, ''),
            captures: context.hasNamedCapture ? context.captureNames : null
        };
    }
    const generated = patternCache[pattern][flags];
    return augment(
        new RegExp(generated.pattern, generated.flags),
        generated.captures,
        pattern,
        flags
    );
}
XRegExp.prototype = new RegExp();
XRegExp.version = '5.1.1';
XRegExp._clipDuplicates = clipDuplicates;
XRegExp._hasNativeFlag = hasNativeFlag;
XRegExp._dec = dec;
XRegExp._hex = hex;
XRegExp._pad4 = pad4;
XRegExp.addToken = (regex, handler, options) => {
    options = options || {};
    let {optionalFlags} = options;
    if (options.flag) {
        registerFlag(options.flag);
    }
    if (optionalFlags) {
        optionalFlags = optionalFlags.split('');
        for (const flag of optionalFlags) {
            registerFlag(flag);
        }
    }
    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
    });
    XRegExp.cache.flush('patterns');
};
XRegExp.cache = (pattern, flags) => {
    if (!regexCache[pattern]) {
        regexCache[pattern] = {};
    }
    return regexCache[pattern][flags] || (
        regexCache[pattern][flags] = XRegExp(pattern, flags)
    );
};
XRegExp.cache.flush = (cacheName) => {
    if (cacheName === 'patterns') {
        patternCache = {};
    } else {
        regexCache = {};
    }
};
XRegExp.escape = (str) => String(nullThrows(str)).
    replace(/[\\\[\]{}()*+?.^$|]/g, '\\$&').
    replace(/[\s#\-,]/g, (match) => `\\u${pad4(hex(match.charCodeAt(0)))}`);
XRegExp.exec = (str, regex, pos, sticky) => {
    let cacheKey = 'g';
    let addY = false;
    let fakeY = false;
    let match;
    addY = hasNativeY && !!(sticky || (regex.sticky && sticky !== false));
    if (addY) {
        cacheKey += 'y';
    } else if (sticky) {
        fakeY = true;
        cacheKey += 'FakeY';
    }
    regex[REGEX_DATA] = regex[REGEX_DATA] || {};
    const r2 = regex[REGEX_DATA][cacheKey] || (
        regex[REGEX_DATA][cacheKey] = copyRegex(regex, {
            addG: true,
            addY,
            source: fakeY ? `${regex.source}|()` : undefined,
            removeY: sticky === false,
            isInternalOnly: true
        })
    );
    pos = pos || 0;
    r2.lastIndex = pos;
    match = fixed.exec.call(r2, str);
    if (fakeY && match && match.pop() === '') {
        match = null;
    }
    if (regex.global) {
        regex.lastIndex = match ? r2.lastIndex : 0;
    }
    return match;
};
XRegExp.forEach = (str, regex, callback) => {
    let pos = 0;
    let i = -1;
    let match;
    while ((match = XRegExp.exec(str, regex, pos))) {
        callback(match, ++i, str, regex);
        pos = match.index + (match[0].length || 1);
    }
};
XRegExp.globalize = (regex) => copyRegex(regex, {addG: true});
XRegExp.install = (options) => {
    options = prepareOptions(options);
    if (!features.astral && options.astral) {
        setAstral(true);
    }
    if (!features.namespacing && options.namespacing) {
        setNamespacing(true);
    }
};
XRegExp.isInstalled = (feature) => !!(features[feature]);
XRegExp.isRegExp = (value) => Object.prototype.toString.call(value) === '[object RegExp]';
XRegExp.match = (str, regex, scope) => {
    const global = (regex.global && scope !== 'one') || scope === 'all';
    const cacheKey = ((global ? 'g' : '') + (regex.sticky ? 'y' : '')) || 'noGY';
    regex[REGEX_DATA] = regex[REGEX_DATA] || {};
    const r2 = regex[REGEX_DATA][cacheKey] || (
        regex[REGEX_DATA][cacheKey] = copyRegex(regex, {
            addG: !!global,
            removeG: scope === 'one',
            isInternalOnly: true
        })
    );
    const result = String(nullThrows(str)).match(r2);
    if (regex.global) {
        regex.lastIndex = (
            (scope === 'one' && result) ?
                (result.index + result[0].length) : 0
        );
    }
    return global ? (result || []) : (result && result[0]);
};
XRegExp.matchChain = (str, chain) => (function recurseChain(values, level) {
    const item = chain[level].regex ? chain[level] : {regex: chain[level]};
    const matches = [];
    function addMatch(match) {
        if (item.backref) {
            const ERR_UNDEFINED_GROUP = `Backreference to undefined group: ${item.backref}`;
            const isNamedBackref = isNaN(item.backref);
            if (isNamedBackref && XRegExp.isInstalled('namespacing')) {
                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);
            }
            const backrefValue = isNamedBackref && XRegExp.isInstalled('namespacing') ?
                match.groups[item.backref] :
                match[item.backref];
            matches.push(backrefValue || '');
        } else {
            matches.push(match[0]);
        }
    }
    for (const value of values) {
        XRegExp.forEach(value, item.regex, addMatch);
    }
    return ((level === chain.length - 1) || !matches.length) ?
        matches :
        recurseChain(matches, level + 1);
}([str], 0));
XRegExp.replace = (str, search, replacement, scope) => {
    const isRegex = XRegExp.isRegExp(search);
    const global = (search.global && scope !== 'one') || scope === 'all';
    const cacheKey = ((global ? 'g' : '') + (search.sticky ? 'y' : '')) || 'noGY';
    let s2 = search;
    if (isRegex) {
        search[REGEX_DATA] = search[REGEX_DATA] || {};
        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');
    }
    const result = fixed.replace.call(nullThrows(str), s2, replacement);
    if (isRegex && search.global) {
        search.lastIndex = 0;
    }
    return result;
};
XRegExp.replaceEach = (str, replacements) => {
    for (const r of replacements) {
        str = XRegExp.replace(str, r[0], r[1], r[2]);
    }
    return str;
};
XRegExp.split = (str, separator, limit) => fixed.split.call(nullThrows(str), separator, limit);
XRegExp.test = (str, regex, pos, sticky) => !!XRegExp.exec(str, regex, pos, sticky);
XRegExp.uninstall = (options) => {
    options = prepareOptions(options);
    if (features.astral && options.astral) {
        setAstral(false);
    }
    if (features.namespacing && options.namespacing) {
        setNamespacing(false);
    }
};
XRegExp.union = (patterns, flags, options) => {
    options = options || {};
    const conjunction = options.conjunction || 'or';
    let numCaptures = 0;
    let numPriorCaptures;
    let captureNames;
    function rewrite(match, paren, backref) {
        const name = captureNames[numCaptures - numPriorCaptures];
        if (paren) {
            ++numCaptures;
            if (name) {
                return `(?<${name}>`;
            }
        } else if (backref) {
            return `\\${+backref + numPriorCaptures}`;
        }
        return match;
    }
    if (!(isType(patterns, 'Array') && patterns.length)) {
        throw new TypeError('Must provide a nonempty array of patterns to merge');
    }
    const parts = /(\()(?!\?)|\\([1-9]\d*)|\\[\s\S]|\[(?:[^\\\]]|\\[\s\S])*\]/g;
    const output = [];
    for (const pattern of patterns) {
        if (XRegExp.isRegExp(pattern)) {
            numPriorCaptures = numCaptures;
            captureNames = (pattern[REGEX_DATA] && pattern[REGEX_DATA].captureNames) || [];
            output.push(XRegExp(pattern.source).source.replace(parts, rewrite));
        } else {
            output.push(XRegExp.escape(pattern));
        }
    }
    const separator = conjunction === 'none' ? '' : '|';
    return XRegExp(output.join(separator), flags);
};
fixed.exec = function(str) {
    const origLastIndex = this.lastIndex;
    const match = RegExp.prototype.exec.apply(this, arguments);
    if (match) {
        if (!correctExecNpcg && match.length > 1 && match.includes('')) {
            const r2 = copyRegex(this, {
                removeG: true,
                isInternalOnly: true
            });
            String(str).slice(match.index).replace(r2, (...args) => {
                const len = args.length;
                for (let i = 1; i < len - 2; ++i) {
                    if (args[i] === undefined) {
                        match[i] = undefined;
                    }
                }
            });
        }
        if (this[REGEX_DATA] && this[REGEX_DATA].captureNames) {
            let groupsObject = match;
            if (XRegExp.isInstalled('namespacing')) {
                match.groups = Object.create(null);
                groupsObject = match.groups;
            }
            for (let i = 1; i < match.length; ++i) {
                const name = this[REGEX_DATA].captureNames[i - 1];
                if (name) {
                    groupsObject[name] = match[i];
                }
            }
        } else if (!match.groups && XRegExp.isInstalled('namespacing')) {
            match.groups = undefined;
        }
        if (this.global && !match[0].length && (this.lastIndex > match.index)) {
            this.lastIndex = match.index;
        }
    }
    if (!this.global) {
        this.lastIndex = origLastIndex;
    }
    return match;
};
fixed.test = function(str) {
    return !!fixed.exec.call(this, str);
};
fixed.match = function(regex) {
    if (!XRegExp.isRegExp(regex)) {
        regex = new RegExp(regex);
    } else if (regex.global) {
        const result = String.prototype.match.apply(this, arguments);
        regex.lastIndex = 0;
        return result;
    }
    return fixed.exec.call(regex, nullThrows(this));
};
fixed.replace = function(search, replacement) {
    const isRegex = XRegExp.isRegExp(search);
    let origLastIndex;
    let captureNames;
    let result;
    if (isRegex) {
        if (search[REGEX_DATA]) {
            ({captureNames} = search[REGEX_DATA]);
        }
        origLastIndex = search.lastIndex;
    } else {
        search += '';
    }
    if (isType(replacement, 'Function')) {
        result = String(this).replace(search, (...args) => {
            if (captureNames) {
                let groupsObject;
                if (XRegExp.isInstalled('namespacing')) {
                    groupsObject = Object.create(null);
                    args.push(groupsObject);
                } else {
                    args[0] = new String(args[0]);
                    [groupsObject] = args;
                }
                for (let i = 0; i < captureNames.length; ++i) {
                    if (captureNames[i]) {
                        groupsObject[captureNames[i]] = args[i + 1];
                    }
                }
            }
            return replacement(...args);
        });
    } else {
        result = String(nullThrows(this)).replace(search, (...args) => {
            return String(replacement).replace(replacementToken, replacer);
            function replacer($0, bracketed, angled, dollarToken) {
                bracketed = bracketed || angled;
                const numNonCaptureArgs = isType(args[args.length - 1], 'Object') ? 4 : 3;
                const numCaptures = args.length - numNonCaptureArgs;
                if (bracketed) {
                    if (/^\d+$/.test(bracketed)) {
                        const n = +bracketed;
                        if (n <= numCaptures) {
                            return args[n] || '';
                        }
                    }
                    const n = captureNames ? captureNames.indexOf(bracketed) : -1;
                    if (n < 0) {
                        throw new SyntaxError(`Backreference to undefined group ${$0}`);
                    }
                    return args[n + 1] || '';
                }
                if (dollarToken === '' || dollarToken === ' ') {
                    throw new SyntaxError(`Invalid token ${$0}`);
                }
                if (dollarToken === '&' || +dollarToken === 0) {
                    return args[0];
                }
                if (dollarToken === '$') {
                    return '$';
                }
                if (dollarToken === '`') {
                    return args[args.length - 1].slice(0, args[args.length - 2]);
                }
                if (dollarToken === "'") {
                    return args[args.length - 1].slice(args[args.length - 2] + args[0].length);
                }
                dollarToken = +dollarToken;
                if (!isNaN(dollarToken)) {
                    if (dollarToken > numCaptures) {
                        throw new SyntaxError(`Backreference to undefined group ${$0}`);
                    }
                    return args[dollarToken] || '';
                }
                throw new SyntaxError(`Invalid token ${$0}`);
            }
        });
    }
    if (isRegex) {
        if (search.global) {
            search.lastIndex = 0;
        } else {
            search.lastIndex = origLastIndex;
        }
    }
    return result;
};
fixed.split = function(separator, limit) {
    if (!XRegExp.isRegExp(separator)) {
        return String.prototype.split.apply(this, arguments);
    }
    const str = String(this);
    const output = [];
    const origLastIndex = separator.lastIndex;
    let lastLastIndex = 0;
    let lastLength;
    limit = (limit === undefined ? -1 : limit) >>> 0;
    XRegExp.forEach(str, separator, (match) => {
        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;
};
XRegExp.addToken(
    /\\([ABCE-RTUVXYZaeg-mopqyz]|c(?![A-Za-z])|u(?![\dA-Fa-f]{4}|{[\dA-Fa-f]+})|x(?![\dA-Fa-f]{2}))/,
    (match, scope) => {
        if (match[1] === 'B' && scope === defaultScope) {
            return match[0];
        }
        throw new SyntaxError(`Invalid escape ${match[0]}`);
    },
    {
        scope: 'all',
        leadChar: '\\'
    }
);
XRegExp.addToken(
    /\\u{([\dA-Fa-f]+)}/,
    (match, scope, flags) => {
        const code = dec(match[1]);
        if (code > 0x10FFFF) {
            throw new SyntaxError(`Invalid Unicode code point ${match[0]}`);
        }
        if (code <= 0xFFFF) {
            return `\\u${pad4(hex(code))}`;
        }
        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: '\\'
    }
);
XRegExp.addToken(
    /\(\?#[^)]*\)/,
    getContextualTokenSeparator,
    {leadChar: '('}
);
XRegExp.addToken(
    /\s+|#[^\n]*\n?/,
    getContextualTokenSeparator,
    {flag: 'x'}
);
if (!hasNativeS) {
    XRegExp.addToken(
        /\./,
        () => '[\\s\\S]',
        {
            flag: 's',
            leadChar: '.'
        }
    );
}
XRegExp.addToken(
    /\\k<([^>]+)>/,
    function(match) {
        const index = isNaN(match[1]) ? (this.captureNames.indexOf(match[1]) + 1) : +match[1];
        const endIndex = match.index + match[0].length;
        if (!index || index > this.captureNames.length) {
            throw new SyntaxError(`Backreference to undefined group ${match[0]}`);
        }
        return `\\${index}${
            endIndex === match.input.length || isNaN(match.input[endIndex]) ?
                '' : '(?:)'
        }`;
    },
    {leadChar: '\\'}
);
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 ${match[0]}`);
        }
        return match[0];
    },
    {
        scope: 'all',
        leadChar: '\\'
    }
);
XRegExp.addToken(
    /\(\?P?<([\p{ID_Start}$_][\p{ID_Continue}$_\u200C\u200D]*)>/u,
    function(match) {
        if (!XRegExp.isInstalled('namespacing') && (match[1] === 'length' || match[1] === '__proto__')) {
            throw new SyntaxError(`Cannot use reserved word as capture name ${match[0]}`);
        }
        if (this.captureNames.includes(match[1])) {
            throw new SyntaxError(`Cannot use same name for multiple groups ${match[0]}`);
        }
        this.captureNames.push(match[1]);
        this.hasNamedCapture = true;
        return '(';
    },
    {leadChar: '('}
);
XRegExp.addToken(
    /\((?!\?)/,
    function(match, scope, flags) {
        if (flags.includes('n')) {
            return '(?:';
        }
        this.captureNames.push(null);
        return '(';
    },
    {
        optionalFlags: 'n',
        leadChar: '('
    }
);

var build = (XRegExp) => {
    const REGEX_DATA = 'xregexp';
    const subParts = /(\()(?!\?)|\\([1-9]\d*)|\\[\s\S]|\[(?:[^\\\]]|\\[\s\S])*\]/g;
    const parts = XRegExp.union([/\({{([\w$]+)}}\)|{{([\w$]+)}}/, subParts], 'g', {
        conjunction: 'or'
    });
    function deanchor(pattern) {
        const leadingAnchor = /^(?:\(\?:\))*\^/;
        const trailingAnchor = /\$(?:\(\?:\))*$/;
        if (
            leadingAnchor.test(pattern) &&
            trailingAnchor.test(pattern) &&
            trailingAnchor.test(pattern.replace(/\\[\s\S]/g, ''))
        ) {
            return pattern.replace(leadingAnchor, '').replace(trailingAnchor, '');
        }
        return pattern;
    }
    function asXRegExp(value, addFlagX) {
        const flags = addFlagX ? 'x' : '';
        return XRegExp.isRegExp(value) ?
            (value[REGEX_DATA] && value[REGEX_DATA].captureNames ?
                value :
                XRegExp(value.source, flags)
            ) :
            XRegExp(value, flags);
    }
    function interpolate(substitution) {
        return substitution instanceof RegExp ? substitution : XRegExp.escape(substitution);
    }
    function reduceToSubpatternsObject(subpatterns, interpolated, subpatternIndex) {
        subpatterns[`subpattern${subpatternIndex}`] = interpolated;
        return subpatterns;
    }
    function embedSubpatternAfter(raw, subpatternIndex, rawLiterals) {
        const hasSubpattern = subpatternIndex < rawLiterals.length - 1;
        return raw + (hasSubpattern ? `{{subpattern${subpatternIndex}}}` : '');
    }
    XRegExp.tag = (flags) => (literals, ...substitutions) => {
        const subpatterns = substitutions.map(interpolate).reduce(reduceToSubpatternsObject, {});
        const pattern = literals.raw.map(embedSubpatternAfter).join('');
        return XRegExp.build(pattern, subpatterns, flags);
    };
    XRegExp.build = (pattern, subs, flags) => {
        flags = flags || '';
        const addFlagX = flags.includes('x');
        const inlineFlags = /^\(\?([\w$]+)\)/.exec(pattern);
        if (inlineFlags) {
            flags = XRegExp._clipDuplicates(flags + inlineFlags[1]);
        }
        const data = {};
        for (const p in subs) {
            if (subs.hasOwnProperty(p)) {
                const sub = asXRegExp(subs[p], addFlagX);
                data[p] = {
                    pattern: deanchor(sub.source),
                    names: sub[REGEX_DATA].captureNames || []
                };
            }
        }
        const patternAsRegex = asXRegExp(pattern, addFlagX);
        let numCaps = 0;
        let numPriorCaps;
        let numOuterCaps = 0;
        const outerCapsMap = [0];
        const outerCapNames = patternAsRegex[REGEX_DATA].captureNames || [];
        const output = patternAsRegex.source.replace(parts, ($0, $1, $2, $3, $4) => {
            const subName = $1 || $2;
            let capName;
            let intro;
            let localCapIndex;
            if (subName) {
                if (!data.hasOwnProperty(subName)) {
                    throw new ReferenceError(`Undefined property ${$0}`);
                }
                if ($1) {
                    capName = outerCapNames[numOuterCaps];
                    outerCapsMap[++numOuterCaps] = ++numCaps;
                    intro = `(?<${capName || subName}>`;
                } else {
                    intro = '(?:';
                }
                numPriorCaps = numCaps;
                const rewrittenSubpattern = data[subName].pattern.replace(subParts, (match, paren, backref) => {
                    if (paren) {
                        capName = data[subName].names[numCaps - numPriorCaps];
                        ++numCaps;
                        if (capName) {
                            return `(?<${capName}>`;
                        }
                    } else if (backref) {
                        localCapIndex = +backref - 1;
                        return data[subName].names[localCapIndex] ?
                            `\\k<${data[subName].names[localCapIndex]}>` :
                            `\\${+backref + numPriorCaps}`;
                    }
                    return match;
                });
                return `${intro}${rewrittenSubpattern})`;
            }
            if ($3) {
                capName = outerCapNames[numOuterCaps];
                outerCapsMap[++numOuterCaps] = ++numCaps;
                if (capName) {
                    return `(?<${capName}>`;
                }
            } else if ($4) {
                localCapIndex = +$4 - 1;
                return outerCapNames[localCapIndex] ?
                    `\\k<${outerCapNames[localCapIndex]}>` :
                    `\\${outerCapsMap[+$4]}`;
            }
            return $0;
        });
        return XRegExp(output, flags);
    };
};

var matchRecursive = (XRegExp) => {
    function row(name, value, start, end) {
        return {
            name,
            value,
            start,
            end
        };
    }
    XRegExp.matchRecursive = (str, left, right, flags, options) => {
        flags = flags || '';
        options = options || {};
        const global = flags.includes('g');
        const sticky = flags.includes('y');
        const basicFlags = flags.replace(/y/g, '');
        left = XRegExp(left, basicFlags);
        right = XRegExp(right, basicFlags);
        let esc;
        let {escapeChar} = options;
        if (escapeChar) {
            if (escapeChar.length > 1) {
                throw new Error('Cannot use more than one escape character');
            }
            escapeChar = XRegExp.escape(escapeChar);
            esc = new RegExp(
                `(?:${escapeChar}[\\S\\s]|(?:(?!${
                    XRegExp.union([left, right], '', {conjunction: 'or'}).source
                })[^${escapeChar}])+)+`,
                flags.replace(XRegExp._hasNativeFlag('s') ? /[^imsu]/g : /[^imu]/g, '')
            );
        }
        let openTokens = 0;
        let delimStart = 0;
        let delimEnd = 0;
        let lastOuterEnd = 0;
        let outerStart;
        let innerStart;
        let leftMatch;
        let rightMatch;
        const vN = options.valueNames;
        const output = [];
        while (true) {
            if (escapeChar) {
                delimEnd += (XRegExp.exec(str, esc, delimEnd, 'sticky') || [''])[0].length;
            }
            leftMatch = XRegExp.exec(str, left, delimEnd);
            rightMatch = XRegExp.exec(str, right, delimEnd);
            if (leftMatch && rightMatch) {
                if (leftMatch.index <= rightMatch.index) {
                    rightMatch = null;
                } else {
                    leftMatch = null;
                }
            }
            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;
                    }
                }
            } else {
                const unbalanced = options.unbalanced || 'error';
                if (unbalanced === 'skip' || unbalanced === 'skip-lazy') {
                    if (rightMatch) {
                        rightMatch = null;
                    } else {
                        if (unbalanced === 'skip') {
                            const outerStartDelimLength = XRegExp.exec(str, left, outerStart, 'sticky')[0].length;
                            delimEnd = outerStart + (outerStartDelimLength || 1);
                        } else {
                            delimEnd = outerStart + 1;
                        }
                        openTokens = 0;
                    }
                } else if (unbalanced === 'error') {
                    const delimSide = rightMatch ? 'right' : 'left';
                    const errorPos = rightMatch ? delimStart : outerStart;
                    throw new Error(`Unbalanced ${delimSide} delimiter found in string at position ${errorPos}`);
                } else {
                    throw new Error(`Unsupported value for unbalanced: ${unbalanced}`);
                }
            }
            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;
    };
};

var unicodeBase = (XRegExp) => {
    const unicode = {};
    const unicodeTypes = {};
    const dec = XRegExp._dec;
    const hex = XRegExp._hex;
    const pad4 = XRegExp._pad4;
    function normalize(name) {
        return name.replace(/[- _]+/g, '').toLowerCase();
    }
    function charCode(chr) {
        const esc = /^\\[xu](.+)/.exec(chr);
        return esc ?
            dec(esc[1]) :
            chr.charCodeAt(chr[0] === '\\' ? 1 : 0);
    }
    function invertBmp(range) {
        let output = '';
        let lastEnd = -1;
        XRegExp.forEach(
            range,
            /(\\x..|\\u....|\\?[\s\S])(?:-(\\x..|\\u....|\\?[\s\S]))?/,
            (m) => {
                const start = charCode(m[1]);
                if (start > (lastEnd + 1)) {
                    output += `\\u${pad4(hex(lastEnd + 1))}`;
                    if (start > (lastEnd + 2)) {
                        output += `-\\u${pad4(hex(start - 1))}`;
                    }
                }
                lastEnd = charCode(m[2] || m[1]);
            }
        );
        if (lastEnd < 0xFFFF) {
            output += `\\u${pad4(hex(lastEnd + 1))}`;
            if (lastEnd < 0xFFFE) {
                output += '-\\uFFFF';
            }
        }
        return output;
    }
    function cacheInvertedBmp(slug) {
        const prop = 'b!';
        return (
            unicode[slug][prop] ||
            (unicode[slug][prop] = invertBmp(unicode[slug].bmp))
        );
    }
    function buildAstral(slug, isNegated) {
        const item = unicode[slug];
        let combined = '';
        if (item.bmp && !item.isBmpLast) {
            combined = `[${item.bmp}]${item.astral ? '|' : ''}`;
        }
        if (item.astral) {
            combined += item.astral;
        }
        if (item.isBmpLast && item.bmp) {
            combined += `${item.astral ? '|' : ''}[${item.bmp}]`;
        }
        return isNegated ?
            `(?:(?!${combined})(?:[\uD800-\uDBFF][\uDC00-\uDFFF]|[\0-\uFFFF]))` :
            `(?:${combined})`;
    }
    function cacheAstral(slug, isNegated) {
        const prop = isNegated ? 'a!' : 'a=';
        return (
            unicode[slug][prop] ||
            (unicode[slug][prop] = buildAstral(slug, isNegated))
        );
    }
    XRegExp.addToken(
        /\\([pP])(?:{(\^?)(?:(\w+)=)?([^}]*)}|([A-Za-z]))/,
        (match, scope, flags) => {
            const ERR_DOUBLE_NEG = 'Invalid double negation ';
            const ERR_UNKNOWN_NAME = 'Unknown Unicode token ';
            const ERR_UNKNOWN_REF = 'Unicode token missing data ';
            const ERR_ASTRAL_ONLY = 'Astral mode required for Unicode token ';
            const ERR_ASTRAL_IN_CLASS = 'Astral mode does not support Unicode tokens within character classes';
            const [
                fullToken,
                pPrefix,
                caretNegation,
                typePrefix,
                tokenName,
                tokenSingleCharName
            ] = match;
            let isNegated = pPrefix === 'P' || !!caretNegation;
            const isAstralMode = flags.includes('A');
            let slug = normalize(tokenSingleCharName || tokenName);
            let 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);
                }
            }
            if (item.inverseOf) {
                slug = normalize(item.inverseOf);
                if (!unicode.hasOwnProperty(slug)) {
                    throw new ReferenceError(`${ERR_UNKNOWN_REF + fullToken} -> ${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) :
                `${(isNegated ? '[^' : '[') + item.bmp}]`;
        },
        {
            scope: 'all',
            optionalFlags: 'A',
            leadChar: '\\'
        }
    );
    XRegExp.addUnicodeData = (data, typePrefix) => {
        const ERR_NO_NAME = 'Unicode token requires name';
        const ERR_NO_DATA = 'Unicode token has no character data ';
        if (typePrefix) {
            unicodeTypes[typePrefix] = {};
        }
        for (const item of data) {
            if (!item.name) {
                throw new Error(ERR_NO_NAME);
            }
            if (!(item.inverseOf || item.bmp || item.astral)) {
                throw new Error(ERR_NO_DATA + item.name);
            }
            const normalizedName = normalize(item.name);
            unicode[normalizedName] = item;
            if (typePrefix) {
                unicodeTypes[typePrefix][normalizedName] = true;
            }
            if (item.alias) {
                const normalizedAlias = normalize(item.alias);
                unicode[normalizedAlias] = item;
                if (typePrefix) {
                    unicodeTypes[typePrefix][normalizedAlias] = true;
                }
            }
        }
        XRegExp.cache.flush('patterns');
    };
    XRegExp._getUnicodeProperty = (name) => {
        const 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__*/(0,text_encoding_polyfill.g)(categories);

var unicodeCategories = (XRegExp) => {
    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__*/(0,text_encoding_polyfill.g)(properties);

var unicodeProperties = (XRegExp) => {
    if (!XRegExp.addUnicodeData) {
        throw new ReferenceError('Unicode Base must be loaded before Unicode Properties');
    }
    const unicodeData = properties$1;
    unicodeData.push({
        name: 'Assigned',
        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__*/(0,text_encoding_polyfill.g)(scripts);

var unicodeScripts = (XRegExp) => {
    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 compatibilityTableData$1 = {};

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 AdblockSyntax;
(function (AdblockSyntax) {
    AdblockSyntax["Common"] = "Common";
    AdblockSyntax["Abp"] = "AdblockPlus";
    AdblockSyntax["Ubo"] = "UblockOrigin";
    AdblockSyntax["Adg"] = "AdGuard";
})(AdblockSyntax || (AdblockSyntax = {}));
const EMPTY = '';
const SPACE = ' ';
const TAB = '\t';
const COLON = ':';
const COMMA = ',';
const DOT = '.';
const SEMICOLON = ';';
const ASTERISK = '*';
const EQUALS = '=';
const PIPE = '|';
const UNDERSCORE = '_';
const BACKSLASH = '\\';
const ESCAPE_CHARACTER = BACKSLASH;
const CR = '\r';
const FF = '\f';
const LF = '\n';
const CRLF = CR + LF;
const BACKTICK_QUOTE = '`';
const DOUBLE_QUOTE = '"';
const SINGLE_QUOTE = '\'';
const OPEN_PARENTHESIS = '(';
const CLOSE_PARENTHESIS = ')';
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';
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,
]);
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';
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,
]);
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';
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 NEGATION_MARKER = '~';
const WILDCARD = ASTERISK;
const NULL = 0;
const UINT8_MAX = 255;
const SINGLE_QUOTE_MARKER = "'";
const DOUBLE_QUOTE_MARKER = '"';
class StringUtils {
    static findNextUnescapedCharacter(pattern, searchedCharacter, start = 0, escapeCharacter = ESCAPE_CHARACTER) {
        for (let i = start; i < pattern.length; i += 1) {
            if (pattern[i] === searchedCharacter && pattern[i - 1] !== escapeCharacter) {
                return i;
            }
        }
        return -1;
    }
    static findNextUnescapedCharacterBackwards(pattern, searchedCharacter, start = pattern.length - 1, escapeCharacter = ESCAPE_CHARACTER) {
        for (let i = start; i >= 0; i -= 1) {
            if (pattern[i] === searchedCharacter && pattern[i - 1] !== escapeCharacter) {
                return i;
            }
        }
        return -1;
    }
    static findLastUnescapedCharacter(pattern, searchedCharacter, escapeCharacter = ESCAPE_CHARACTER) {
        for (let i = pattern.length - 1; i >= 0; i -= 1) {
            if (pattern[i] === searchedCharacter && pattern[i - 1] !== escapeCharacter) {
                return i;
            }
        }
        return -1;
    }
    static findNextUnescapedCharacterThatNotFollowedBy(pattern, start, searchedCharacter, notFollowedBy, escapeCharacter = ESCAPE_CHARACTER) {
        for (let i = start; i < pattern.length; i += 1) {
            if (pattern[i] === searchedCharacter
                && pattern[i + 1] !== notFollowedBy
                && pattern[i - 1] !== escapeCharacter) {
                return i;
            }
        }
        return -1;
    }
    static findLastUnescapedCharacterThatNotFollowedBy(pattern, searchedCharacter, notFollowedBy, escapeCharacter = ESCAPE_CHARACTER) {
        for (let i = pattern.length - 1; i >= 0; i -= 1) {
            if (pattern[i] === searchedCharacter
                && pattern[i + 1] !== notFollowedBy
                && pattern[i - 1] !== escapeCharacter) {
                return i;
            }
        }
        return -1;
    }
    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;
    }
    static findNextUnquotedUnescapedCharacter(pattern, searchedCharacter, start = 0, escapeCharacter = ESCAPE_CHARACTER) {
        let openQuote = null;
        for (let i = start; i < pattern.length; i += 1) {
            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) {
                if (!openQuote) {
                    return i;
                }
            }
        }
        return -1;
    }
    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;
    }
    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;
    }
    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;
    }
    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;
    }
    static isWhitespace(char) {
        return char === SPACE || char === TAB;
    }
    static isDigit(char) {
        return char >= NUMBER_0 && char <= NUMBER_9;
    }
    static isSmallLetter(char) {
        return char >= SMALL_LETTER_A && char <= SMALL_LETTER_Z;
    }
    static isCapitalLetter(char) {
        return char >= CAPITAL_LETTER_A && char <= CAPITAL_LETTER_Z;
    }
    static isLetter(char) {
        return StringUtils.isSmallLetter(char) || StringUtils.isCapitalLetter(char);
    }
    static isAlphaNumeric(char) {
        return StringUtils.isLetter(char) || StringUtils.isDigit(char);
    }
    static findFirstNonWhitespaceCharacter(pattern, start = 0) {
        for (let i = start; i < pattern.length; i += 1) {
            if (!StringUtils.isWhitespace(pattern[i])) {
                return i;
            }
        }
        return -1;
    }
    static findLastNonWhitespaceCharacter(pattern) {
        for (let i = pattern.length - 1; i >= 0; i -= 1) {
            if (!StringUtils.isWhitespace(pattern[i])) {
                return i;
            }
        }
        return -1;
    }
    static findNextWhitespaceCharacter(pattern, start = 0) {
        for (let i = start; i < pattern.length; i += 1) {
            if (StringUtils.isWhitespace(pattern[i])) {
                return i;
            }
        }
        return pattern.length;
    }
    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;
    }
    static skipWS(pattern, start = 0) {
        let i = start;
        while (i < pattern.length && StringUtils.isWhitespace(pattern[i])) {
            i += 1;
        }
        return Math.min(i, pattern.length);
    }
    static skipWSBack(pattern, start = pattern.length - 1) {
        let i = start;
        while (i >= 0 && StringUtils.isWhitespace(pattern[i])) {
            i -= 1;
        }
        return Math.max(i, -1);
    }
    static isEOL(char) {
        return char === CR || char === LF || char === FF;
    }
    static splitStringByNewLines(input) {
        return input.split(/\r?\n/);
    }
    static splitStringByNewLinesEx(input) {
        const result = [];
        let currentLine = EMPTY;
        let newLineType = null;
        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;
    }
    static mergeStringByNewLines(input) {
        let result = EMPTY;
        for (let i = 0; i < input.length; i += 1) {
            const [line, newLineType] = input[i];
            result += line;
            if (newLineType !== null) {
                if (newLineType === 'crlf') {
                    result += CRLF;
                }
                else if (newLineType === 'cr') {
                    result += CR;
                }
                else {
                    result += LF;
                }
            }
        }
        return result;
    }
    static parseNumber(raw) {
        const result = parseInt(raw, 10);
        if (Number.isNaN(result)) {
            throw new Error('Expected a number');
        }
        return result;
    }
    static isString(value) {
        return typeof value === '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;
    }
}
var OperatorValue;
(function (OperatorValue) {
    OperatorValue["Not"] = "!";
    OperatorValue["And"] = "&&";
    OperatorValue["Or"] = "||";
})(OperatorValue || (OperatorValue = {}));
var CommentMarker;
(function (CommentMarker) {
    CommentMarker["Regular"] = "!";
    CommentMarker["Hashmark"] = "#";
})(CommentMarker || (CommentMarker = {}));
var RuleCategory;
(function (RuleCategory) {
    RuleCategory["Empty"] = "Empty";
    RuleCategory["Invalid"] = "Invalid";
    RuleCategory["Comment"] = "Comment";
    RuleCategory["Cosmetic"] = "Cosmetic";
    RuleCategory["Network"] = "Network";
})(RuleCategory || (RuleCategory = {}));
var ListNodeType;
(function (ListNodeType) {
    ListNodeType["Unknown"] = "Unknown";
    ListNodeType["AppList"] = "AppList";
    ListNodeType["DomainList"] = "DomainList";
    ListNodeType["MethodList"] = "MethodList";
    ListNodeType["StealthOptionList"] = "StealthOptionList";
})(ListNodeType || (ListNodeType = {}));
var ListItemNodeType;
(function (ListItemNodeType) {
    ListItemNodeType["Unknown"] = "Unknown";
    ListItemNodeType["App"] = "App";
    ListItemNodeType["Domain"] = "Domain";
    ListItemNodeType["Method"] = "Method";
    ListItemNodeType["StealthOption"] = "StealthOption";
})(ListItemNodeType || (ListItemNodeType = {}));
var CommentRuleType;
(function (CommentRuleType) {
    CommentRuleType["AgentCommentRule"] = "AgentCommentRule";
    CommentRuleType["CommentRule"] = "CommentRule";
    CommentRuleType["ConfigCommentRule"] = "ConfigCommentRule";
    CommentRuleType["HintCommentRule"] = "HintCommentRule";
    CommentRuleType["MetadataCommentRule"] = "MetadataCommentRule";
    CommentRuleType["PreProcessorCommentRule"] = "PreProcessorCommentRule";
})(CommentRuleType || (CommentRuleType = {}));
var CosmeticRuleType;
(function (CosmeticRuleType) {
    CosmeticRuleType["ElementHidingRule"] = "ElementHidingRule";
    CosmeticRuleType["CssInjectionRule"] = "CssInjectionRule";
    CosmeticRuleType["ScriptletInjectionRule"] = "ScriptletInjectionRule";
    CosmeticRuleType["HtmlFilteringRule"] = "HtmlFilteringRule";
    CosmeticRuleType["JsInjectionRule"] = "JsInjectionRule";
})(CosmeticRuleType || (CosmeticRuleType = {}));
var CosmeticRuleSeparator;
(function (CosmeticRuleSeparator) {
    CosmeticRuleSeparator["ElementHiding"] = "##";
    CosmeticRuleSeparator["ElementHidingException"] = "#@#";
    CosmeticRuleSeparator["ExtendedElementHiding"] = "#?#";
    CosmeticRuleSeparator["ExtendedElementHidingException"] = "#@?#";
    CosmeticRuleSeparator["AbpSnippet"] = "#$#";
    CosmeticRuleSeparator["AbpSnippetException"] = "#@$#";
    CosmeticRuleSeparator["AdgCssInjection"] = "#$#";
    CosmeticRuleSeparator["AdgCssInjectionException"] = "#@$#";
    CosmeticRuleSeparator["AdgExtendedCssInjection"] = "#$?#";
    CosmeticRuleSeparator["AdgExtendedCssInjectionException"] = "#@$?#";
    CosmeticRuleSeparator["AdgJsInjection"] = "#%#";
    CosmeticRuleSeparator["AdgJsInjectionException"] = "#@%#";
    CosmeticRuleSeparator["AdgHtmlFiltering"] = "$$";
    CosmeticRuleSeparator["AdgHtmlFilteringException"] = "$@$";
})(CosmeticRuleSeparator || (CosmeticRuleSeparator = {}));
var BinaryTypeMap;
(function (BinaryTypeMap) {
    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";
    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 = {}));
const SYNTAX_SERIALIZATION_MAP = new Map([
    [AdblockSyntax.Common, 0],
    [AdblockSyntax.Abp, 1],
    [AdblockSyntax.Adg, 2],
    [AdblockSyntax.Ubo, 3],
]);
new Map(Array.from(SYNTAX_SERIALIZATION_MAP, ([key, value]) => [value, key]));
var NetworkRuleType;
(function (NetworkRuleType) {
    NetworkRuleType["NetworkRule"] = "NetworkRule";
    NetworkRuleType["HostRule"] = "HostRule";
})(NetworkRuleType || (NetworkRuleType = {}));
const ERROR_NAME$3 = 'AdblockSyntaxError';
class AdblockSyntaxError extends SyntaxError {
    start;
    end;
    constructor(message, start, end) {
        super(message);
        this.name = ERROR_NAME$3;
        this.start = start;
        this.end = end;
    }
}
const ERROR_NAME$2 = 'NotImplementedError';
const BASE_MESSAGE = 'Not implemented';
class NotImplementedError extends Error {
    constructor(message = undefined) {
        const fullMessage = message
            ? `${BASE_MESSAGE}: ${message}`
            : BASE_MESSAGE;
        super(fullMessage);
        this.name = ERROR_NAME$2;
    }
}
class ParserBase {
    static parse(input, options, baseOffset, ...args) {
        throw new NotImplementedError();
    }
    static generate(node) {
        throw new NotImplementedError();
    }
    static serialize(node, buffer, ...args) {
        throw new NotImplementedError();
    }
    static deserialize(buffer, node, ...args) {
        throw new NotImplementedError();
    }
}
const defaultParserOptions = Object.freeze({
    tolerant: false,
    isLocIncluded: true,
    parseAbpSpecificRules: true,
    parseUboSpecificRules: true,
    includeRaws: true,
    ignoreComments: false,
    parseHostRules: false,
});
const isUndefined = (value) => {
    return typeof value === 'undefined';
};
const isNull = (value) => {
    return value === null;
};
const isString = (value) => {
    return typeof value === 'string';
};
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 = {}));
class ValueParser extends (/* unused pure expression or super */ null && (ParserBase)) {
    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;
    }
    static generate(node) {
        return node.value;
    }
    static serialize(node, buffer, frequentValuesMap, toLower = false) {
        buffer.writeUint8(BinaryTypeMap.ValueNode);
        const frequentValue = frequentValuesMap?.get(toLower ? node.value.toLowerCase() : node.value);
        if (!isUndefined(frequentValue)) {
            buffer.writeUint8(ValueNodeSerializationMap.FrequentValue);
            buffer.writeUint8(frequentValue);
        }
        else {
            buffer.writeUint8(ValueNodeSerializationMap.Value);
            buffer.writeString(node.value);
        }
        if (!isUndefined(node.start)) {
            buffer.writeUint8(ValueNodeSerializationMap.Start);
            buffer.writeUint32(node.start);
        }
        if (!isUndefined(node.end)) {
            buffer.writeUint8(ValueNodeSerializationMap.End);
            buffer.writeUint32(node.end);
        }
        buffer.writeUint8(NULL);
    }
    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();
        }
    }
}
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 = {}));
const FREQUENT_AGENTS_DESERIALIZATION_MAP = new Map([
    [0, 'AdGuard'],
    [1, 'ADG'],
    [2, 'uBlock Origin'],
    [3, 'uBlock'],
    [4, 'uBO'],
    [5, 'Adblock Plus'],
    [6, 'AdblockPlus'],
    [7, 'ABP'],
    [8, 'AdBlock'],
]);
new Map(Array.from(FREQUENT_AGENTS_DESERIALIZATION_MAP).map(([key, value]) => [value.toLowerCase(), key]));
var AgentRuleSerializationMap;
(function (AgentRuleSerializationMap) {
    AgentRuleSerializationMap[AgentRuleSerializationMap["Children"] = 1] = "Children";
    AgentRuleSerializationMap[AgentRuleSerializationMap["Start"] = 2] = "Start";
    AgentRuleSerializationMap[AgentRuleSerializationMap["End"] = 3] = "End";
})(AgentRuleSerializationMap || (AgentRuleSerializationMap = {}));
var ParameterListNodeSerializationMap;
(function (ParameterListNodeSerializationMap) {
    ParameterListNodeSerializationMap[ParameterListNodeSerializationMap["Children"] = 1] = "Children";
    ParameterListNodeSerializationMap[ParameterListNodeSerializationMap["Start"] = 2] = "Start";
    ParameterListNodeSerializationMap[ParameterListNodeSerializationMap["End"] = 3] = "End";
})(ParameterListNodeSerializationMap || (ParameterListNodeSerializationMap = {}));
class ParameterListParser extends (/* unused pure expression or super */ null && (ParserBase)) {
    static parse(raw, options = defaultParserOptions, baseOffset = 0, separator = COMMA) {
        const params = {
            type: 'ParameterList',
            children: [],
        };
        const { length } = raw;
        if (options.isLocIncluded) {
            params.start = baseOffset;
            params.end = baseOffset + length;
        }
        let offset = 0;
        while (offset < length) {
            offset = StringUtils.skipWS(raw, offset);
            if (raw[offset] === separator || offset === length) {
                params.children.push(null);
                offset += 1;
            }
            else {
                const paramStart = offset;
                const nextSeparator = StringUtils.findUnescapedNonStringNonRegexChar(raw, separator, offset);
                const paramEnd = nextSeparator !== -1
                    ? StringUtils.skipWSBack(raw, nextSeparator - 1)
                    : StringUtils.skipWSBack(raw);
                const param = ValueParser.parse(raw.slice(paramStart, paramEnd + 1), options, baseOffset + paramStart);
                params.children.push(param);
                offset = nextSeparator !== -1 ? nextSeparator + 1 : length;
            }
        }
        if (raw[length - 1] === separator) {
            params.children.push(null);
        }
        return params;
    }
    static generate(params, separator = COMMA) {
        const collection = [];
        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));
            }
        }
        const result = collection.join(separator === SPACE ? separator : `${separator}${SPACE}`);
        return result;
    }
    static serialize(node, buffer, frequentValuesMap, toLower = false) {
        buffer.writeUint8(BinaryTypeMap.ParameterListNode);
        const count = node.children.length;
        buffer.writeUint8(ParameterListNodeSerializationMap.Children);
        buffer.writeUint32(count);
        for (let i = 0; i < count; i += 1) {
            const child = node.children[i];
            if (isNull(child)) {
                buffer.writeUint8(BinaryTypeMap.Null);
                continue;
            }
            ValueParser.serialize(child, buffer, frequentValuesMap, toLower);
        }
        if (!isUndefined(node.start)) {
            buffer.writeUint8(ParameterListNodeSerializationMap.Start);
            buffer.writeUint32(node.start);
        }
        if (!isUndefined(node.end)) {
            buffer.writeUint8(ParameterListNodeSerializationMap.End);
            buffer.writeUint32(node.end);
        }
        buffer.writeUint8(NULL);
    }
    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());
                    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();
        }
    }
}
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 = {}));
var ConfigNodeSerializationMap;
(function (ConfigNodeSerializationMap) {
    ConfigNodeSerializationMap[ConfigNodeSerializationMap["Value"] = 1] = "Value";
    ConfigNodeSerializationMap[ConfigNodeSerializationMap["Start"] = 2] = "Start";
    ConfigNodeSerializationMap[ConfigNodeSerializationMap["End"] = 3] = "End";
})(ConfigNodeSerializationMap || (ConfigNodeSerializationMap = {}));
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],
]);
new Map(Array.from(FREQUENT_COMMANDS_SERIALIZATION_MAP).map(([key, value]) => [value, key]));
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 = {}));
const FREQUENT_HINTS_SERIALIZATION_MAP = new Map([
    ['NOT_OPTIMIZED', 0],
    ['PLATFORM', 1],
    ['NOT_PLATFORM', 2],
]);
new Map(Array.from(FREQUENT_HINTS_SERIALIZATION_MAP).map(([key, value]) => [value, key]));
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],
]);
new Map(Array.from(FREQUENT_PLATFORMS_SERIALIZATION_MAP).map(([key, value]) => [value, key]));
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 = {}));
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 = {}));
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'],
]);
const FREQUENT_HEADERS_SERIALIZATION_MAP = new Map(Array.from(FREQUENT_HEADERS_DESERIALIZATION_MAP.entries()).map(([key, value]) => [value.toLowerCase(), key]));
Array.from(FREQUENT_HEADERS_SERIALIZATION_MAP.keys());
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 = {}));
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 = {}));
var ParenthesisNodeBinaryPropMap;
(function (ParenthesisNodeBinaryPropMap) {
    ParenthesisNodeBinaryPropMap[ParenthesisNodeBinaryPropMap["Expression"] = 1] = "Expression";
    ParenthesisNodeBinaryPropMap[ParenthesisNodeBinaryPropMap["Start"] = 2] = "Start";
    ParenthesisNodeBinaryPropMap[ParenthesisNodeBinaryPropMap["End"] = 3] = "End";
})(ParenthesisNodeBinaryPropMap || (ParenthesisNodeBinaryPropMap = {}));
var TokenType;
(function (TokenType) {
    TokenType[TokenType["Variable"] = 0] = "Variable";
    TokenType[TokenType["Operator"] = 1] = "Operator";
    TokenType[TokenType["Parenthesis"] = 2] = "Parenthesis";
})(TokenType || (TokenType = {}));
var NodeType;
(function (NodeType) {
    NodeType["Variable"] = "Variable";
    NodeType["Operator"] = "Operator";
    NodeType["Parenthesis"] = "Parenthesis";
})(NodeType || (NodeType = {}));
({
    [OperatorValue.Not]: 3,
    [OperatorValue.And]: 2,
    [OperatorValue.Or]: 1,
});
const OPERATOR_BINARY_MAP = new Map([
    [OperatorValue.Not, 0],
    [OperatorValue.And, 1],
    [OperatorValue.Or, 2],
]);
new Map(Array.from(OPERATOR_BINARY_MAP).map(([key, value]) => [value, key]));
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],
]);
new Map(Array.from(KNOWN_VARIABLES_MAP).map(([key, value]) => [value, key]));
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 = {}));
const FREQUENT_DIRECTIVES_SERIALIZATION_MAP = new Map([
    ['if', 0],
    ['else', 1],
    ['endif', 2],
    ['include', 3],
    ['safari_cb_affinity', 4],
]);
new Map(Array.from(FREQUENT_DIRECTIVES_SERIALIZATION_MAP).map(([key, value]) => [value, key]));
const FREQUENT_PARAMS_SERIALIZATION_MAP = new Map([
    ['general', 0],
    ['privacy', 1],
    ['social', 2],
    ['security', 3],
    ['other', 4],
    ['custom', 5],
    ['all', 6],
]);
new Map(Array.from(FREQUENT_PARAMS_SERIALIZATION_MAP).map(([key, value]) => [value, key]));
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 = {}));
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 = {}));
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',
};
const parseListItems = (raw, options = defaultParserOptions, baseOffset = 0, separator = COMMA, type = ListItemNodeType.Unknown) => {
    const rawListItems = [];
    let offset = 0;
    offset = StringUtils.skipWS(raw, offset);
    if (raw[offset] === separator) {
        throw new AdblockSyntaxError(LIST_PARSE_ERROR_PREFIX.NO_SEPARATOR_AT_THE_BEGINNING, baseOffset + offset, baseOffset + raw.length);
    }
    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);
    }
    while (offset < raw.length) {
        offset = StringUtils.skipWS(raw, offset);
        let itemStart = offset;
        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;
        if (exception) {
            itemStart += 1;
            const item = raw[itemStart];
            if (item === NEGATION_MARKER) {
                throw new AdblockSyntaxError(LIST_PARSE_ERROR_PREFIX.NO_MULTIPLE_NEGATION, baseOffset + itemStart, baseOffset + itemStart + 1);
            }
            if (item === separator) {
                throw new AdblockSyntaxError(LIST_PARSE_ERROR_PREFIX.NO_SEPARATOR_AFTER_NEGATION, baseOffset + itemStart, baseOffset + itemStart + 1);
            }
            if (StringUtils.isWhitespace(item)) {
                throw new AdblockSyntaxError(LIST_PARSE_ERROR_PREFIX.NO_WHITESPACE_AFTER_NEGATION, baseOffset + itemStart, baseOffset + itemStart + 1);
            }
        }
        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;
        }
        rawListItems.push(listItem);
        offset = separatorStartIndex === -1 ? raw.length : separatorStartIndex + 1;
    }
    return rawListItems;
};
const generateListItem = (item) => {
    return `${item.exception ? NEGATION_MARKER : EMPTY}${item.value}`;
};
const generateListItems = (items, separator) => {
    return items.map(generateListItem).join(separator);
};
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(item.start)) {
        buffer.writeUint8(ListItemSerializationMap.Start);
        buffer.writeUint32(item.start);
    }
    if (!isUndefined(item.end)) {
        buffer.writeUint8(ListItemSerializationMap.End);
        buffer.writeUint32(item.end);
    }
    buffer.writeUint8(NULL);
};
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();
    }
};
const serializeListItems = (items, buffer) => {
    const { length } = items;
    buffer.writeUint16(length);
    for (let i = 0; i < length; i += 1) {
        serializeListItem(items[i], buffer);
    }
};
const deserializeListItems = (buffer, items) => {
    const length = buffer.readUint16();
    items.length = length;
    for (let i = 0; i < length; i += 1) {
        deserializeListItem(buffer, items[i] = {});
    }
};
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 = {}));
const SEPARATOR_SERIALIZATION_MAP$1 = new Map([
    [COMMA, 0],
    [PIPE, 1],
]);
const SEPARATOR_DESERIALIZATION_MAP$1 = new Map(Array.from(SEPARATOR_SERIALIZATION_MAP$1).map(([key, value]) => [value, key]));
class DomainListParser extends ParserBase {
    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;
    }
    static generate(node) {
        return generateListItems(node.children, node.separator);
    }
    static serialize(node, buffer) {
        buffer.writeUint8(BinaryTypeMap.DomainListNode);
        const separator = SEPARATOR_SERIALIZATION_MAP$1.get(node.separator);
        if (isUndefined(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(node.start)) {
            buffer.writeUint8(DomainListSerializationMap.Start);
            buffer.writeUint32(node.start);
        }
        if (!isUndefined(node.end)) {
            buffer.writeUint8(DomainListSerializationMap.End);
            buffer.writeUint32(node.end);
        }
        buffer.writeUint8(NULL);
    }
    static deserialize(buffer, node) {
        buffer.assertUint8(BinaryTypeMap.DomainListNode);
        node.type = ListNodeType.DomainList;
        let prop = buffer.readUint8();
        while (prop !== NULL) {
            switch (prop) {
                case DomainListSerializationMap.Separator:
                    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();
        }
    }
}
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 = {}));
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],
]);
new Map(Array.from(FREQUENT_MODIFIERS_SERIALIZATION_MAP, ([key, value]) => [value, key]));
const FREQUENT_REDIRECT_VALUES_SERIALIZATION_MAP = new Map([
    ['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],
    ['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],
    ['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],
    ['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],
]);
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],
]);
new Map(Array.from(FREQUENT_VALUES_SERIALIZATION_MAPS, ([modifier, valueMap]) => [modifier, new Map(Array.from(valueMap, ([key, value]) => [value, key]))]));
var ModifierListNodeSerializationMap;
(function (ModifierListNodeSerializationMap) {
    ModifierListNodeSerializationMap[ModifierListNodeSerializationMap["Children"] = 1] = "Children";
    ModifierListNodeSerializationMap[ModifierListNodeSerializationMap["Start"] = 2] = "Start";
    ModifierListNodeSerializationMap[ModifierListNodeSerializationMap["End"] = 3] = "End";
})(ModifierListNodeSerializationMap || (ModifierListNodeSerializationMap = {}));
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],
]);
new Map([
    [TokenType$1.Function, TokenType$1.CloseParenthesis],
    [TokenType$1.OpenParenthesis, TokenType$1.CloseParenthesis],
]);
var UboPseudoName;
(function (UboPseudoName) {
    UboPseudoName["MatchesMedia"] = "matches-media";
    UboPseudoName["MatchesPath"] = "matches-path";
    UboPseudoName["Remove"] = "remove";
    UboPseudoName["Style"] = "style";
})(UboPseudoName || (UboPseudoName = {}));
new Set([
    UboPseudoName.MatchesMedia,
    UboPseudoName.MatchesPath,
    UboPseudoName.Remove,
    UboPseudoName.Style,
]);
const EXT_CSS_PSEUDO_CLASSES_STRICT = new Set([
    'contains',
    'if-not',
    'matches-attr',
    'matches-css',
    'matches-property',
    'nth-ancestor',
    'remove',
    'upward',
    'xpath',
    'has-text',
    'matches-css-after',
    'matches-css-before',
    'matches-path',
    'min-text-length',
    'watch-attr',
    '-abp-contains',
    '-abp-has',
    '-abp-properties',
]);
new Set([
    ...EXT_CSS_PSEUDO_CLASSES_STRICT,
    'has',
    'is',
]);
var AbpSnippetBodySerializationMap;
(function (AbpSnippetBodySerializationMap) {
    AbpSnippetBodySerializationMap[AbpSnippetBodySerializationMap["Children"] = 1] = "Children";
    AbpSnippetBodySerializationMap[AbpSnippetBodySerializationMap["Start"] = 2] = "Start";
    AbpSnippetBodySerializationMap[AbpSnippetBodySerializationMap["End"] = 3] = "End";
})(AbpSnippetBodySerializationMap || (AbpSnippetBodySerializationMap = {}));
const serializeScriptletBody = (node, buffer, frequentScriptletArgs) => {
    buffer.writeUint8(BinaryTypeMap.ScriptletInjectionRuleBodyNode);
    const { length } = node.children;
    buffer.writeUint8(AbpSnippetBodySerializationMap.Children);
    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(node.start)) {
        buffer.writeUint8(AbpSnippetBodySerializationMap.Start);
        buffer.writeUint32(node.start);
    }
    if (!isUndefined(node.end)) {
        buffer.writeUint8(AbpSnippetBodySerializationMap.End);
        buffer.writeUint32(node.end);
    }
    buffer.writeUint8(NULL);
};
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());
                for (let i = 0; i < node.children.length; i += 1) {
                    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();
    }
};
class AbpSnippetInjectionBodyParser extends (/* unused pure expression or super */ null && (ParserBase)) {
    static ERROR_MESSAGES = {
        EMPTY_SCRIPTLET_CALL: 'Empty ABP snippet call',
    };
    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],
    ]);
    static FREQUENT_ARGS_DESERIALIZATION_MAP = new Map(Array.from(this.FREQUENT_ARGS_SERIALIZATION_MAP).map(([key, value]) => [value, key]));
    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;
        offset = StringUtils.skipWS(raw, offset);
        while (offset < raw.length) {
            offset = StringUtils.skipWS(raw, offset);
            const scriptletCallStart = offset;
            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);
            result.children.push(params);
            offset = semicolonIndex + 1;
        }
        if (result.children.length === 0) {
            throw new AdblockSyntaxError(this.ERROR_MESSAGES.EMPTY_SCRIPTLET_CALL, baseOffset, baseOffset + raw.length);
        }
        return result;
    }
    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);
    }
    static serialize(node, buffer) {
        serializeScriptletBody(node, buffer, this.FREQUENT_ARGS_SERIALIZATION_MAP);
    }
    static deserialize(buffer, node) {
        deserializeScriptletBody(buffer, node, this.FREQUENT_ARGS_DESERIALIZATION_MAP);
    }
}
const QUOTE_SET = new Set([
    SINGLE_QUOTE,
    DOUBLE_QUOTE,
    BACKTICK_QUOTE,
]);
var QuoteType;
(function (QuoteType) {
    QuoteType["None"] = "none";
    QuoteType["Single"] = "single";
    QuoteType["Double"] = "double";
    QuoteType["Backtick"] = "backtick";
})(QuoteType || (QuoteType = {}));
class QuoteUtils {
    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;
    }
    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;
    }
    static getStringQuoteType(string) {
        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;
    }
    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) {
                    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) {
                    return BACKTICK_QUOTE + QuoteUtils.escapeUnescapedOccurrences(string, BACKTICK_QUOTE) + BACKTICK_QUOTE;
                }
                if (actualQuoteType !== QuoteType.Backtick) {
                    return BACKTICK_QUOTE
                        + QuoteUtils.escapeUnescapedOccurrences(QuoteUtils.unescapeSingleEscapedOccurrences(string.slice(1, -1), SINGLE_QUOTE), BACKTICK_QUOTE) + BACKTICK_QUOTE;
                }
                return string;
            default:
                return string;
        }
    }
    static removeQuotes(string) {
        if (
        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;
    }
    static removeQuotesAndUnescape(string) {
        if (
        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;
    }
    static quoteAndJoinStrings(strings, quoteType = QuoteType.Single, separator = `${COMMA}${SPACE}`) {
        return strings
            .map((s) => QuoteUtils.setStringQuoteType(s, quoteType))
            .join(separator);
    }
}
class UboParameterListParser extends (/* unused pure expression or super */ null && (ParameterListParser)) {
    static parse(raw, options = defaultParserOptions, baseOffset = 0, separator = COMMA, requireQuotes = false, supportedQuotes = QUOTE_SET) {
        const params = {
            type: 'ParameterList',
            children: [],
        };
        const { length } = raw;
        if (options.isLocIncluded) {
            params.start = baseOffset;
            params.end = baseOffset + length;
        }
        let offset = 0;
        let extraNull = false;
        while (offset < length) {
            offset = StringUtils.skipWS(raw, offset);
            const paramStart = offset;
            let paramEnd = offset;
            if (supportedQuotes.has(raw[offset])) {
                const possibleClosingQuoteIndex = StringUtils.findNextUnescapedCharacter(raw, raw[offset], offset + 1);
                if (possibleClosingQuoteIndex !== -1) {
                    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);
                        }
                        paramEnd = StringUtils.skipWSBack(raw, length - 1) + 1;
                        offset = length;
                    }
                    else if (raw[nextSeparatorIndex] === separator) {
                        paramEnd = possibleClosingQuoteIndex + 1;
                        offset = nextSeparatorIndex + 1;
                    }
                    else {
                        if (requireQuotes) {
                            throw new AdblockSyntaxError(`Expected separator, got: '${raw[nextSeparatorIndex]}'`, baseOffset + nextSeparatorIndex, baseOffset + length);
                        }
                        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);
                    }
                    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) {
                    paramEnd = StringUtils.skipWSBack(raw, length - 1) + 1;
                    offset = length;
                }
                else {
                    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;
    }
}
class UboScriptletInjectionBodyParser extends (/* unused pure expression or super */ null && (ParserBase)) {
    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',
    };
    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],
    ]);
    static FREQUENT_ARGS_DESERIALIZATION_MAP = new Map(Array.from(this.FREQUENT_ARGS_SERIALIZATION_MAP).map(([key, value]) => [value, key]));
    static parse(raw, options = defaultParserOptions, baseOffset = 0) {
        let offset = 0;
        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;
        }
        if (!scriptletMaskLength) {
            throw new AdblockSyntaxError(this.ERROR_MESSAGES.NO_SCRIPTLET_MASK, baseOffset + offset, baseOffset + raw.length);
        }
        offset += scriptletMaskLength;
        if (raw[offset] === SPACE) {
            throw new AdblockSyntaxError(this.ERROR_MESSAGES.WHITESPACE_AFTER_MASK, baseOffset + offset, baseOffset + raw.length);
        }
        if (raw[offset] !== OPEN_PARENTHESIS) {
            throw new AdblockSyntaxError(this.ERROR_MESSAGES.NO_OPENING_PARENTHESIS, baseOffset + offset, baseOffset + raw.length);
        }
        const openingParenthesesIndex = offset;
        const closingParenthesesIndex = StringUtils.skipWSBack(raw, raw.length - 1);
        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;
        }
        if (StringUtils.skipWS(raw, openingParenthesesIndex + 1) === closingParenthesesIndex) {
            return result;
        }
        const params = UboParameterListParser.parse(raw.slice(openingParenthesesIndex + 1, closingParenthesesIndex), options, baseOffset + openingParenthesesIndex + 1, COMMA);
        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;
    }
    static generate(node) {
        const result = [];
        if (node.children.length > 1) {
            throw new Error(this.ERROR_MESSAGES.NO_MULTIPLE_SCRIPTLET_CALLS);
        }
        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);
    }
    static serialize(node, buffer) {
        serializeScriptletBody(node, buffer, this.FREQUENT_ARGS_SERIALIZATION_MAP);
    }
    static deserialize(buffer, node) {
        deserializeScriptletBody(buffer, node, this.FREQUENT_ARGS_DESERIALIZATION_MAP);
    }
}
class AdgScriptletInjectionBodyParser extends (/* unused pure expression or super */ null && (ParserBase)) {
    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'",
    };
    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],
    ]);
    static FREQUENT_ARGS_DESERIALIZATION_MAP = new Map(Array.from(this.FREQUENT_ARGS_SERIALIZATION_MAP).map(([key, value]) => [value, key]));
    static parse(raw, options = defaultParserOptions, baseOffset = 0) {
        let offset = 0;
        offset = StringUtils.skipWS(raw, offset);
        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;
        if (raw[offset] === SPACE) {
            throw new AdblockSyntaxError(this.ERROR_MESSAGES.WHITESPACE_AFTER_MASK, baseOffset + offset, baseOffset + raw.length);
        }
        if (raw[offset] !== OPEN_PARENTHESIS) {
            throw new AdblockSyntaxError(this.ERROR_MESSAGES.NO_OPENING_PARENTHESIS, baseOffset + offset, baseOffset + raw.length);
        }
        const openingParenthesesIndex = offset;
        const closingParenthesesIndex = StringUtils.skipWSBack(raw, raw.length - 1);
        if (raw[closingParenthesesIndex] !== CLOSE_PARENTHESIS
            || raw[closingParenthesesIndex - 1] === ESCAPE_CHARACTER) {
            throw new AdblockSyntaxError(this.ERROR_MESSAGES.NO_CLOSING_PARENTHESIS, baseOffset + offset, baseOffset + raw.length);
        }
        offset = StringUtils.skipWS(raw, offset + 1);
        const result = {
            type: 'ScriptletInjectionRuleBody',
            children: [],
        };
        if (options.isLocIncluded) {
            result.start = baseOffset;
            result.end = baseOffset + raw.length;
        }
        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) {
            offset = StringUtils.skipWS(raw, offset);
            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);
                }
                offset += 1;
                offset = StringUtils.skipWS(raw, offset);
            }
            if (raw[offset] === SINGLE_QUOTE || raw[offset] === DOUBLE_QUOTE) {
                if (isNull(detectedQuote)) {
                    detectedQuote = raw[offset];
                }
                else if (detectedQuote !== raw[offset]) {
                    throw new AdblockSyntaxError(AdgScriptletInjectionBodyParser.ERROR_MESSAGES.NO_INCONSISTENT_QUOTES, baseOffset + offset, baseOffset + raw.length);
                }
                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);
                }
                const parameter = ValueParser.parse(raw.slice(offset, closingQuoteIndex + 1), options, baseOffset + offset);
                parameterList.children.push(parameter);
                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;
    }
    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);
    }
    static serialize(node, buffer) {
        serializeScriptletBody(node, buffer, this.FREQUENT_ARGS_SERIALIZATION_MAP);
    }
    static deserialize(buffer, node) {
        deserializeScriptletBody(buffer, node, this.FREQUENT_ARGS_DESERIALIZATION_MAP);
    }
}
const SEPARATOR_SERIALIZATION_MAP = new Map([
    ['##', 0],
    ['#@#', 1],
    ['#?#', 2],
    ['#@?#', 3],
    ['#$#', 4],
    ['#$?#', 5],
    ['#@$#', 6],
    ['#@$?#', 7],
    ['#%#', 8],
    ['#@%#', 9],
    ['$$', 10],
    ['$@$', 11],
]);
new Map(Array.from(SEPARATOR_SERIALIZATION_MAP).map(([key, value]) => [value, key]));
new Map([
    [BinaryTypeMap.ElementHidingRule, CosmeticRuleType.ElementHidingRule],
    [BinaryTypeMap.CssInjectionRule, CosmeticRuleType.CssInjectionRule],
    [BinaryTypeMap.ScriptletInjectionRule, CosmeticRuleType.ScriptletInjectionRule],
    [BinaryTypeMap.JsInjectionRule, CosmeticRuleType.JsInjectionRule],
    [BinaryTypeMap.HtmlFilteringRule, CosmeticRuleType.HtmlFilteringRule],
]);
var ElementHidingRuleSerializationMap;
(function (ElementHidingRuleSerializationMap) {
    ElementHidingRuleSerializationMap[ElementHidingRuleSerializationMap["SelectorList"] = 1] = "SelectorList";
    ElementHidingRuleSerializationMap[ElementHidingRuleSerializationMap["Start"] = 2] = "Start";
    ElementHidingRuleSerializationMap[ElementHidingRuleSerializationMap["End"] = 3] = "End";
})(ElementHidingRuleSerializationMap || (ElementHidingRuleSerializationMap = {}));
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 = {}));
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 = {}));
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 = {}));
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 = {}));
var HostnameListNodeSerializationMap;
(function (HostnameListNodeSerializationMap) {
    HostnameListNodeSerializationMap[HostnameListNodeSerializationMap["Children"] = 1] = "Children";
    HostnameListNodeSerializationMap[HostnameListNodeSerializationMap["Start"] = 2] = "Start";
    HostnameListNodeSerializationMap[HostnameListNodeSerializationMap["End"] = 3] = "End";
})(HostnameListNodeSerializationMap || (HostnameListNodeSerializationMap = {}));
var EmptyRuleSerializationMap;
(function (EmptyRuleSerializationMap) {
    EmptyRuleSerializationMap[EmptyRuleSerializationMap["Start"] = 1] = "Start";
    EmptyRuleSerializationMap[EmptyRuleSerializationMap["End"] = 2] = "End";
})(EmptyRuleSerializationMap || (EmptyRuleSerializationMap = {}));
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 = {}));
var InvalidRuleSerializationMap;
(function (InvalidRuleSerializationMap) {
    InvalidRuleSerializationMap[InvalidRuleSerializationMap["Error"] = 1] = "Error";
    InvalidRuleSerializationMap[InvalidRuleSerializationMap["Start"] = 2] = "Start";
    InvalidRuleSerializationMap[InvalidRuleSerializationMap["End"] = 3] = "End";
})(InvalidRuleSerializationMap || (InvalidRuleSerializationMap = {}));
const APP_LIST_SEPARATOR = PIPE;
class AppListParser extends ParserBase {
    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;
class MethodListParser extends ParserBase {
    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;
class StealthOptionListParser extends ParserBase {
    static parse(raw, options = defaultParserOptions, baseOffset = 0) {
        const result = {
            type: ListNodeType.StealthOptionList,
            separator: STEALTH_OPTION_LIST_SEPARATOR,
            children: parseListItems(raw, options, baseOffset, STEALTH_OPTION_LIST_SEPARATOR, ListItemNodeType.StealthOption),
        };
        if (options.isLocIncluded) {
            result.start = baseOffset;
            result.end = baseOffset + raw.length;
        }
        return result;
    }
}
var FilterListNodeSerializationMap;
(function (FilterListNodeSerializationMap) {
    FilterListNodeSerializationMap[FilterListNodeSerializationMap["Children"] = 1] = "Children";
    FilterListNodeSerializationMap[FilterListNodeSerializationMap["Start"] = 2] = "Start";
    FilterListNodeSerializationMap[FilterListNodeSerializationMap["End"] = 3] = "End";
})(FilterListNodeSerializationMap || (FilterListNodeSerializationMap = {}));
({
    [AdblockSyntax.Adg]: 'adg_',
    [AdblockSyntax.Ubo]: 'ubo_',
    [AdblockSyntax.Abp]: 'abp_',
});
const APP_NAME_ALLOWED_CHARS = new Set([
    ...CAPITAL_LETTERS,
    ...SMALL_LETTERS,
    ...NUMBERS,
    UNDERSCORE,
]);
const ALLOWED_METHODS = new Set([
    'connect',
    'delete',
    'get',
    'head',
    'options',
    'patch',
    'post',
    'put',
    'trace',
]);
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',
]);
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',
]);
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',
]);
const PERMISSIONS_TOKEN_SELF = 'self';
const EMPTY_PERMISSIONS_ALLOWLIST = `${OPEN_PARENTHESIS}${CLOSE_PARENTHESIS}`;
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',
]);
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',
    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',
};
const getInvalidValidationResult = (error) => {
    return {
        valid: false,
        error,
    };
};
const getValueRequiredValidationResult = (modifierName) => {
    return getInvalidValidationResult(`${VALIDATION_ERROR_PREFIX.VALUE_REQUIRED}: '${modifierName}'`);
};
const WILDCARD_TLD = DOT + WILDCARD;
const WILDCARD_SUBDOMAIN = WILDCARD + DOT;
class DomainUtils {
    static isValidDomainOrHostname(domain) {
        let domainToCheck = domain;
        if (domainToCheck === WILDCARD) {
            return true;
        }
        if (domainToCheck.endsWith(WILDCARD_TLD)) {
            domainToCheck = domainToCheck.substring(0, domainToCheck.length - WILDCARD_TLD.length);
        }
        if (domainToCheck.startsWith(WILDCARD_SUBDOMAIN)) {
            domainToCheck = domainToCheck.substring(WILDCARD_SUBDOMAIN.length);
        }
        const tldtsResult = (0,es6/* parse */.Qc)(domainToCheck);
        return domainToCheck === tldtsResult.domain || domainToCheck === tldtsResult.hostname;
    }
}
var CustomValueFormatValidatorName;
(function (CustomValueFormatValidatorName) {
    CustomValueFormatValidatorName["App"] = "pipe_separated_apps";
    CustomValueFormatValidatorName["Csp"] = "csp_value";
    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 = {}));
const isValidAppNameChunk = (chunk) => {
    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;
};
const isValidAppModifierValue = (value) => {
    if (value.includes(WILDCARD)) {
        return false;
    }
    return value
        .split(DOT)
        .every((chunk) => isValidAppNameChunk(chunk));
};
const isValidMethodModifierValue = (value) => {
    return ALLOWED_METHODS.has(value);
};
const isValidStealthModifierValue = (value) => {
    return ALLOWED_STEALTH_OPTIONS.has(value);
};
const isValidPermissionsOrigin = (rawOrigin) => {
    const actualQuoteType = QuoteUtils.getStringQuoteType(rawOrigin);
    if (actualQuoteType !== QuoteType.Double) {
        return false;
    }
    const origin = QuoteUtils.removeQuotes(rawOrigin);
    try {
        new URL(origin);
    }
    catch (e) {
        return false;
    }
    return true;
};
const isValidDenyAllowModifierValue = (value) => {
    if (value.includes(WILDCARD)) {
        return false;
    }
    return DomainUtils.isValidDomainOrHostname(value);
};
const isValidDomainModifierValue = (value) => {
    return DomainUtils.isValidDomainOrHostname(value);
};
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 };
};
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 };
};
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) => {
        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}`);
    }
    if (customListValidator) {
        return customListValidator(modifierName, theList.children);
    }
    return { valid: true };
};
const validatePipeSeparatedApps = (modifier) => {
    return validateListItemsModifier(modifier, (raw) => AppListParser.parse(raw), isValidAppModifierValue);
};
const validatePipeSeparatedDenyAllowDomains = (modifier) => {
    return validateListItemsModifier(modifier, DomainListParser.parse, isValidDenyAllowModifierValue, customNoNegatedListItemsValidator);
};
const validatePipeSeparatedDomains = (modifier) => {
    return validateListItemsModifier(modifier, DomainListParser.parse, isValidDomainModifierValue);
};
const validatePipeSeparatedMethods = (modifier) => {
    return validateListItemsModifier(modifier, (raw) => MethodListParser.parse(raw), isValidMethodModifierValue, customConsistentExceptionsValidator);
};
const validatePipeSeparatedStealthOptions = (modifier) => {
    return validateListItemsModifier(modifier, (raw) => StealthOptionListParser.parse(raw), isValidStealthModifierValue, customNoNegatedListItemsValidator);
};
const validateCspValue = (modifier) => {
    const modifierName = modifier.name.value;
    if (!modifier.value?.value) {
        return getValueRequiredValidationResult(modifierName);
    }
    const policyDirectives = modifier.value.value
        .split(SEMICOLON)
        .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;
        if (!directive) {
            return invalidValueValidationResult;
        }
        if (!ALLOWED_CSP_DIRECTIVES.has(directive)) {
            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 };
};
const validatePermissionAllowlistOrigins = (allowlistChunks, directive, modifierName) => {
    const invalidOrigins = [];
    for (let i = 0; i < allowlistChunks.length; i += 1) {
        const chunk = allowlistChunks[i].trim();
        if (chunk.length === 0) {
            continue;
        }
        if (chunk.toLowerCase() === PERMISSIONS_TOKEN_SELF) {
            continue;
        }
        if (QuoteUtils.getStringQuoteType(chunk) !== QuoteType.Double) {
            return getInvalidValidationResult(
            `${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(
        `${VALIDATION_ERROR_PREFIX.INVALID_PERMISSION_ORIGINS}: '${modifierName}': '${directive}': ${originsToStr}`);
    }
    return { valid: true };
};
const validatePermissionAllowlist = (allowlist, directive, modifierName) => {
    if (allowlist === WILDCARD
        || 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);
};
const validateSinglePermission = (permission, modifierName, modifierValue) => {
    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);
};
const validatePermissions = (modifier) => {
    if (!modifier.value?.value) {
        return getValueRequiredValidationResult(modifier.name.value);
    }
    const modifierName = modifier.name.value;
    const modifierValue = modifier.value.value;
    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 };
};
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)) {
        return getInvalidValidationResult(`${VALIDATION_ERROR_PREFIX.INVALID_REFERRER_POLICY_DIRECTIVE}: '${modifierName}': '${modifierValue}'`);
    }
    return { valid: true };
};
({
    [CustomValueFormatValidatorName.App]: validatePipeSeparatedApps,
    [CustomValueFormatValidatorName.Csp]: validateCspValue,
    [CustomValueFormatValidatorName.DenyAllow]: validatePipeSeparatedDenyAllowDomains,
    [CustomValueFormatValidatorName.Domain]: validatePipeSeparatedDomains,
    [CustomValueFormatValidatorName.Method]: validatePipeSeparatedMethods,
    [CustomValueFormatValidatorName.Permissions]: validatePermissions,
    [CustomValueFormatValidatorName.ReferrerPolicy]: validateReferrerPolicy,
    [CustomValueFormatValidatorName.StealthOption]: validatePipeSeparatedStealthOptions,
});
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 = {}));
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 = {}));
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],
]);
new Map([...SPECIFIC_PLATFORM_MAP].map(([key, value]) => [value, key]));
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],
]);
const isGenericPlatform = (platform) => {
    return !!(platform & (platform - 1));
};
class CompatibilityTableBase {
    data;
    nameTransformer;
    constructor(data, nameTransformer = null) {
        this.data = data;
        this.nameTransformer = nameTransformer;
    }
    getRowStorage(name) {
        const idx = this.data.map[name];
        if (isUndefined(idx)) {
            return null;
        }
        return this.data.shared[idx];
    }
    existsAny(name) {
        const normalizedName = this.nameTransformer ? this.nameTransformer(name) : name;
        return !isUndefined(this.data.map[normalizedName]);
    }
    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(el) && (el.name === normalizedName || !!el.aliases?.includes(normalizedName));
        };
        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 (isMatch(idx)) {
                        return true;
                    }
                }
            }
            return false;
        }
        const idx = data.map[platform];
        return isMatch(idx);
    }
    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(idx) ? null : data.shared[idx];
    }
    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(idx)) {
                        result[key] = data.shared[idx];
                    }
                }
            }
            return result;
        }
        const idx = data.map[platform];
        if (isUndefined(idx)) {
            return null;
        }
        return { key: data.shared[idx] };
    }
    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;
    }
    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(idx)) {
                        return data.shared[idx];
                    }
                }
            }
            return null;
        }
        const idx = data.map[platform];
        if (isUndefined(idx)) {
            return null;
        }
        return data.shared[idx];
    }
    getRow(name) {
        const normalizedName = this.nameTransformer ? this.nameTransformer(name) : name;
        const data = this.getRowStorage(normalizedName);
        if (!data) {
            return [];
        }
        return data.shared;
    }
    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;
    }
}
const deepFreeze = (object) => {
    const propNames = Reflect.ownKeys(object);
    for (const name of propNames) {
        const value = object[name];
        if ((value && typeof value === 'object') || typeof value === 'function') {
            deepFreeze(value);
        }
    }
    return Object.freeze(object);
};
const noopModifierNameNormalizer = (name) => {
    if (name.startsWith(UNDERSCORE)) {
        if (name.split(EMPTY).every((char) => char === UNDERSCORE)) {
            return UNDERSCORE;
        }
    }
    return name;
};
class ModifiersCompatibilityTable extends CompatibilityTableBase {
    constructor(data) {
        super(data, noopModifierNameNormalizer);
    }
}
deepFreeze(modifiersCompatibilityTableData_1);
const modifiersCompatibilityTable = new ModifiersCompatibilityTable(modifiersCompatibilityTableData_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 = {}));
new Set([
    PseudoClasses$1.Contains,
    PseudoClasses$1.HasText,
    PseudoClasses$1.MinTextLength,
]);
({
    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'",
    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'",
    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',
});
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 = {}));
const resourceTypeSchema = lib/* default.nativeEnum */.ZP.nativeEnum(ResourceType);
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',
});
const getResourceTypeModifier = (resourceType, platform) => {
    const modifierName = RESOURCE_TYPE_MODIFIER_MAP[resourceType];
    if (!modifierName) {
        return null;
    }
    const modifierData = modifiersCompatibilityTable.getFirst(modifierName, platform);
    if (isNull(modifierData)) {
        return null;
    }
    return modifierData.name;
};
const ABP_RESOURCE_PREFIX = 'abp-resource:';
const ABP_RESOURCE_PREFIX_LENGTH = ABP_RESOURCE_PREFIX.length;
const redirectNameNormalizer = (name) => {
    if (name.startsWith(ABP_RESOURCE_PREFIX)) {
        return name.slice(ABP_RESOURCE_PREFIX_LENGTH);
    }
    const colonIndex = name.lastIndexOf(COLON);
    if (colonIndex !== -1 && /^\d+$/.test(name.slice(colonIndex + 1))) {
        return name.slice(0, colonIndex);
    }
    return name;
};
class RedirectsCompatibilityTable extends CompatibilityTableBase {
    constructor(data) {
        super(data, redirectNameNormalizer);
    }
    getResourceTypeModifiers(redirect, platform) {
        let redirectData = null;
        if (isString(redirect)) {
            redirectData = this.getFirst(redirect, platform);
        }
        else {
            redirectData = redirect;
        }
        const modifierNames = new Set();
        if (isNull(redirectData) || isUndefined(redirectData.resourceTypes)) {
            return modifierNames;
        }
        for (const resourceType of redirectData.resourceTypes) {
            const modifierName = getResourceTypeModifier(resourceType, platform);
            if (isNull(modifierName)) {
                continue;
            }
            modifierNames.add(modifierName);
        }
        return modifierNames;
    }
}
deepFreeze(redirectsCompatibilityTableData_1);
new RedirectsCompatibilityTable(redirectsCompatibilityTableData_1);
deepFreeze(scriptletsCompatibilityTableData_1);
const PLATFORM_SEPARATOR = '|';
const PLATFORM_NEGATION = '~';
const parseRawPlatforms = (rawPlatforms) => {
    const rawPlatformList = rawPlatforms
        .split(PLATFORM_SEPARATOR)
        .map((rawPlatform) => rawPlatform.trim());
    let result = 0;
    for (let rawPlatform of rawPlatformList) {
        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(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;
};
lib/* default.string */.ZP.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');
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;
		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;
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});
const dist_isObject = value =>
	typeof value === 'object' &&
	value !== null &&
	!(value instanceof RegExp) &&
	!(value instanceof Error) &&
	!(value instanceof Date);
const camelCaseConvert = (input, options) => {
	if (!dist_isObject(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 && dist_isObject(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) {
					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 = getDefaultExportFromCjs(camelcaseKeys);
const zodToCamelCase = (zod) => {
    return zod.transform((val) => camelCaseKeys(val));
};
const booleanSchema = lib/* default.union */.ZP.union([
    lib/* default.string */.ZP.string().transform((val) => val.trim().toLowerCase() === 'true'),
    lib/* default.boolean */.ZP.boolean(),
]);
const nonEmptyStringSchema = lib/* default.string */.ZP.string()
    .transform((val) => val.trim())
    .pipe(lib/* default.string */.ZP.string().min(1));
const baseCompatibilityDataSchema = lib/* default.object */.ZP.object({
    name: nonEmptyStringSchema,
    aliases: lib/* default.array */.ZP.array(nonEmptyStringSchema).nullable().default(null),
    description: nonEmptyStringSchema.nullable().default(null),
    docs: nonEmptyStringSchema.nullable().default(null),
    version_added: nonEmptyStringSchema.nullable().default(null),
    version_removed: nonEmptyStringSchema.nullable().default(null),
    deprecated: booleanSchema.default(false),
    deprecation_message: nonEmptyStringSchema.nullable().default(null),
    removed: booleanSchema.default(false),
    removal_message: nonEmptyStringSchema.nullable().default(null),
});
zodToCamelCase(baseCompatibilityDataSchema);
const baseRefineLogic = (data, ctx) => {
    if (data.deprecated && !data.deprecation_message) {
        ctx.addIssue({
            code: lib/* default.ZodIssueCode.custom */.ZP.ZodIssueCode.custom,
            message: 'deprecation_message is required for deprecated modifiers',
        });
    }
    if (!data.deprecated && data.deprecation_message) {
        ctx.addIssue({
            code: lib/* default.ZodIssueCode.custom */.ZP.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: lib/* default.ZodIssueCode.custom */.ZP.ZodIssueCode.custom,
            message: 'Aliases must be unique',
        });
    }
};
function isErrorWithMessage$1(error) {
    return (typeof error === 'object'
        && error !== null
        && 'message' in error
        && typeof error.message === 'string');
}
function toErrorWithMessage$1(maybeError) {
    if (isErrorWithMessage$1(maybeError)) {
        return maybeError;
    }
    try {
        return new Error(JSON.stringify(maybeError));
    }
    catch {
        return new Error(String(maybeError));
    }
}
function getErrorMessage$1(error) {
    return toErrorWithMessage$1(error).message;
}
const KNOWN_VALIDATORS = new Set([
    'domain',
    'pipe_separated_domains',
    'regexp',
    'url',
]);
zodToCamelCase(baseCompatibilityDataSchema.extend({
    conflicts: lib/* default.array */.ZP.array(nonEmptyStringSchema).nullable().default(null),
    inverse_conflicts: booleanSchema.default(false),
    assignable: booleanSchema.default(false),
    negatable: booleanSchema.default(true),
    block_only: booleanSchema.default(false),
    exception_only: booleanSchema.default(false),
    value_optional: booleanSchema.default(false),
    value_format: nonEmptyStringSchema.nullable().default(null),
}).superRefine((data, ctx) => {
    baseRefineLogic(data, ctx);
    if (data.block_only && data.exception_only) {
        ctx.addIssue({
            code: lib/* default.ZodIssueCode.custom */.ZP.ZodIssueCode.custom,
            message: 'block_only and exception_only are mutually exclusive',
        });
    }
    if (data.assignable && !data.value_format) {
        ctx.addIssue({
            code: lib/* default.ZodIssueCode.custom */.ZP.ZodIssueCode.custom,
            message: 'value_format is required for assignable modifiers',
        });
    }
    if (data.value_format) {
        const valueFormat = data.value_format.trim();
        if (KNOWN_VALIDATORS.has(valueFormat)) {
            return;
        }
        try {
            XRegExp(valueFormat);
        }
        catch (error) {
            ctx.addIssue({
                code: lib/* default.ZodIssueCode.custom */.ZP.ZodIssueCode.custom,
                message: getErrorMessage$1(error),
            });
        }
    }
}));
zodToCamelCase(baseCompatibilityDataSchema.extend({
    is_blocking: booleanSchema.default(false),
    resource_types: lib/* default.array */.ZP.array(resourceTypeSchema).default([]),
}).superRefine(baseRefineLogic));
const scriptletParameterSchema = lib/* default.object */.ZP.object({
    name: nonEmptyStringSchema,
    required: booleanSchema,
    description: nonEmptyStringSchema.nullable().default(null),
    pattern: nonEmptyStringSchema.nullable().default(null),
    default: nonEmptyStringSchema.nullable().default(null),
    debug: booleanSchema.default(false),
});
const scriptletParametersSchema = lib/* default.array */.ZP.array(scriptletParameterSchema);
zodToCamelCase(baseCompatibilityDataSchema.extend({
    parameters: scriptletParametersSchema.optional(),
}).superRefine((data, ctx) => {
    baseRefineLogic(data, ctx);
    if (!data.parameters) {
        return;
    }
    let optionalFound = false;
    for (const parameter of data.parameters) {
        if (optionalFound && parameter.required) {
            ctx.addIssue({
                code: lib/* default.ZodIssueCode.custom */.ZP.ZodIssueCode.custom,
                message: 'Required parameters must be before optional ones',
            });
        }
        if (!parameter.required) {
            optionalFound = true;
        }
    }
}));
({
    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 = {}));
new Set([
    PseudoElements.After,
    PseudoElements.Before,
]);

function __esDecorate(ctor, descriptorIn, decorators, contextIn, initializers, extraInitializers) {
    function accept(f) { if (f !== void 0 && typeof f !== "function") throw new TypeError("Function expected"); return f; }
    var kind = contextIn.kind, key = kind === "getter" ? "get" : kind === "setter" ? "set" : "value";
    var target = !descriptorIn && ctor ? contextIn["static"] ? ctor : ctor.prototype : null;
    var descriptor = descriptorIn || (target ? Object.getOwnPropertyDescriptor(target, contextIn.name) : {});
    var _, done = false;
    for (var i = decorators.length - 1; i >= 0; i--) {
        var context = {};
        for (var p in contextIn) context[p] = p === "access" ? {} : contextIn[p];
        for (var p in contextIn.access) context.access[p] = contextIn.access[p];
        context.addInitializer = function (f) { if (done) throw new TypeError("Cannot add initializers after decoration has completed"); extraInitializers.push(accept(f || null)); };
        var result = (0, decorators[i])(kind === "accessor" ? { get: descriptor.get, set: descriptor.set } : descriptor[key], context);
        if (kind === "accessor") {
            if (result === void 0) continue;
            if (result === null || typeof result !== "object") throw new TypeError("Object expected");
            if (_ = accept(result.get)) descriptor.get = _;
            if (_ = accept(result.set)) descriptor.set = _;
            if (_ = accept(result.init)) initializers.unshift(_);
        }
        else if (_ = accept(result)) {
            if (kind === "field") initializers.unshift(_);
            else descriptor[key] = _;
        }
    }
    if (target) Object.defineProperty(target, contextIn.name, descriptor);
    done = true;
}function __runInitializers(thisArg, initializers, value) {
    var useValue = arguments.length > 2;
    for (var i = 0; i < initializers.length; i++) {
        value = useValue ? initializers[i].call(thisArg, value) : initializers[i].call(thisArg);
    }
    return useValue ? value : void 0;
}

/**
 * API to store a persistent value with debounced synchronization to the specified web extension storage key.
 *
 * After the container is created, we initialize it asynchronously to get the actual value from the storage.
 * The Init method is guarded against multiple initializations to avoid unnecessary reads from the memory.
 * Get/set methods are protected from uninitialized storage to ensure that actual data is used.
 *
 * We declare the sync get/set methods to update the cached value. This allows us to use containers in accessors.
 *
 * Set method updates the cached value and schedules the save operation to the storage via a debounce function to
 * avoid unnecessary writes to the storage.
 *
 * This container saves the data to storage using the specified key to avoid collisions with other instances.
 * It helps to avoid reading the data from the storage that is not related to the current instance.
 */
class PersistentValueContainer {
    // TODO: delete after the migration to event-driven background.
    // We do not recalculate this value because the background type cannot change at runtime.
    static #IS_BACKGROUND_PERSISTENT = PersistentValueContainer.#isBackgroundPersistent();
    #api;
    #key;
    #value;
    // TODO: make required after the migration to event-driven background.
    #save;
    #isInitialized = false;
    /**
     * Creates {@link PersistentValueContainer} instance.
     * @param key The key to use for storing the data.
     * @param api Webextension storage API.
     * @param debounceMs The debounce time in milliseconds to save the data to the storage.
     * Optional. Default is 300ms.
     */
    constructor(key, api, debounceMs = 300) {
        this.#key = key;
        this.#api = api;
        /**
         * TODO: remove this condition after the migration to event-driven background.
         */
        if (!PersistentValueContainer.#IS_BACKGROUND_PERSISTENT) {
            this.#save = (0,debounce/* default */.Z)(() => {
                this.#api.set({ [this.#key]: this.#value });
            }, debounceMs);
        }
    }
    /**
     * Initializes the value.
     * @param value The initial value.
     * @returns Promise that resolves when the value is initialized.
     * @throws Error, if storage already initialized.
     */
    async init(value) {
        if (this.#isInitialized) {
            throw new Error('Storage already initialized');
        }
        if (PersistentValueContainer.#IS_BACKGROUND_PERSISTENT) {
            this.#value = value;
        }
        else {
            const storageData = await this.#api.get({
                [this.#key]: value,
            });
            // Since Value is unknown, we need to cast it to the correct type.
            this.#value = storageData[this.#key];
        }
        this.#isInitialized = true;
    }
    /**
     * Gets the value.
     * @returns The value stored by the specified key.
     * @throws Error, if storage not initialized.
     */
    get() {
        this.#checkIsInitialized();
        return this.#value;
    }
    /**
     * Sets the value.
     * @param value Value to be stored in the specified key.
     * @throws Error, if storage not initialized.
     */
    set(value) {
        this.#checkIsInitialized();
        this.#value = value;
        if (this.#save) {
            this.#save();
        }
    }
    /**
     * Checks if the storage is initialized.
     * @throws Error, if storage not initialized.
     */
    #checkIsInitialized() {
        if (!this.#isInitialized) {
            throw new Error('Storage not initialized');
        }
    }
    /**
     * TODO: remove this method after the migration to event-driven background.
     * Checks if the background script is persistent.
     * @returns True if the background script is persistent.
     */
    static #isBackgroundPersistent() {
        const manifest = browser_polyfill_default().runtime.getManifest();
        if (manifest.manifest_version === 3) {
            return false;
        }
        if (!manifest.background) {
            return true;
        }
        const background = manifest.background;
        return background.persistent ?? true;
    }
}

/**
 * API for storing persistent key-value data with debounced sync with the specified webextension storage key.
 * Webextension storage synchronization described in the {@link PersistentValueContainer} class.
 */
class ExtensionStorage {
    /**
     * API for storing persistent value with debounced sync with the specified webextension storage key.
     */
    #container;
    /**
     * Creates {@link ExtensionStorage} instance.
     * @param key The key to use for storing the data.
     * @param api Webextension storage API.
     */
    constructor(key, api) {
        this.#container = new PersistentValueContainer(key, api);
    }
    /**
     * Initializes the storage.
     * @param data The initial data.
     * @returns Promise that resolves when the storage is initialized.
     * @throws Error, if storage already initialized.
     */
    init(data) {
        return this.#container.init(data);
    }
    /**
     * Gets the value by the specified key.
     * @param key The key to use for storing the value.
     * @throws Error, if storage not initialized.
     * @returns Data stored by the specified key.
     */
    get(key) {
        return this.#container.get()[key];
    }
    /**
     * Sets the value by the specified key.
     * @param key The key to use for storing the value.
     * @param value New value.
     * @throws Error, if storage not initialized.
     */
    set(key, value) {
        const data = this.#container.get();
        data[key] = value;
        this.#container.set(data);
    }
    /**
     * Deletes the value by the specified key.
     * @param key The key to use for storing the value.
     * @throws Error, if storage not initialized.
     */
    delete(key) {
        const data = this.#container.get();
        delete data[key];
        this.#container.set(data);
    }
}

/**
 * Creates accessor decorator for the specified storage.
 *
 * @param storage The extension storage API to use.
 * @returns Accessor decorator for the specified storage.
 * @see https://github.com/tc39/proposal-decorators
 */
function createExtensionStorageDecorator(storage) {
    const fields = new Set();
    /**
     * Creates accessor decorator for the specified storage field.
     *
     * NOTE: You should not set the initial value to the accessor via assignment,
     * because decorator overwrite accessors methods and don't use private property, created on initialization.
     * Use Non-null assertion operator instead.
     * @example `@storage('foo') accessor bar!: string`;
     * @param field Storage field name.
     * @throws Error if decorator is already registered for {@link field}
     * or decorator is applied to class member different from auto accessor.
     * @returns Decorator for access to specified storage {@link field}.
     */
    return function createFieldDecorator(field) {
        // We prevent the use of multiple decorators on a single storage field,
        // because manipulating data through the accessors of multiple modules can be confusing.
        if (fields.has(field)) {
            throw new Error(`Decorator for ${String(field)} field is already registered`);
        }
        fields.add(field);
        return function fieldDecorator(_target, context) {
            if (context.kind !== 'accessor') {
                throw new Error('Class member is not auto accessor');
            }
            // we do not set init descriptor, because data will be initialized asynchronously
            return {
                get() {
                    return storage.get(field);
                },
                set(value) {
                    return storage.set(field, value);
                },
            };
        };
    };
}

/**
 * Memory storage that implements the StorageArea interface.
 */
class MemoryStorage {
    data;
    /** @inheritdoc */
    constructor(initData = {}) {
        this.data = initData;
    }
    /** @inheritdoc */
    get(keys) {
        if (keys === undefined || keys === null) {
            return Promise.resolve(this.data);
        }
        if (typeof keys === 'string') {
            return Promise.resolve({ [keys]: this.data[keys] });
        }
        if (Array.isArray(keys)) {
            return Promise.resolve(lodash_es_pick(this.data, keys));
        }
        if (typeof keys === 'object') {
            const picked = Object.keys(keys);
            this.data = lodash_es_merge(keys, this.data);
            return Promise.resolve(lodash_es_pick(this.data, picked));
        }
        return Promise.resolve({});
    }
    /** @inheritdoc */
    set(items) {
        Object.assign(this.data, items);
        return Promise.resolve();
    }
    /** @inheritdoc */
    remove(keys) {
        if (typeof keys === 'string') {
            delete this.data[keys];
        }
        else {
            keys.forEach((key) => {
                delete this.data[key];
            });
        }
        return Promise.resolve();
    }
    /** @inheritdoc */
    clear() {
        this.data = {};
        return Promise.resolve();
    }
}

/**
 * API for storing data described by {@link SessionStorageSchema} in the {@link browser.storage.session}.
 */
class ExtSessionStorage extends ExtensionStorage {
    static #DOMAIN = 'tswebextension';
    static #DEFAULT_DATA = {
        isAppStarted: false,
        configuration: undefined,
        startTimeMs: undefined,
        cosmeticsInjectedOnStartup: false,
    };
    /**
     * Creates {@link SessionStorage} instance.
     */
    constructor() {
        // Use memory storage as a fallback for old browsers.
        super(ExtSessionStorage.#DOMAIN, (browser_polyfill_default()).storage.session ?? new MemoryStorage());
    }
    /** @inheritdoc */
    init() {
        return super.init(ExtSessionStorage.#DEFAULT_DATA);
    }
}
const extSessionStorage = new ExtSessionStorage();
const sessionDecorator = createExtensionStorageDecorator(extSessionStorage);

/**
 * Top level app context storage.
 *
 * This context is needed to share data between other modules without cyclic dependencies.
 *
 * TODO (v.zhelvis) delete this context after DI is implemented.
 */
let AppContext = (() => {
    let _isAppStarted_decorators;
    let _isAppStarted_initializers = [];
    let _isAppStarted_extraInitializers = [];
    let _configuration_decorators;
    let _configuration_initializers = [];
    let _configuration_extraInitializers = [];
    let _startTimeMs_decorators;
    let _startTimeMs_initializers = [];
    let _startTimeMs_extraInitializers = [];
    let _cosmeticsInjectedOnStartup_decorators;
    let _cosmeticsInjectedOnStartup_initializers = [];
    let _cosmeticsInjectedOnStartup_extraInitializers = [];
    return class AppContext {
        static {
            const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(null) : void 0;
            _isAppStarted_decorators = [sessionDecorator("isAppStarted" /* SessionStorageKey.IsAppStarted */)];
            _configuration_decorators = [sessionDecorator("configuration" /* SessionStorageKey.Configuration */)];
            _startTimeMs_decorators = [sessionDecorator("startTimeMs" /* SessionStorageKey.StartTimeMs */)];
            _cosmeticsInjectedOnStartup_decorators = [sessionDecorator("cosmeticsInjectedOnStartup" /* SessionStorageKey.CosmeticsInjectedOnStartup */)];
            __esDecorate(this, null, _isAppStarted_decorators, { kind: "accessor", name: "isAppStarted", static: false, private: false, access: { has: obj => "isAppStarted" in obj, get: obj => obj.isAppStarted, set: (obj, value) => { obj.isAppStarted = value; } }, metadata: _metadata }, _isAppStarted_initializers, _isAppStarted_extraInitializers);
            __esDecorate(this, null, _configuration_decorators, { kind: "accessor", name: "configuration", static: false, private: false, access: { has: obj => "configuration" in obj, get: obj => obj.configuration, set: (obj, value) => { obj.configuration = value; } }, metadata: _metadata }, _configuration_initializers, _configuration_extraInitializers);
            __esDecorate(this, null, _startTimeMs_decorators, { kind: "accessor", name: "startTimeMs", static: false, private: false, access: { has: obj => "startTimeMs" in obj, get: obj => obj.startTimeMs, set: (obj, value) => { obj.startTimeMs = value; } }, metadata: _metadata }, _startTimeMs_initializers, _startTimeMs_extraInitializers);
            __esDecorate(this, null, _cosmeticsInjectedOnStartup_decorators, { kind: "accessor", name: "cosmeticsInjectedOnStartup", static: false, private: false, access: { has: obj => "cosmeticsInjectedOnStartup" in obj, get: obj => obj.cosmeticsInjectedOnStartup, set: (obj, value) => { obj.cosmeticsInjectedOnStartup = value; } }, metadata: _metadata }, _cosmeticsInjectedOnStartup_initializers, _cosmeticsInjectedOnStartup_extraInitializers);
            if (_metadata) Object.defineProperty(this, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
        }
        /**
         * Is storage initialized.
         * This flag is used to prevent access to persistent storage data on
         * request from content script, before app is started.
         */
        isStorageInitialized = false;
        #isAppStarted_accessor_storage = __runInitializers(this, _isAppStarted_initializers, void 0);
        /**
         * Is app started.
         */
        get isAppStarted() { return this.#isAppStarted_accessor_storage; }
        set isAppStarted(value) { this.#isAppStarted_accessor_storage = value; }
        #configuration_accessor_storage = (__runInitializers(this, _isAppStarted_extraInitializers), __runInitializers(this, _configuration_initializers, void 0));
        /**
         * MV2 ConfigurationMV2 excludes heavyweight fields with rules.
         */
        get configuration() { return this.#configuration_accessor_storage; }
        set configuration(value) { this.#configuration_accessor_storage = value; }
        #startTimeMs_accessor_storage = (__runInitializers(this, _configuration_extraInitializers), __runInitializers(this, _startTimeMs_initializers, void 0));
        /**
         * Start time of the app.
         */
        get startTimeMs() { return this.#startTimeMs_accessor_storage; }
        set startTimeMs(value) { this.#startTimeMs_accessor_storage = value; }
        #cosmeticsInjectedOnStartup_accessor_storage = (__runInitializers(this, _startTimeMs_extraInitializers), __runInitializers(this, _cosmeticsInjectedOnStartup_initializers, void 0));
        /**
         * Flag that indicates that cosmetics were injected on startup.
         */
        get cosmeticsInjectedOnStartup() { return this.#cosmeticsInjectedOnStartup_accessor_storage; }
        set cosmeticsInjectedOnStartup(value) { this.#cosmeticsInjectedOnStartup_accessor_storage = value; }
        constructor() {
            __runInitializers(this, _cosmeticsInjectedOnStartup_extraInitializers);
        }
    };
})();
const appContext = new AppContext();

/**
 * Taken from:
 * {@link https://github.com/seanl-adg/InlineResourceLiteral/blob/master/index.js#L136}
 * {@link https://github.com/joliss/js-string-escape/blob/master/index.js}.
 */
const reJsEscape = /["'\\\n\r\u2028\u2029]/g;
const escapeJs = (match) => {
    switch (match) {
        case '"':
        case "'":
        case '\\':
            return `\\${match}`;
        case '\n':
            /**
             * Line continuation character for ease of reading inlined resource.
             */
            return '\\n\\\n';
        case '\r':
            /**
             * Carriage returns won't have any semantic meaning in JS.
             */
            return '';
        case '\u2028':
            return '\\u2028';
        case '\u2029':
            return '\\u2029';
        default:
            return match;
    }
};
/**
 * Builds script to inject in a safe way.
 *
 * @see {@link LocalScriptRulesService} for details about script source.
 * @param scriptText Script text.
 * @param startTimeMs App start time in milliseconds.
 * @returns Script to inject.
 * @throws Error if start time is not defined.
 */
const buildScriptText = (scriptText, startTimeMs) => {
    if (!startTimeMs) {
        throw new Error('Start time is not defined');
    }
    /**
     * We use changing variable name because global properties can be modified across isolated worlds of extension
     * content page and tab page.
     *
     * Issue: @see {@link https://bugs.chromium.org/p/project-zero/issues/detail?id=1225&desc=6}.
     */
    const variableName = `scriptExecuted${startTimeMs}`;
    /**
     * Executes scripts in a scope of the page, but the `window` fields are in
     * an isolated scope, e.g. `window.${variableName}` will only be visible in
     * this scope of the script, but not in the original scope of the page.
     * In order to prevent multiple script execution checks if script was already executed.
     *
     * Sometimes in Firefox when content-filtering is applied to the page race condition happens.
     * This causes an issue when the page doesn't have its document.head or document.documentElement at the moment of
     * injection. So script waits for them. But if a quantity of frame-requests reaches FRAME_REQUESTS_LIMIT then
     * script stops waiting with the error.
     * Description of the issue: @see {@link https://github.com/AdguardTeam/AdguardBrowserExtension/issues/1004}.
     *
     * Injecting content-script, which appends a script tag, breaks Firefox's pretty printer for xml documents.
     * Description of the issue: @see {@link https://github.com/AdguardTeam/AdguardBrowserExtension/issues/2194}.
     *
     * CSP may prevent script execution in Firefox if script.textContent is used.
     * That's why script.src is used as a primary way, and script.textContent is used as a fallback.
     * Description of the issue: @see {@link https://github.com/AdguardTeam/AdguardBrowserExtension/issues/1733}.
     */
    return `(function() {\
                if (window.${variableName} || document instanceof XMLDocument) {\
                    return;\
                }\
                var script = document.createElement("script");\
                var preparedScriptText = "${scriptText.replace(reJsEscape, escapeJs)}";\
                var blob;\
                var url;\
                try {\
                    blob = new Blob([preparedScriptText], { type: "text/javascript; charset=utf-8" });\
                    url = URL.createObjectURL(blob);\
                    script.src = url;\
                } catch (e) {\
                    script.setAttribute("type", "text/javascript");\
                    script.textContent = preparedScriptText;\
                }\
                var FRAME_REQUESTS_LIMIT = 500;\
                var frameRequests = 0;\
                function waitParent () {\
                    frameRequests += 1;\
                    var parent = document.head || document.documentElement;\
                    if (parent) {\
                        try {\
                            parent.appendChild(script);\
                            if (url) {\
                                URL.revokeObjectURL(url);\
                            }\
                            parent.removeChild(script);\
                        } catch (e) {\
                        } finally {\
                            window.${variableName} = true;\
                            return true;\
                        }\
                    }\
                    if(frameRequests < FRAME_REQUESTS_LIMIT) {\
                        requestAnimationFrame(waitParent);\
                    } else {\
                        console.log("AdGuard: document.head or document.documentElement were unavailable too long");\
                    }\
                }\
                waitParent();\
            })()`;
};

/**
 * By the rules of AMO we cannot use remote scripts (and our JS rules can be counted as such).
 * Because of that we use the following approach (that was accepted by AMO reviewers):
 *
 * 1. We pre-build JS rules from AdGuard filters into the JSON file.
 * 2. At runtime we check every JS rule if it's included into JSON.
 *    If it is included we allow this rule to work since it's pre-built. Other rules are discarded.
 * 3. We also allow "User rules" to work since those rules are added manually by the user.
 *    This way filters maintainers can test new rules before including them in the filters.
 */
class LocalScriptRulesService {
    /**
     * If {@link setLocalScriptRules} was called (for example, it should be
     * called in Firefox AMO), this set will contain a list of prebuilt JSON
     * with scriptlets and JS rules allowed to run.
     * Otherwise it will remain undefined.
     * Key is the scriptlet call (e.g.: `example.com#%#//scriptlet('foo')` it will be `#%#//scriptlet('foo')`)
     * and the value is the list of domains from the rule.
     */
    localScripts;
    /**
     * Saves local script rules to object.
     *
     * @param json JSON object with pre-build JS rules.
     */
    setLocalScriptRules(json) {
        this.localScripts = new Map(Object.entries(json.rules));
    }
    /**
     * Checks if ruleText is in the pre-built JSON with JS rules.
     *
     * @param rule Rule text.
     *
     * @returns True, if rule is local, else returns false.
     */
    isLocal(rule) {
        if (this.localScripts === undefined) {
            return true;
        }
        // Key can be checked quickly
        const scriptDomains = this.localScripts.get(rule.getContent());
        if (scriptDomains === undefined) {
            return false;
        }
        return lodash_es_some(scriptDomains, {
            permittedDomains: rule.getPermittedDomains() ?? [],
            restrictedDomains: rule.getRestrictedDomains() ?? [],
        });
    }
}
const localScriptRulesService = new LocalScriptRulesService();

/**
 * Finds header object by header name (case-insensitive).
 *
 * @param headers Headers collection.
 * @param headerName Header name.
 * @returns Found header, or null if not found.
 */
function findHeaderByName(headers, headerName) {
    for (let i = 0; i < headers.length; i += 1) {
        const header = headers[i];
        if (header.name.toLowerCase() === headerName.toLowerCase()) {
            return header;
        }
    }
    return null;
}
/**
 * TODO: Make function pure (don't modify headers, return new object instead)
 * Removes header from headers by name.
 *
 * @param headers Headers collection.
 * @param headerName Header name.
 * @returns True if headers were removed.
 */
function removeHeader(headers, headerName) {
    let removed = false;
    for (let i = headers.length - 1; i >= 0; i -= 1) {
        const header = headers[i];
        if (header.name.toLowerCase() === headerName.toLowerCase()) {
            headers.splice(i, 1);
            removed = true;
        }
    }
    return removed;
}

// Disable jest coverage for this file, because it will insert
// line comments, and code to count lines covered by tests, for example:
// /* istanbul ignore next */
// cov_uqm40oh03().f[0]++;
// cov_uqm40oh03().s[2]++;
// And we cannot test these strings correctly, because the names of these
// functions with counters are generated at runtime
/* istanbul ignore file */
/**
 * This module applies stealth actions in page context.
 */
class StealthHelper {
    /**
     * Sends a Global Privacy Control DOM signal.
     */
    static setDomSignal() {
        try {
            if ('globalPrivacyControl' in Navigator.prototype) {
                return;
            }
            Object.defineProperty(Navigator.prototype, 'globalPrivacyControl', {
                get: () => true,
                configurable: true,
                enumerable: true,
            });
        }
        catch (ex) {
            // Ignore
        }
    }
    /**
     * Hides document referrer.
     */
    static hideDocumentReferrer() {
        const origDescriptor = Object.getOwnPropertyDescriptor(Document.prototype, 'referrer');
        if (!origDescriptor || !origDescriptor.get || !origDescriptor.configurable) {
            return;
        }
        const returnEmptyReferrerFunc = () => '';
        // Protect getter from native code check
        returnEmptyReferrerFunc.toString = origDescriptor.get.toString.bind(origDescriptor.get);
        Object.defineProperty(Document.prototype, 'referrer', {
            get: returnEmptyReferrerFunc,
        });
    }
}

/**
 * Stealth action bitwise masks used on the background page and on the filtering log page.
 */
var StealthActions;
(function (StealthActions) {
    StealthActions[StealthActions["None"] = 0] = "None";
    StealthActions[StealthActions["HideReferrer"] = 1] = "HideReferrer";
    StealthActions[StealthActions["HideSearchQueries"] = 2] = "HideSearchQueries";
    StealthActions[StealthActions["BlockChromeClientData"] = 4] = "BlockChromeClientData";
    StealthActions[StealthActions["SendDoNotTrack"] = 8] = "SendDoNotTrack";
    // TODO check where this enums are used, and add comments
    StealthActions[StealthActions["FirstPartyCookies"] = 16] = "FirstPartyCookies";
    StealthActions[StealthActions["ThirdPartyCookies"] = 32] = "ThirdPartyCookies";
})(StealthActions || (StealthActions = {}));

/**
 * Stealth service module.
 */
class StealthService {
    /**
     * Headers.
     */
    static HEADERS = {
        REFERRER: 'Referer',
        X_CLIENT_DATA: 'X-Client-Data',
        DO_NOT_TRACK: 'DNT',
    };
    /**
     * Header values.
     */
    static HEADER_VALUES = {
        DO_NOT_TRACK: {
            name: 'DNT',
            value: '1',
        },
        GLOBAL_PRIVACY_CONTROL: {
            name: 'Sec-GPC',
            value: '1',
        },
    };
    /**
     * Search engines regexps.
     */
    static SEARCH_ENGINES = [
        /https?:\/\/(www\.)?google\./i,
        /https?:\/\/(www\.)?yandex\./i,
        /https?:\/\/(www\.)?bing\./i,
        /https?:\/\/(www\.)?yahoo\./i,
        /https?:\/\/(www\.)?go\.mail\.ru/i,
        /https?:\/\/(www\.)?ask\.com/i,
        /https?:\/\/(www\.)?aol\.com/i,
        /https?:\/\/(www\.)?baidu\.com/i,
        /https?:\/\/(www\.)?seznam\.cz/i,
    ];
    /**
     * Filtering logger.
     */
    filteringLog;
    /**
     * App context.
     */
    appContext;
    /**
     * Configuration.
     *
     * @returns App Stealth configuration or undefined.
     */
    get config() {
        return this.appContext.configuration?.settings.stealth;
    }
    /**
     * Constructor.
     *
     * @param appContext App context.
     * @param filteringLog Filtering log.
     */
    constructor(appContext, filteringLog) {
        this.appContext = appContext;
        this.filteringLog = filteringLog;
    }
    /**
     * Returns synthetic set of rules matching the specified request.
     *
     * @returns Strings of cookie rules.
     */
    // TODO (David): Change to AST-based rule creation.
    getCookieRulesTexts() {
        const result = [];
        if (this.config?.selfDestructFirstPartyCookies) {
            result.push(StealthService.generateCookieRuleText(this.config.selfDestructFirstPartyCookiesTime));
        }
        if (this.config?.selfDestructThirdPartyCookies) {
            result.push(StealthService.generateCookieRuleText(this.config.selfDestructThirdPartyCookiesTime, true));
        }
        return result;
    }
    /**
     * Applies stealth actions to request headers.
     *
     * @param context Request context.
     * @returns Stealth actions bitmask.
     */
    processRequestHeaders(context) {
        let stealthActions = StealthActions.None;
        if (!this.config) {
            return stealthActions;
        }
        const { requestUrl, requestHeaders, matchingResult, requestType, tabId, eventId, referrerUrl, contentType, timestamp, } = context;
        if (!requestHeaders || matchingResult?.documentRule) {
            return stealthActions;
        }
        /**
         * Regarding stealth rule modifier, stealth options can be disabled on two occasions:
         * - stealth modifier does not have specific values, thus disabling stealth entirely
         * - stealth modifier has specific options to disable.
         */
        const stealthDisablingRule = matchingResult?.getStealthRule();
        if (stealthDisablingRule) {
            // $stealth rule without options is not being published to the filtering log
            // to conform with desktop application behavior
            return stealthActions;
        }
        // Collect applied allowlist rules in a set to only publish
        // one filtering event per applied allowlist rule
        const appliedAllowlistRules = new Set();
        // Remove referrer for third-party requests
        if (this.config?.hideReferrer) {
            const disablingRule = matchingResult?.getStealthRule(es/* StealthOptionName.HideReferrer */.Mn.HideReferrer);
            if (disablingRule) {
                appliedAllowlistRules.add(disablingRule);
            }
            else if (StealthService.removeReferrer(requestHeaders, requestUrl)) {
                stealthActions |= StealthActions.HideReferrer;
            }
        }
        // Hide referrer in case of search engine is referrer
        const isMainFrame = requestType === RequestType.Document;
        if (isMainFrame && this.config?.hideSearchQueries) {
            const disablingRule = matchingResult?.getStealthRule(es/* StealthOptionName.HideSearchQueries */.Mn.HideSearchQueries);
            if (disablingRule) {
                appliedAllowlistRules.add(disablingRule);
            }
            else if (StealthService.hideSearchQueries(requestHeaders, requestUrl)) {
                stealthActions |= StealthActions.HideSearchQueries;
            }
        }
        // Remove X-Client-Data header
        if (this.config?.blockChromeClientData) {
            const disablingRule = matchingResult?.getStealthRule(es/* StealthOptionName.XClientData */.Mn.XClientData);
            if (disablingRule) {
                appliedAllowlistRules.add(disablingRule);
            }
            else if (StealthService.removeXClientData(requestHeaders)) {
                stealthActions |= StealthActions.BlockChromeClientData;
            }
        }
        // Adding Do-Not-Track (DNT) header
        if (this.config?.sendDoNotTrack) {
            const disablingRule = matchingResult?.getStealthRule(es/* StealthOptionName.DoNotTrack */.Mn.DoNotTrack);
            if (disablingRule) {
                appliedAllowlistRules.add(disablingRule);
            }
            else if (StealthService.sendDoNotTrack(requestHeaders)) {
                stealthActions |= StealthActions.SendDoNotTrack;
            }
        }
        if (appliedAllowlistRules.size > 0) {
            this.filteringLog.publishEvent({
                type: FilteringEventType.StealthAllowlistAction,
                data: {
                    tabId,
                    eventId,
                    rules: Array.from(appliedAllowlistRules).map((rule) => ({
                        filterId: rule.getFilterListId(),
                        ruleIndex: rule.getIndex(),
                        isAllowlist: rule.isAllowlist(),
                        isImportant: rule.isOptionEnabled(es/* NetworkRuleOption.Important */.SJ.Important),
                        isDocumentLevel: rule.isDocumentLevelAllowlistRule(),
                        isCsp: rule.isOptionEnabled(es/* NetworkRuleOption.Csp */.SJ.Csp),
                        isCookie: rule.isOptionEnabled(es/* NetworkRuleOption.Cookie */.SJ.Cookie),
                        advancedModifier: rule.getAdvancedModifierValue(),
                    })),
                    requestUrl,
                    frameUrl: referrerUrl,
                    requestType: contentType,
                    timestamp,
                },
            });
        }
        if (stealthActions > 0) {
            this.filteringLog.publishEvent({
                type: FilteringEventType.StealthAction,
                data: {
                    tabId,
                    eventId,
                    stealthActions,
                },
            });
        }
        return stealthActions;
    }
    /**
     * Removes referrer from request headers.
     *
     * @param requestHeaders Request headers.
     * @param requestUrl Request URL.
     * @returns True if referrer was removed.
     */
    static removeReferrer(requestHeaders, requestUrl) {
        const refHeader = findHeaderByName$1(requestHeaders, StealthService.HEADERS.REFERRER);
        if (refHeader
            && refHeader.value
            && isThirdPartyRequest(requestUrl, refHeader.value)) {
            refHeader.value = StealthService.createMockRefHeaderUrl(requestUrl);
            return true;
        }
        return false;
    }
    /**
     * Hides search queries from referrer.
     *
     * @param requestHeaders Request headers.
     * @param requestUrl Request URL.
     * @returns True if search queries were hidden.
     */
    static hideSearchQueries(requestHeaders, requestUrl) {
        const refHeader = findHeaderByName$1(requestHeaders, StealthService.HEADERS.REFERRER);
        if (refHeader
            && refHeader.value
            && StealthService.isSearchEngine(refHeader.value)
            && isThirdPartyRequest(requestUrl, refHeader.value)) {
            refHeader.value = StealthService.createMockRefHeaderUrl(requestUrl);
            return true;
        }
        return false;
    }
    /**
     * Removes X-Client-Data header.
     *
     * @param requestHeaders Request headers.
     * @returns True if X-Client-Data header was removed.
     */
    static removeXClientData(requestHeaders) {
        return removeHeader(requestHeaders, StealthService.HEADERS.X_CLIENT_DATA);
    }
    /**
     * Adds Do-Not-Track (DNT) and Global Privacy Control (GPC) headers.
     *
     * @param requestHeaders Request headers.
     * @returns True if DNT and GPC headers were added.
     */
    static sendDoNotTrack(requestHeaders) {
        requestHeaders.push(StealthService.HEADER_VALUES.DO_NOT_TRACK);
        requestHeaders.push(StealthService.HEADER_VALUES.GLOBAL_PRIVACY_CONTROL);
        return true;
    }
    /**
     * Returns set dom signal script if sendDoNotTrack enabled, otherwise empty string.
     *
     * @returns Dom signal script.
     */
    getSetDomSignalScript() {
        if (this.config?.sendDoNotTrack) {
            return `;(function ${StealthHelper.setDomSignal.toString()})();`;
        }
        return '';
    }
    /**
     * Returns hide document referrer script if hideReferrer enabled, otherwise empty string.
     *
     * @returns Hide referrer script.
     */
    getHideDocumentReferrerScript() {
        if (this.config?.hideReferrer) {
            return `;(function ${StealthHelper.hideDocumentReferrer.toString()})();`;
        }
        return '';
    }
    /**
     * Generates rule removing cookies.
     *
     * @param maxAgeMinutes Cookie maxAge in minutes.
     * @param isThirdParty Flag for generating third-party rule texts.
     * @returns Rule text.
     */
    static generateCookieRuleText(maxAgeMinutes, isThirdParty = false) {
        const maxAgeOption = maxAgeMinutes > 0 ? `;maxAge=${maxAgeMinutes * 60}` : '';
        const thirdPartyOption = isThirdParty ? ',third-party' : '';
        const ruleText = `$cookie=/.+/${maxAgeOption}${thirdPartyOption}`;
        return ruleText;
    }
    /**
     * Crops url path.
     *
     * @param url URL.
     * @returns URL without path.
     */
    static createMockRefHeaderUrl(url) {
        const host = getHost(url);
        return `${(url.indexOf('https') === 0 ? 'https://' : 'http://') + host}/`;
    }
    /**
     * Is url search engine.
     *
     * @param url Url for check.
     * @returns True if url is search engine.
     */
    static isSearchEngine(url) {
        return StealthService.SEARCH_ENGINES.some((searchEngineRegex) => searchEngineRegex.test(url));
    }
}

/**
 * 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(error) {
    return toErrorWithMessage(error).message;
}

/**
 * Stealth api implementation.
 */
class StealthApi {
    /**
     * Privacy permission for block webrtc stealth setting.
     */
    static PRIVACY_PERMISSIONS = {
        permissions: ['privacy'],
    };
    /**
     * Stealth service.
     */
    stealthService;
    /**
     * Filtering log.
     */
    filteringLog;
    /**
     * App context.
     */
    appContext;
    /**
     * Stealth configuration.
     *
     * @returns App Stealth configuration or undefined.
     */
    get configuration() {
        return this.appContext.configuration?.settings.stealth;
    }
    /**
     * Gets app stealth mode status.
     *
     * @returns True if stealth mode is enabled, otherwise returns false.
     */
    get isStealthModeEnabled() {
        return Boolean(this.appContext.configuration?.settings.stealthModeEnabled);
    }
    /**
     * Gets app filtering status.
     *
     * TODO: This method is duplicated in {@link EngineApi}. Consider moving it to {@link appContext}
     *  itself (DRY). But appContext supposed to be deleted (v.zhelvis).
     *
     * @returns True if filtering is enabled, otherwise returns false.
     */
    get isFilteringEnabled() {
        return Boolean(this.appContext.configuration?.settings.filteringEnabled);
    }
    /**
     * Checks if both stealth mode and filtering are enabled.
     *
     * @returns True if stealth mode and filtering are enabled.
     */
    get isStealthAllowed() {
        return this.isStealthModeEnabled && this.isFilteringEnabled;
    }
    /**
     * Stealth API constructor.
     *
     * @param appContextInstance App context.
     * @param filteringLog Filtering log.
     */
    constructor(appContextInstance, filteringLog) {
        this.appContext = appContextInstance;
        this.filteringLog = filteringLog;
        this.stealthService = new StealthService(this.appContext, this.filteringLog);
    }
    /**
     * Requires privacy permissions and updates browser privacy.network
     * settings depending on blocking WebRTC or not.
     */
    async updateWebRtcPrivacyPermissions() {
        if (!StealthApi.canBlockWebRTC()) {
            return;
        }
        try {
            const isPermissionsGranted = await browser_polyfill_default().permissions.contains(StealthApi.PRIVACY_PERMISSIONS);
            if (isPermissionsGranted) {
                await this.handleBlockWebRTC();
            }
        }
        catch (e) {
            logger.error(getErrorMessage(e));
        }
    }
    /**
     * Returns rule list with stealth mode rules.
     *
     * @returns String rule list or null.
     */
    getStealthModeRuleList() {
        if (!this.isStealthAllowed) {
            return null;
        }
        // TODO (David): Change to AST generation
        const rulesTexts = this.stealthService.getCookieRulesTexts().join('\n');
        return new es/* BufferRuleList */.bm(es/* STEALTH_MODE_FILTER_ID */.AG, es/* FilterListPreprocessor.preprocess */.HV.preprocess(rulesTexts).filterList, false, false);
    }
    /**
     * Stealth api onBeforeRequest handler.
     *
     * @param context Request context.
     *
     * @returns True if the headers have been changed.
     */
    onBeforeSendHeaders(context) {
        if (!context) {
            return false;
        }
        if (!this.isStealthAllowed) {
            return false;
        }
        const stealthActions = this.stealthService.processRequestHeaders(context);
        return stealthActions !== StealthActions.None;
    }
    /**
     * Returns stealth script to apply to the frame.
     *
     * TODO this should be expanded for v2.3 to accommodate for $stealth values feature,
     * i.e checking specific stealth options (dnt and referrer)
     * https://github.com/AdguardTeam/tsurlfilter/issues/100.
     *
     * @param mainFrameRule Main frame rule to use if no matching result provided.
     * @param matchingResult Matching result.
     * @returns Stealth script.
     */
    getStealthScript(mainFrameRule, matchingResult) {
        if (!this.isStealthAllowed) {
            return '';
        }
        let documentRule = null;
        // Matching result may be missing in case of dynamically created frames without url
        if (matchingResult) {
            documentRule = matchingResult.documentRule || matchingResult.getStealthRule();
        }
        else {
            documentRule = mainFrameRule;
        }
        if (documentRule) {
            return '';
        }
        let stealthScript = '';
        if (!matchingResult?.getStealthRule(es/* StealthOptionName.DoNotTrack */.Mn.DoNotTrack)) {
            stealthScript += this.getSetDomSignalScript();
        }
        if (!matchingResult?.getStealthRule(es/* StealthOptionName.HideReferrer */.Mn.HideReferrer)) {
            stealthScript += this.getHideDocumentReferrerScript();
        }
        return stealthScript;
    }
    /**
     * Returns set dom signal script if sendDoNotTrack enabled, otherwise empty string.
     *
     * @returns Dom signal script.
     */
    getSetDomSignalScript() {
        return this.isStealthAllowed
            ? this.stealthService.getSetDomSignalScript()
            : '';
    }
    /**
     * Returns hide document referrer script if hideDocumentReferrer enabled, otherwise empty string.
     *
     * @returns Hide referrer script.
     */
    getHideDocumentReferrerScript() {
        return this.isStealthAllowed
            ? this.stealthService.getHideDocumentReferrerScript()
            : '';
    }
    /**
     * Updates browser privacy.network settings depending on blocking WebRTC or not.
     */
    async handleBlockWebRTC() {
        if (!this.configuration) {
            return;
        }
        const isWebRTCDisabled = this.configuration.blockWebRTC && this.isStealthAllowed;
        try {
            if (isWebRTCDisabled) {
                await browser_polyfill_default().privacy.network.webRTCIPHandlingPolicy.set({
                    value: 'disable_non_proxied_udp',
                    scope: 'regular',
                });
            }
            else {
                await browser_polyfill_default().privacy.network.webRTCIPHandlingPolicy.clear({
                    scope: 'regular',
                });
            }
        }
        catch (e) {
            logger.error(`Error updating privacy.network settings: ${getErrorMessage(e)}`);
        }
        // privacy.network.peerConnectionEnabled is currently only supported in Firefox
        if (typeof (browser_polyfill_default()).privacy.network.peerConnectionEnabled === 'object') {
            try {
                if (isWebRTCDisabled) {
                    await browser_polyfill_default().privacy.network.peerConnectionEnabled.set({
                        value: false,
                        scope: 'regular',
                    });
                }
                else {
                    await browser_polyfill_default().privacy.network.peerConnectionEnabled.clear({
                        scope: 'regular',
                    });
                }
            }
            catch (e) {
                logger.error(`Error updating privacy.network settings: ${getErrorMessage(e)}`);
            }
        }
    }
    /**
     * // TODO consider deprecating this method as edge browser is built on chromium now.
     * Checks if there is browser.privacy permission is granted.
     *
     * @returns True if there is browser.privacy permission.
     */
    static canBlockWebRTC() {
        // Edge doesn't support privacy api
        // https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/privacy
        return !!(browser_polyfill_default()).privacy;
    }
}
const stealthApi = new StealthApi(appContext, defaultFilteringLog);

/**
 * Checks if iframe has same source as main frame or if src is about:blank, javascript:, etc.
 * We don't include frames with 'src=data:' because Chrome and Firefox
 * do not allow data to be injected into frames with this type of src,
 * this bug is reported here https://bugs.chromium.org/p/chromium/issues/detail?id=55084.
 *
 * @param frameUrl Frame url.
 * @param frameId Unique id of frame in the tab.
 * @param mainFrameUrl Url of tab where iframe exists.
 * @returns True if frame without src, else returns false.
 */
function isLocalFrame(frameUrl, frameId, mainFrameUrl) {
    return frameId !== MAIN_FRAME_ID
        && (frameUrl === mainFrameUrl
            || isEmptySrcFrame(frameUrl)
            // eslint-disable-next-line no-script-url
            || frameUrl.indexOf('javascript:') > -1);
}

/**
 * Creates match query for frame based on content script data and background tab context.
 * Used in {@link CosmeticApi} and {@link CookieFiltering} to match rules for content scripts.
 * @param frameUrl Frame url. Received from content script.
 * @param frameId Frame id. Received from content script.
 * @param tabContext Tab context. Received from background script.
 * @returns Match query for {@link EngineApi}.
 * @throws Error if tab context url is not defined.
 */
function createFrameMatchQuery(frameUrl, frameId, tabContext) {
    const { info } = tabContext;
    if (!info.url) {
        throw new Error('Tab url is required');
    }
    const mainFrameUrl = info.url;
    const isLocal = isLocalFrame(frameUrl, frameId, mainFrameUrl);
    const requestUrl = isLocal ? mainFrameUrl : frameUrl;
    let requestType;
    // if frame is Local, then apply main frame rules.
    if (isLocal) {
        requestType = RequestType.Document;
    }
    else if (frameId === MAIN_FRAME_ID) {
        requestType = RequestType.Document;
    }
    else {
        requestType = RequestType.SubDocument;
    }
    return {
        requestUrl,
        frameUrl: requestUrl,
        requestType,
        frameRule: tabContext.mainFrameRule,
    };
}

/**
 * CosmeticApiCommon contains common logic about building css for hiding elements.
 */
class CosmeticApiCommon {
    static LINE_BREAK = '\r\n';
    /**
     * Number of selectors in grouped selector list.
     */
    static CSS_SELECTORS_PER_LINE = 50;
    /**
     * Builds stylesheets from rules.
     * If `groupElemhideSelectors` is set,
     * element hiding selector are to be combined into selector lists of {@link CosmeticApi.CSS_SELECTORS_PER_LINE}.
     *
     * @param elemhideRules List of elemhide rules.
     * @param injectRules List of inject css rules.
     * @param groupElemhideSelectors Flag for elemhide selectors grouping.
     *
     * @returns List of stylesheet expressions.
     */
    static buildStyleSheets(elemhideRules, injectRules, groupElemhideSelectors) {
        const styles = [];
        const elemHideStyles = CosmeticApiCommon.buildElemhideStyles(elemhideRules, groupElemhideSelectors);
        if (elemHideStyles.length > 0) {
            if (groupElemhideSelectors) {
                styles.push(elemHideStyles.join(CosmeticApiCommon.LINE_BREAK));
            }
            else {
                styles.push(...elemHideStyles);
            }
        }
        const cssStyles = injectRules.map((x) => x.getContent());
        if (cssStyles.length > 0) {
            if (groupElemhideSelectors) {
                styles.push(cssStyles.join(CosmeticApiCommon.LINE_BREAK));
            }
            else {
                styles.push(...cssStyles);
            }
        }
        return styles;
    }
    /**
     * Builds element hiding stylesheet from rules.
     * If `groupElemhideSelectors` is set,
     * selector are to be combined into selector lists of {@link CosmeticApi.CSS_SELECTORS_PER_LINE}.
     *
     * @param elemhideRules List of elemhide rules.
     * @param groupElemhideSelectors Flag for elemhide selectors grouping.
     *
     * @returns Array of styles.
     */
    static buildElemhideStyles(elemhideRules, groupElemhideSelectors) {
        // TODO: refactor constants as ELEMHIDE_CSS_STYLE and ELEMHIDE_HIT_START are duplicates partly
        const ELEMHIDE_CSS_STYLE = ' { display: none !important; }';
        const elemhideSelectors = [];
        for (const selector of elemhideRules) {
            elemhideSelectors.push(selector.getContent());
        }
        // if selector should not be grouped,
        // add element hiding style to each of them
        if (!groupElemhideSelectors) {
            return elemhideSelectors.map((selector) => {
                return `${selector}${ELEMHIDE_CSS_STYLE}`;
            });
        }
        // otherwise selectors should be grouped into selector lists
        const elemhideStyles = [];
        for (let i = 0; i < elemhideSelectors.length; i += CosmeticApiCommon.CSS_SELECTORS_PER_LINE) {
            const selectorList = elemhideSelectors
                .slice(i, i + CosmeticApiCommon.CSS_SELECTORS_PER_LINE)
                .join(', ');
            elemhideStyles.push(`${selectorList}${ELEMHIDE_CSS_STYLE}`);
        }
        return elemhideStyles;
    }
}

/* eslint-disable jsdoc/require-returns */
/**
 * Cosmetic api class.
 * Used to prepare and inject javascript and css into pages.
 */
class CosmeticApi extends CosmeticApiCommon {
    static ELEMHIDE_HIT_START = " { display: none !important; content: 'adguard";
    static INJECT_HIT_START = " content: 'adguard";
    static HIT_SEP = encodeURIComponent(';');
    static HIT_END = "' !important; }";
    // Timeout for cosmetic injection retry on failure.
    static INJECTION_RETRY_TIMEOUT_MS = 10;
    // Max number of tries to inject cosmetic rules.
    static INJECTION_MAX_TRIES = 100;
    /**
     * Applies scripts from a cosmetic result. It is possible inject a script
     * only once, because after the first inject, we set a flag in an isolated
     * copy of the window and all next calls to `buildScriptText` will return
     * nothing.
     *
     * @param scriptText Script text.
     * @param tabId Tab id.
     * @param frameId Frame id.
     * @see {@link buildScriptText} for details about multiple injects.
     * @see {@link LocalScriptRulesService} for details about script source.
     */
    static async injectScript(scriptText, tabId, frameId = 0) {
        return TabsApi.injectScript(buildScriptText(scriptText, appContext.startTimeMs), tabId, frameId);
    }
    /**
     * Applies css from cosmetic result.
     *
     * Patches rule selector adding adguard mark rule info in the content attribute.
     * Example:
     * .selector -> .selector { content: 'adguard{filterId};{ruleText} !important;}.
     *
     * @param cssText Css text.
     * @param tabId Tab id.
     * @param frameId Frame id.
     */
    static async injectCss(cssText, tabId, frameId = 0) {
        return TabsApi.injectCss(cssText, tabId, frameId);
    }
    /**
     * Retrieves css styles from the cosmetic result.
     *
     * @param cosmeticResult Cosmetic result.
     * @param collectingCosmeticRulesHits Flag to collect cosmetic rules hits.
     * @returns Css styles as string, or `undefined` if no styles found.
     */
    static getCssText(cosmeticResult, collectingCosmeticRulesHits = false) {
        const { elementHiding, CSS } = cosmeticResult;
        const elemhideCss = elementHiding.generic.concat(elementHiding.specific);
        const injectCss = CSS.generic.concat(CSS.specific);
        let styles;
        if (collectingCosmeticRulesHits) {
            styles = CosmeticApi.buildStyleSheetsWithHits(elemhideCss, injectCss);
        }
        else {
            styles = CosmeticApi.buildStyleSheets(elemhideCss, injectCss, true);
        }
        if (styles.length > 0) {
            return styles.join(CosmeticApi.LINE_BREAK);
        }
        return undefined;
    }
    /**
     * Builds extended css rules from cosmetic result.
     *
     * @param cosmeticResult Cosmetic result.
     * @param collectingCosmeticRulesHits Flag to collect cosmetic rules hits.
     * @returns Array of extended css rules or null.
     */
    static getExtCssRules(cosmeticResult, collectingCosmeticRulesHits = false) {
        const { elementHiding, CSS } = cosmeticResult;
        const elemhideExtCss = elementHiding.genericExtCss.concat(elementHiding.specificExtCss);
        const injectExtCss = CSS.genericExtCss.concat(CSS.specificExtCss);
        let extCssRules;
        if (collectingCosmeticRulesHits) {
            extCssRules = CosmeticApi.buildStyleSheetsWithHits(elemhideExtCss, injectExtCss);
        }
        else {
            extCssRules = CosmeticApi.buildStyleSheets(elemhideExtCss, injectExtCss, false);
        }
        return extCssRules.length > 0
            ? extCssRules
            : null;
    }
    /**
     * Builds scripts from cosmetic rules.
     *
     * @param rules Cosmetic rules.
     * @param frameUrl Frame url.
     * @returns Script text or empty string if no script rules are passed.
     */
    static getScriptText(rules, frameUrl) {
        if (rules.length === 0) {
            return '';
        }
        const permittedRules = CosmeticApi.sanitizeScriptRules(rules);
        let debug = false;
        const { configuration } = appContext;
        if (configuration) {
            const { settings } = configuration;
            if (settings) {
                // https://github.com/AdguardTeam/AdguardBrowserExtension/issues/2584
                debug = settings.debugScriptlets;
            }
        }
        const scriptParams = {
            debug,
            frameUrl,
        };
        const scriptText = permittedRules
            .map((rule) => rule.getScript(scriptParams))
            .join('\n');
        if (!scriptText) {
            return '';
        }
        return `
        (function () {
            try {
                ${scriptText}
            } catch (ex) {
                console.error('Error executing AG js: ' + ex);
            }
        })();
        `;
    }
    /**
     * Returns content script data for applying cosmetic.
     *
     * @param frameUrl Frame url.
     * @param tabId Tab id.
     * @param frameId Frame id.
     * @returns Content script data for applying cosmetic.
     */
    static getContentScriptData(frameUrl, tabId, frameId) {
        const { isStorageInitialized } = appContext;
        const data = {
            isAppStarted: false,
            areHitsStatsCollected: false,
            extCssRules: null,
        };
        // if storage is not initialized, then app is not ready yet.
        if (!isStorageInitialized) {
            return data;
        }
        const { isAppStarted, configuration } = appContext;
        const areHitsStatsCollected = configuration?.settings.collectStats || false;
        data.isAppStarted = isAppStarted;
        data.areHitsStatsCollected = areHitsStatsCollected;
        const tabContext = tabsApi.getTabContext(tabId);
        if (!tabContext?.info.url) {
            return data;
        }
        const matchQuery = createFrameMatchQuery(frameUrl, frameId, tabContext);
        const cosmeticResult = engineApi.matchCosmetic(matchQuery);
        data.extCssRules = CosmeticApi.getExtCssRules(cosmeticResult, areHitsStatsCollected);
        return data;
    }
    /**
     * Applies css rules to specific frame.
     *
     * @param params Data for css rules injecting.
     */
    static async applyCssRules(params) {
        const { tabId, frameId, cosmeticResult, } = params;
        const { configuration } = appContext;
        const areHitsStatsCollected = configuration?.settings.collectStats || false;
        const cssText = CosmeticApi.getCssText(cosmeticResult, areHitsStatsCollected);
        if (cssText) {
            await CosmeticApi.injectCss(cssText, tabId, frameId);
        }
    }
    /**
     * Applies js rules to specific frame.
     *
     * @param params Data for js rule injecting.
     */
    static async applyJsRules(params) {
        const { tabId, frameId, cosmeticResult, url, } = params;
        const scriptRules = cosmeticResult.getScriptRules();
        let scriptText = CosmeticApi.getScriptText(scriptRules, url);
        const tabContext = tabsApi.getTabContext(tabId);
        if (tabContext) {
            const frame = tabContext.frames.get(frameId);
            scriptText += stealthApi.getStealthScript(tabContext.mainFrameRule, frame?.matchingResult);
        }
        if (scriptText) {
            /**
             * We can execute injectScript only once per frame, so we need to
             * combine all the scripts into a single injection.
             *
             * @see {@link buildScriptText} for details about multiple injects.
             * @see {@link LocalScriptRulesService} for details about script source
             */
            await CosmeticApi.injectScript(scriptText, tabId, frameId);
        }
    }
    /**
     * Logs js rules applied to specific frame.
     *
     * We need a separate function for logging because script rules can be logged before injection
     * to avoid duplicate logs while the js rule is being applied.
     *
     * See {@link WebRequestApi.onBeforeRequest} for details.
     *
     * @param params Data for js rule logging.
     */
    static logScriptRules(params) {
        const { tabId, cosmeticResult, url, contentType, timestamp, } = params;
        const scriptRules = cosmeticResult.getScriptRules();
        const permittedScriptRules = CosmeticApi.sanitizeScriptRules(scriptRules);
        for (const scriptRule of permittedScriptRules) {
            if (scriptRule.isGeneric()) {
                continue;
            }
            const ruleType = scriptRule.getType();
            defaultFilteringLog.publishEvent({
                type: FilteringEventType.JsInject,
                data: {
                    script: true,
                    tabId,
                    // for proper filtering log request info rule displaying
                    // event id should be unique for each event, not copied from request
                    // https://github.com/AdguardTeam/AdguardBrowserExtension/issues/2341
                    eventId: index_browser_nanoid(),
                    requestUrl: url,
                    frameUrl: url,
                    frameDomain: getDomain(url),
                    requestType: contentType,
                    timestamp,
                    filterId: scriptRule.getFilterListId(),
                    ruleIndex: scriptRule.getIndex(),
                    cssRule: ruleType === CosmeticRuleType.ElementHidingRule
                        || ruleType === CosmeticRuleType.CssInjectionRule,
                    scriptRule: ruleType === CosmeticRuleType.ScriptletInjectionRule
                        || ruleType === CosmeticRuleType.JsInjectionRule,
                    contentRule: ruleType === CosmeticRuleType.HtmlFilteringRule,
                },
            });
        }
    }
    /**
     * Injects js to specified frame based on provided data and injection FSM state.
     *
     * @param frameId Frame id.
     * @param tabId Tab id.
     */
    static async applyFrameJsRules(frameId, tabId) {
        return CosmeticApi.applyFrameCosmeticRules(frameId, tabId, CosmeticApi.applyJsRules);
    }
    /**
     * Injects css to specified frame based on provided data and injection FSM state.
     *
     * @param frameId Frame id.
     * @param tabId Tab id.
     */
    static async applyFrameCssRules(frameId, tabId) {
        return CosmeticApi.applyFrameCosmeticRules(frameId, tabId, CosmeticApi.applyCssRules);
    }
    /**
     * Injects cosmetic result to specified frame based on data provided via context.
     *
     * @param frameId Frame id.
     * @param tabId Tab id.
     * @param injector Inject function.
     * @param tries Number of tries for the injection in case of failure.
     */
    static async applyFrameCosmeticRules(frameId, tabId, injector, tries = 0) {
        try {
            // We read a cosmetic result on execution, because the tab context can change while retrying the injection.
            const frame = tabsApi.getTabFrame(tabId, frameId);
            if (frame?.cosmeticResult) {
                await injector({
                    frameId,
                    tabId,
                    url: frame.url,
                    cosmeticResult: frame.cosmeticResult,
                });
            }
        }
        catch (e) {
            if (tries < CosmeticApi.INJECTION_MAX_TRIES) {
                setTimeout(() => {
                    CosmeticApi.applyFrameCosmeticRules(frameId, tabId, injector, tries + 1);
                }, CosmeticApi.INJECTION_RETRY_TIMEOUT_MS);
            }
            else {
                logger.debug(getErrorMessage(e));
            }
        }
    }
    /**
     * Filters insecure scripts from remote sources.
     *
     * @param rules Cosmetic rules.
     * @returns Permitted script rules.
     */
    static sanitizeScriptRules(rules) {
        return rules.filter((rule) => {
            // Scriptlets should not be excluded for remote filters
            if (rule.isScriptlet) {
                return true;
            }
            // User rules should not be excluded
            const filterId = rule.getFilterListId();
            if (filterId === USER_FILTER_ID) {
                return true;
            }
            /**
             * @see {@link LocalScriptRulesService} for details about script source
             */
            return localScriptRulesService.isLocal(rule);
        });
    }
    /**
     * Patches rule selector adding adguard mark rule info in the content attribute.
     * Example:
     * .selector -> .selector { content: 'adguard{filterId};{ruleText} !important;}.
     *
     * @param rule Elemhide cosmetic rule.
     *
     * @returns Rule with modified stylesheet, containing content marker.
     */
    static addMarkerToElemhideRule(rule) {
        const result = [];
        result.push(rule.getContent());
        result.push(CosmeticApi.ELEMHIDE_HIT_START);
        result.push(rule.getFilterListId());
        result.push(CosmeticApi.HIT_SEP);
        result.push(rule.getIndex());
        result.push(CosmeticApi.HIT_END);
        return result.join('');
    }
    /**
     * Patches rule selector adding adguard mark and rule info in the content style attribute.
     * Example:
     * .selector { color: red } -> .selector { color: red, content: 'adguard{filterId};{ruleText} !important;}.
     *
     * @param rule Inject cosmetic rule.
     *
     * @returns Modified rule with injected content marker into stylesheet.
     */
    static addMarkerToInjectRule(rule) {
        const result = [];
        const ruleContent = rule.getContent();
        // if rule text has content attribute we don't add rule marker
        const contentAttributeRegex = /[{;"(]\s*content\s*:/gi;
        if (contentAttributeRegex.test(ruleContent)) {
            return ruleContent;
        }
        // remove closing brace
        const ruleTextWithoutCloseBrace = ruleContent.slice(0, -1).trim();
        // check semicolon
        const ruleTextWithSemicolon = ruleTextWithoutCloseBrace.endsWith(';')
            ? ruleTextWithoutCloseBrace
            : `${ruleTextWithoutCloseBrace};`;
        result.push(ruleTextWithSemicolon);
        result.push(CosmeticApi.INJECT_HIT_START);
        result.push(rule.getFilterListId());
        result.push(CosmeticApi.HIT_SEP);
        result.push(rule.getIndex());
        result.push(CosmeticApi.HIT_END);
        return result.join('');
    }
    /**
     * Builds stylesheets with css-hits marker.
     *
     * @param elemhideRules Elemhide css rules.
     * @param injectRules Inject css rules.
     *
     * @returns List of stylesheet expressions.
     */
    static buildStyleSheetsWithHits(elemhideRules, injectRules) {
        const elemhideStyles = elemhideRules.map((x) => CosmeticApi.addMarkerToElemhideRule(x));
        const injectStyles = injectRules.map((x) => CosmeticApi.addMarkerToInjectRule(x));
        return [...elemhideStyles, ...injectStyles];
    }
}

/**
 * Css, injected to broken element for hiding.
 */
// eslint-disable-next-line max-len
const HIDING_STYLE = '{ display: none!important; visibility: hidden!important; height: 0px!important; min-height: 0px!important; }';
/**
 * Creates hiding css rule for specified tag with src attribute.
 *
 * @param tag Element tag for css selector.
 * @param src `src` attribute value for css selector. If value is the empty string
 * then the selector does not represent anything.
 * @param matching Attribute matching type. Currently support strict (=) and suffix ($=) matching.
 * Default to strict.
 *
 * @returns Css rule text.
 */
function createHidingCssRule(tag, src, matching = "=" /* AttributeMatching.Strict */) {
    return `${tag}[src${matching}"${src}"] ${HIDING_STYLE}\n`;
}

/**
 * Get relative path of first-party request for resource `src` attribute.
 *
 * @param requestUrl Resource url.
 * @param documentUrl Url of the document in which the resource will be loaded.
 *
 * @returns Relative path of resource `src` attribute for css selector.
 */
function getRelativeSrcPath(requestUrl, documentUrl) {
    const requestUrlData = new URL(requestUrl);
    const documentUrlData = new URL(documentUrl);
    const documentPathname = documentUrlData.pathname;
    const requestPathname = requestUrlData.pathname;
    const requestUrlTail = requestUrlData.search + requestUrlData.hash;
    if (documentPathname === '/') {
        return requestPathname + requestUrlTail;
    }
    // Check that partial pathnames match
    const requestUrlPathParts = requestPathname.split('/').filter((part) => !!part);
    const documentUrlPathParts = documentPathname.split('/').filter((part) => !!part);
    const commonParts = [];
    for (let i = 0; i < Math.min(requestUrlPathParts.length, documentUrlPathParts.length); i += 1) {
        if (requestUrlPathParts[i] !== documentUrlPathParts[i]) {
            const path = requestUrlPathParts.slice(i).join('/') + requestUrlTail;
            // If first parts are matched, return path relative to document page
            // else return path relative to host
            return i > 0 ? path : `/${path}`;
        }
        commonParts.push(requestUrlPathParts[i]);
    }
    const commonPath = `/${commonParts.join('/')}`;
    return requestPathname.substring(commonPath.length + 1) + requestUrlTail;
}
/**
 * Returns network request initiator tag by request type.
 *
 * @param requestType Request type.
 * @returns Initiator tag.
 */
function getRequestInitiatorTag(requestType) {
    switch (requestType) {
        case RequestType.SubDocument:
            return ["iframe" /* InitiatorTag.Iframe */, "frame" /* InitiatorTag.Frame */];
        case RequestType.Image:
            return ["img" /* InitiatorTag.Image */];
        default:
            return null;
    }
}
/**
 * Inject css for element hiding by tabs.injectCss.
 *
 * @param tabId Tab id.
 * @param requestFrameId Request frame id.
 * @param requestUrl Request url.
 * @param documentUrl Document url.
 * @param requestType Request type.
 * @param isThirdParty Flag telling if request is third-party.
 */
function hideRequestInitiatorElement(tabId, requestFrameId, requestUrl, documentUrl, requestType, isThirdParty) {
    const initiatorTags = getRequestInitiatorTag(requestType);
    if (!initiatorTags || tabId === BACKGROUND_TAB_ID) {
        return;
    }
    let src;
    let matching;
    if (isThirdParty) {
        src = requestUrl.substring(requestUrl.indexOf('//'));
        matching = "$=" /* AttributeMatching.Suffix */;
    }
    else {
        src = getRelativeSrcPath(requestUrl, documentUrl);
        matching = "=" /* AttributeMatching.Strict */;
    }
    let code = '';
    for (let i = 0; i < initiatorTags.length; i += 1) {
        code += createHidingCssRule(initiatorTags[i], src, matching);
    }
    CosmeticApi.injectCss(code, tabId, requestFrameId);
}

/**
 * IMPORTANT: if 'import' is used, the path will be resolved to the actual file in the bundled index.mv3.ts
 * but we need the same relative path (to dist file) since the data will be replaced after the build,
 * so it should be 'require' instead of 'import'.
 */
const { rawCompaniesDb } = __webpack_require__(18721);
/**
 * Service for working with companies database.
 */
class CompaniesDbService {
    /**
     * Category name for unknown domains.
     *
     * @see {@link https://github.com/AdguardTeam/companiesdb/blob/6a8fbfc3bff4fdffc4c8bae30756530afc2635bd/dist/trackers.json#L15}
     */
    static UNKNOWN_CATEGORY_NAME = 'unknown';
    /**
     * Companies database.
     */
    companiesDb = rawCompaniesDb;
    /**
     * Returns categories from the companiesdb data where
     * - key — numeric category id
     * - value — category name.
     *
     * @returns Categories from the companiesdb data.
     *
     * @throws Error if companies database is not loaded.
     */
    getCompaniesDbCategories() {
        if (!this.companiesDb) {
            throw new Error('[CompaniesDbService] Companies database is not loaded');
        }
        return this.companiesDb.categories;
    }
    /**
     * Matches a URL to a tracker category id.
     *
     * List of categories ids can be found in {@link companiesDb.categories}.
     *
     * @param url Request URL to match.
     *
     * @returns Matched company category name,
     * or {@link CompaniesDbService.UNKNOWN_CATEGORY_NAME} if the category is unknown.
     */
    match(url) {
        if (!this.companiesDb || !this.companiesDb.trackerDomains) {
            return CompaniesDbService.UNKNOWN_CATEGORY_NAME;
        }
        const domain = (0,es6/* getDomain */.ge)(url);
        if (!domain) {
            return CompaniesDbService.UNKNOWN_CATEGORY_NAME;
        }
        const companyCategoryId = this.companiesDb.trackerDomains[domain];
        if (!companyCategoryId) {
            return CompaniesDbService.UNKNOWN_CATEGORY_NAME;
        }
        const companyCategoryName = this.companiesDb.categories[companyCategoryId];
        if (!companyCategoryName) {
            return CompaniesDbService.UNKNOWN_CATEGORY_NAME;
        }
        return companyCategoryName;
    }
}
const companiesDbService = new CompaniesDbService();

/**
 * Api for processing request filtering.
 *
 * Method {@link getBlockingResponse} processes rule applying for request and computes response
 * for {@link WebRequestApi.onBeforeRequest} listener.
 *
 * Method {@link shouldCollapseElement} checks, if initializer for request should be collapsed by content-script.
 *
 * This class also provides method {@link isRequestBlockedByRule} for checking, if rule is blocking rule.
 */
class RequestBlockingApi {
    /**
     * In some cases request blocking breaks images and frames on page.
     * We match rule from content-script and decide if DOM element should be hidden via css.
     *
     * @param tabId Tab id.
     * @param url Request url.
     * @param referrerUrl Request initializer frame url.
     * @param requestType Type of request.
     *
     * @returns True, if element should be collapsed, else returns false.
     */
    static shouldCollapseElement(tabId, url, referrerUrl, requestType) {
        const result = engineApi.matchRequest({
            requestUrl: url,
            frameUrl: referrerUrl,
            requestType,
            frameRule: tabsApi.getTabFrameRule(tabId),
        });
        if (!result) {
            return false;
        }
        const basicRule = result.getBasicResult();
        const popupRule = result.getPopupRule();
        // we do not want to block the main page if the rule has only $popup modifier
        if (basicRule === popupRule) {
            return false;
        }
        return RequestBlockingApi.isRequestBlockedByRule(result.getBasicResult());
    }
    /**
     * Checks if request rule is blocked.
     *
     * @param requestRule Request network rule or null.
     * @returns True, if rule is request blocking, else returns false.
     */
    static isRequestBlockedByRule(requestRule) {
        return !!requestRule
            && !requestRule.isAllowlist()
            && !requestRule.isOptionEnabled(es/* NetworkRuleOption.Replace */.SJ.Replace)
            && !requestRule.isOptionEnabled(es/* NetworkRuleOption.Redirect */.SJ.Redirect);
    }
    /**
     * Closes the tab which considered as a popup.
     *
     * @param data Needed data for logging closing of tab.
     * @param appliedRule Network rule which was applied to request. This field
     * is needed because data contains two rules: one for the request and
     * one for the popup. And we should log only the rule which was applied
     * to the request.
     *
     * @returns Response for {@link WebRequestApi.onBeforeRequest} listener.
     */
    static closeTab(data, appliedRule) {
        RequestBlockingApi.logRuleApplying(data, appliedRule);
        browser_polyfill_default().tabs.remove(data.tabId);
        return { cancel: true };
    }
    /**
     * Processes rule applying for request and compute response for {@link WebRequestApi.onBeforeRequest} listener.
     *
     * @param data Data for request processing.
     *
     * @returns Response for {@link WebRequestApi.onBeforeRequest} listener.
     */
    static getBlockingResponse(data) {
        const { rule, popupRule, requestType, tabId, eventId, requestUrl, requestId, referrerUrl, } = data;
        if (!rule) {
            return undefined;
        }
        // popup rule will be handled in the condition with RequestType === document below
        if (popupRule === rule && requestType !== es/* RequestType.Document */.xd.Document) {
            return undefined;
        }
        if (rule.isAllowlist()) {
            RequestBlockingApi.logRuleApplying(data, rule);
            return undefined;
        }
        if (rule.isOptionEnabled(es/* NetworkRuleOption.Redirect */.SJ.Redirect)) {
            const redirectUrl = redirectsService.createRedirectUrl(rule.getAdvancedModifierValue(), requestUrl);
            if (redirectUrl) {
                RequestBlockingApi.logRuleApplying(data, rule);
                // redirects should be considered as blocked for the tab blocked request count
                // which is displayed on the extension badge
                // https://github.com/AdguardTeam/AdguardBrowserExtension/issues/2443
                tabsApi.incrementTabBlockedRequestCount(tabId, referrerUrl);
                return { redirectUrl };
            }
        }
        // Basic rules for blocking requests are applied only to sub-requests
        // so `||example.com^` will not block the main page
        // https://adguard.com/kb/general/ad-filtering/create-own-filters/#basic-rules
        // For document requests we need to show blocking page or close tab.
        if (requestType === es/* RequestType.Document */.xd.Document) {
            // Blocking rule can be with $popup modifier - in this case we need
            // to close the tab as soon as possible.
            // https://adguard.com/kb/general/ad-filtering/create-own-filters/#popup-modifier
            if (popupRule && tabsApi.isNewPopupTab(tabId)) {
                return RequestBlockingApi.closeTab(data, popupRule);
            }
            // to handle rules with $all modifier, where popup was added implicitly
            if (rule.isOptionEnabled(es/* NetworkRuleOption.Popup */.SJ.Popup) && tabsApi.isNewPopupTab(tabId)) {
                return RequestBlockingApi.closeTab(data, rule);
            }
            // we do not want to block the main page if rule has only $popup modifier
            if (rule === popupRule && !tabsApi.isNewPopupTab(tabId)) {
                return undefined;
            }
            // but if the blocking rule has $document modifier, blocking page should be shown
            // e.g. `||example.com^$document`
            if ((rule.getPermittedRequestTypes() & es/* RequestType.Document */.xd.Document) === es/* RequestType.Document */.xd.Document) {
                return documentBlockingService.getDocumentBlockingResponse({
                    eventId,
                    requestUrl,
                    requestId,
                    referrerUrl,
                    rule,
                    tabId,
                });
            }
            return undefined;
        }
        RequestBlockingApi.logRuleApplying(data, rule);
        return { cancel: true };
    }
    /**
     * Processes rule applying for request and compute response for {@link WebRequestApi.onHeadersReceived} listener.
     *
     * @param responseHeaders Response headers.
     * @param data Data for request processing.
     *
     * @returns Response for {@link WebRequestApi.onHeadersReceived} listener.
     */
    static getResponseOnHeadersReceived(responseHeaders, data) {
        if (!data.rule || !responseHeaders) {
            return undefined;
        }
        RequestBlockingApi.logRuleApplying(data, data.rule);
        return data.rule.isAllowlist() ? undefined : { cancel: true };
    }
    /**
     * Creates {@link FilteringLog} event of rule applying for processed request.
     *
     * @param data Data for request processing.
     * @param appliedRule Network rule which was applied to request.
     */
    static logRuleApplying(data, appliedRule) {
        const { tabId, eventId, requestId, referrerUrl, requestUrl, contentType, } = data;
        if (!appliedRule) {
            return;
        }
        const companyCategoryName = companiesDbService.match(requestUrl);
        defaultFilteringLog.publishEvent({
            type: FilteringEventType.ApplyBasicRule,
            data: {
                tabId,
                eventId,
                requestType: contentType,
                frameUrl: referrerUrl,
                requestId,
                requestUrl,
                companyCategoryName,
                filterId: appliedRule.getFilterListId(),
                ruleIndex: appliedRule.getIndex(),
                isAllowlist: appliedRule.isAllowlist(),
                isImportant: appliedRule.isOptionEnabled(es/* NetworkRuleOption.Important */.SJ.Important),
                isDocumentLevel: appliedRule.isDocumentLevelAllowlistRule(),
                isCsp: appliedRule.isOptionEnabled(es/* NetworkRuleOption.Csp */.SJ.Csp),
                isCookie: appliedRule.isOptionEnabled(es/* NetworkRuleOption.Cookie */.SJ.Cookie),
                advancedModifier: appliedRule.getAdvancedModifierValue(),
            },
        });
    }
}

/**
 * Generic wrapper for browser.webRequest with custom event implementation.
 */
class RequestEvent {
    listeners = [];
    /**
     * Register listener for the browser.webRequest events.
     *
     * @param event Webrequest event name.
     * @param handler Handler to register.
     * @param filter Filter of the events.
     * @param extraInfoSpec Extra info spec.
     */
    init(event, handler, filter, extraInfoSpec) {
        const handleBrowserEvent = (details) => {
            const data = handler(details);
            /**
             * Execute all registered listeners one by one until a non-empty value is returned.
             */
            for (let i = 0; i < this.listeners.length; i += 1) {
                const res = this.listeners[i](data);
                if (res) {
                    return res;
                }
            }
            return undefined;
        };
        if (extraInfoSpec) {
            event.addListener(handleBrowserEvent, filter, extraInfoSpec);
        }
        else {
            event.addListener(handleBrowserEvent, filter);
        }
    }
    /**
     * Register listener for the browser.webRequest events.
     *
     * @param listener Event callback.
     */
    addListener(listener) {
        this.listeners.push(listener);
    }
    /**
     * Remove listener from the browser.webRequest events.
     *
     * @param listener Event callback.
     */
    removeListener(listener) {
        const index = this.listeners.indexOf(listener);
        if (index !== -1) {
            this.listeners.splice(index, 1);
        }
    }
}

const browserDetector = es5_default().getParser(window.navigator.userAgent);
const browserDetails = browserDetector.getBrowser();
const engineDetails = browserDetector.getEngine();
const isOpera = browserDetails.name === 'Opera';
const isFirefox = browserDetails.name === 'Firefox';
browserDetails.name === 'Chrome';
const isChromium = engineDetails.name === 'Blink';

/**
 * Synthetic Cookie-like object parsed from headers.
 */
class ParsedCookie {
    /**
     * The request-URI to associate with the setting of the cookie.
     */
    url;
    /**
     * Defines the host to which the cookie will be sent.
     * Only the current domain can be set as the value, or a domain of a higher
     * order, unless it is a public suffix. Setting the domain will make
     * the cookie available to it, as well as to all its subdomains.
     *
     * Can be empty. And actually should be empty for `__Host-` cookies.
     *
     * @see {@link https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie#attributes}
     */
    domain;
    /**
     * The name of the cookie.
     */
    name;
    /**
     * The value of the cookie.
     */
    value;
    /**
     * The expiration date of the cookie.
     */
    expires;
    /**
     * The parsed max-age value in seconds.
     */
    maxAge;
    /**
     * True if the cookie is marked as Secure.
     */
    secure;
    /**
     * Whether the cookie should be marked as HttpOnly.
     */
    httpOnly;
    /**
     * Cookie's same-site status.
     */
    sameSite;
    /**
     * Cookies path. Defaults to the path portion of the url parameter.
     */
    path;
    /**
     * Priority chrome only specs.
     * Isn't affected. Let it be here just in case.
     *
     * @see {@link https://bugs.chromium.org/p/chromium/issues/detail?id=232693}
     */
    priority;
    /**
     * Cookie's third-party status.
     */
    thirdParty = false;
    /**
     * Constructor.
     *
     * @param name Cookie name.
     * @param value Cookie value.
     * @param url Url.
     */
    constructor(name, value, url) {
        this.name = name;
        this.value = value;
        this.url = url;
        this.path = new URL(url).pathname;
    }
    /**
     * Creates new {@link ParsedCookie} from provided {@link Cookies.Cookie}.
     *
     * @param cookie Item of {@link Cookies.Cookie}.
     * @param url String URL relative to this cookie.
     *
     * @returns New {@link ParsedCookie}.
     */
    static fromBrowserCookie(cookie, url) {
        const parsedCookie = new ParsedCookie(cookie.name, cookie.value, url);
        parsedCookie.thirdParty = !cookie.firstPartyDomain;
        parsedCookie.httpOnly = cookie.httpOnly;
        parsedCookie.secure = cookie.secure;
        parsedCookie.sameSite = cookie.sameSite;
        // For hostOnly cookie domain should be empty and path should be '/'.
        if (cookie.hostOnly) {
            parsedCookie.path = '/';
        }
        else {
            parsedCookie.domain = cookie.domain;
            parsedCookie.path = cookie.path;
        }
        if (cookie.expirationDate) {
            // cookie.expirationDate is a number of seconds that's why it should be multiplied
            parsedCookie.expires = new Date(cookie.expirationDate * 1000);
        }
        return parsedCookie;
    }
}

/**
 * Cookie Utils.
 */
let CookieUtils$1 = class CookieUtils {
    /**
     * RegExp to match field-content in RFC 7230 sec 3.2.
     *
     * Example:
     * field-content = field-vchar [ 1*( SP / HTAB ) field-vchar ]
     * field-vchar   = VCHAR / obs-text
     * obs-text      = %x80-FF.
     */
    // eslint-disable-next-line no-control-regex
    static FIELD_CONTENT_REGEX = /^[\u0009\u0020-\u007e\u0080-\u00ff]+$/;
    /**
     * Parses set-cookie header from http response header.
     *
     * @param header HTTP response header.
     * @param url Request URL.
     * @returns Parsed cookie or null if it failed to parse the header.
     */
    static parseSetCookieHeader(header, url) {
        if (!header.name || header.name.toLowerCase() !== 'set-cookie') {
            return null;
        }
        if (!header.value) {
            return null;
        }
        return CookieUtils.parseSetCookie(header.value, url);
    }
    /**
     * Parses set-cookie headers for cookie objects.
     *
     * @param responseHeaders HTTP response headers.
     * @param url Request URL.
     * @returns Array of parsed cookies.
     */
    static parseSetCookieHeaders(responseHeaders, url) {
        const result = [];
        let iResponseHeaders = responseHeaders.length;
        while (iResponseHeaders > 0) {
            iResponseHeaders -= 1;
            const header = responseHeaders[iResponseHeaders];
            const setCookie = CookieUtils.parseSetCookieHeader(header, url);
            if (setCookie) {
                result.push(setCookie);
            }
        }
        return result;
    }
    /**
     * Parse an HTTP Cookie header string and return an object with all cookie name-value pairs.
     *
     * @param cookieValue HTTP Cookie value.
     * @param url Request URL.
     * @returns Array of cookie name-value pairs.
     */
    static parseCookies(cookieValue, url) {
        const cookies = [];
        // Split Cookie values
        const pairs = cookieValue.split(/; */);
        for (let i = 0; i < pairs.length; i += 1) {
            const pair = pairs[i];
            const eqIdx = pair.indexOf('=');
            // skip things that don't look like key=value
            if (eqIdx < 0) {
                continue;
            }
            const key = pair.substring(0, eqIdx).trim();
            const value = pair.substring(eqIdx + 1, pair.length).trim();
            const parsedCookie = new ParsedCookie(key, value, url);
            /**
             * Not obviously there are few special name prefixes.
             *
             * @see {@link https://developer.cdn.mozilla.net/pt-BR/docs/Web/HTTP/Headers/Set-Cookie}
             */
            if (key.startsWith('__Secure-') || key.startsWith('__Host-')) {
                parsedCookie.secure = true;
            }
            cookies.push(parsedCookie);
        }
        return cookies;
    }
    /**
     * Parses "Set-Cookie" header value and returns a cookie object with its properties.
     *
     * @param setCookieValue "Set-Cookie" header value to parse.
     * @param url Request URL.
     * @returns Parsed cookie or null if it failed to parse the value.
     */
    static parseSetCookie(setCookieValue, url) {
        const parts = setCookieValue.split(';').filter((s) => !!s);
        const nameValuePart = parts.shift();
        if (!nameValuePart) {
            // eslint-disable-next-line max-len
            logger.debug(`[tswebextension.parseSetCookie]: cannot shift first name-value pair from Set-Cookie header '${setCookieValue}'.`);
            return null;
        }
        const nameValue = nameValuePart.split('=');
        const name = nameValue.shift();
        if (!name) {
            // eslint-disable-next-line max-len
            logger.debug(`[tswebextension.parseSetCookie]: cannot extract name from first name-value pair from Set-Cookie header '${setCookieValue}'.`);
            return null;
        }
        // Everything after the first =, joined by a "=" if there was more
        // than one part.
        const value = nameValue.join('=');
        const cookie = new ParsedCookie(name, value, url);
        parts.forEach((part) => {
            const sides = part.split('=');
            const key = sides
                .shift()
                .trimStart()
                .toLowerCase();
            const optionValue = sides.join('=');
            if (key === 'expires') {
                cookie.expires = new Date(optionValue);
            }
            else if (key === 'max-age') {
                cookie.maxAge = parseInt(optionValue, 10);
            }
            else if (key === 'secure') {
                cookie.secure = true;
            }
            else if (key === 'httponly') {
                cookie.httpOnly = true;
            }
            else if (key === 'samesite') {
                cookie.sameSite = optionValue;
            }
            else if (key === 'path') {
                cookie.path = optionValue;
            }
            else if (key === 'domain') {
                cookie.domain = optionValue;
            }
        });
        return cookie;
    }
    /**
     * Updates cookie maxAge value.
     *
     * @param cookie Cookie to modify.
     * @param maxAge New maxAge value.
     * @returns True if cookie was modified.
     */
    static updateCookieMaxAge(cookie, maxAge) {
        const currentTimeSec = Date.now() / 1000;
        let cookieExpiresTimeSec = null;
        if (cookie.maxAge) {
            cookieExpiresTimeSec = currentTimeSec + cookie.maxAge;
        }
        else if (cookie.expires) {
            cookieExpiresTimeSec = cookie.expires.getTime() / 1000;
        }
        const newCookieExpiresTimeSec = currentTimeSec + maxAge;
        if (cookieExpiresTimeSec === null || cookieExpiresTimeSec > newCookieExpiresTimeSec) {
            // eslint-disable-next-line no-param-reassign
            cookie.expires = new Date(newCookieExpiresTimeSec * 1000);
            // eslint-disable-next-line no-param-reassign
            cookie.maxAge = maxAge;
            return true;
        }
        return false;
    }
    /**
     * Serializes cookie data into a string suitable for Set-Cookie header.
     *
     * @param cookie A cookie object.
     * @returns Set-Cookie string or null if it failed to serialize object.
     * @throws {TypeError} Thrown in case of invalid input data.
     */
    static serializeCookieToResponseHeader(cookie) {
        if (!cookie) {
            throw new TypeError('empty cookie data');
        }
        // 1. Validate fields
        if (!CookieUtils.FIELD_CONTENT_REGEX.test(cookie.name)) {
            throw new TypeError(`Cookie name is invalid: ${cookie.name}`);
        }
        if (cookie.value && !CookieUtils.FIELD_CONTENT_REGEX.test(cookie.value)) {
            throw new TypeError(`Cookie value is invalid: ${cookie.value}`);
        }
        if (cookie.domain && !CookieUtils.FIELD_CONTENT_REGEX.test(cookie.domain)) {
            throw new TypeError(`Cookie domain is invalid: ${cookie.domain}`);
        }
        if (cookie.path && !CookieUtils.FIELD_CONTENT_REGEX.test(cookie.path)) {
            throw new TypeError(`Cookie path is invalid: ${cookie.path}`);
        }
        if (cookie.expires && typeof cookie.expires.toUTCString !== 'function') {
            throw new TypeError(`Cookie expires is invalid: ${cookie.expires}`);
        }
        // 2. Build Set-Cookie header value
        let setCookieValue = `${cookie.name}=${cookie.value}`;
        if (typeof cookie.maxAge === 'number' && !Number.isNaN(cookie.maxAge)) {
            setCookieValue += `; Max-Age=${Math.floor(cookie.maxAge)}`;
        }
        if (cookie.domain) {
            setCookieValue += `; Domain=${cookie.domain}`;
        }
        if (cookie.path) {
            setCookieValue += `; Path=${cookie.path}`;
        }
        if (cookie.expires) {
            setCookieValue += `; Expires=${cookie.expires.toUTCString()}`;
        }
        if (cookie.httpOnly) {
            setCookieValue += '; HttpOnly';
        }
        if (cookie.secure) {
            setCookieValue += '; Secure';
        }
        if (cookie.sameSite) {
            const sameSite = cookie.sameSite.toLowerCase();
            switch (sameSite) {
                case 'lax':
                    setCookieValue += '; SameSite=Lax';
                    break;
                case 'strict':
                    setCookieValue += '; SameSite=Strict';
                    break;
                case 'none':
                    setCookieValue += '; SameSite=None';
                    break;
                default:
                    throw new TypeError(`Cookie sameSite is invalid: ${cookie.sameSite}`);
            }
        }
        // Not affected. Let it be here just in case
        // https://bugs.chromium.org/p/chromium/issues/detail?id=232693
        if (cookie.priority) {
            setCookieValue += `; Priority=${cookie.priority}`;
        }
        return setCookieValue;
    }
    /**
     * Serializes cookie data into a string suitable for Cookie header.
     *
     * @param cookies Array with {@link ParsedCookie}.
     * @returns Cookie string or null if it failed to serialize object.
     */
    static serializeCookieToRequestHeader(cookies) {
        return cookies
            .map((cookie) => `${cookie.name}=${cookie.value}`)
            .join('; ');
    }
};

/**
 * Cookie Utils.
 */
class CookieUtils extends CookieUtils$1 {
    /**
     * Set-Cookie header name.
     */
    static SET_COOKIE_HEADER_NAME = 'set-cookie';
    /**
     * Line feed character.
     */
    static LINE_FEED = '\n';
    /**
     * Splits a single `set-cookie` header with multiline cookies into
     * multiple `set-cookie` headers with single-line cookies.
     *
     * Mutates `responseHeaders`.
     *
     * @param responseHeaders HTTP response headers.
     */
    static splitMultilineCookies(responseHeaders) {
        for (let i = responseHeaders.length - 1; i >= 0; i -= 1) {
            const { name, value } = responseHeaders[i];
            if (name.toLowerCase() !== CookieUtils.SET_COOKIE_HEADER_NAME
                || !value
                || !value.includes(CookieUtils.LINE_FEED)) {
                continue;
            }
            const values = value.split(CookieUtils.LINE_FEED);
            // Remove the original header, iteration won't be broken
            // as the array is being modified from the end
            responseHeaders.splice(i, 1);
            // eslint-disable-next-line @typescript-eslint/no-shadow
            values.forEach((value) => {
                responseHeaders.push({ name: CookieUtils.SET_COOKIE_HEADER_NAME, value });
            });
        }
    }
    /**
     * Serializes cookie data into a string suitable for Set-Cookie header.
     *
     * @param cookie A cookie object.
     * @returns Set-Cookie string or null if it failed to serialize object.
     * @throws {TypeError} Thrown in case of invalid input data.
     */
    static serializeCookieToResponseHeader(cookie) {
        if (!cookie) {
            throw new TypeError('empty cookie data');
        }
        // 1. Validate fields
        if (!CookieUtils.FIELD_CONTENT_REGEX.test(cookie.name)) {
            throw new TypeError(`Cookie name is invalid: ${cookie.name}`);
        }
        if (cookie.value && !CookieUtils.FIELD_CONTENT_REGEX.test(cookie.value)) {
            throw new TypeError(`Cookie value is invalid: ${cookie.value}`);
        }
        if (cookie.domain && !CookieUtils.FIELD_CONTENT_REGEX.test(cookie.domain)) {
            throw new TypeError(`Cookie domain is invalid: ${cookie.domain}`);
        }
        if (cookie.path && !CookieUtils.FIELD_CONTENT_REGEX.test(cookie.path)) {
            throw new TypeError(`Cookie path is invalid: ${cookie.path}`);
        }
        if (cookie.expires && typeof cookie.expires.toUTCString !== 'function') {
            throw new TypeError(`Cookie expires is invalid: ${cookie.expires}`);
        }
        // 2. Build Set-Cookie header value
        let setCookieValue = `${cookie.name}=${cookie.value}`;
        if (typeof cookie.maxAge === 'number' && !Number.isNaN(cookie.maxAge)) {
            setCookieValue += `; Max-Age=${Math.floor(cookie.maxAge)}`;
        }
        if (cookie.domain) {
            setCookieValue += `; Domain=${cookie.domain}`;
        }
        if (cookie.path) {
            setCookieValue += `; Path=${cookie.path}`;
        }
        if (cookie.expires) {
            setCookieValue += `; Expires=${cookie.expires.toUTCString()}`;
        }
        if (cookie.httpOnly) {
            setCookieValue += '; HttpOnly';
        }
        if (cookie.secure) {
            setCookieValue += '; Secure';
        }
        if (cookie.sameSite) {
            const sameSite = cookie.sameSite.toLowerCase();
            switch (sameSite) {
                case 'lax':
                    setCookieValue += '; SameSite=Lax';
                    break;
                case 'strict':
                    setCookieValue += '; SameSite=Strict';
                    break;
                case 'none':
                    setCookieValue += '; SameSite=None';
                    break;
                default:
                    throw new TypeError(`Cookie sameSite is invalid: ${cookie.sameSite}`);
            }
        }
        // Not affected. Let it be here just in case
        // https://bugs.chromium.org/p/chromium/issues/detail?id=232693
        if (cookie.priority) {
            setCookieValue += `; Priority=${cookie.priority}`;
        }
        return setCookieValue;
    }
    /**
     * Serializes cookie data into a string suitable for Cookie header.
     *
     * @param cookies Array with {@link ParsedCookie}.
     * @returns Cookie string or null if it failed to serialize object.
     */
    static serializeCookieToRequestHeader(cookies) {
        return cookies
            .map((cookie) => `${cookie.name}=${cookie.value}`)
            .join('; ');
    }
}

/**
 * Request content type.
 *
 * NOTE: Do not use `const enum`,
 * because this enum is imported in extension frontend writing in js.
 */
var ContentType;
(function (ContentType) {
    ContentType["Document"] = "document";
    ContentType["Subdocument"] = "subdocument";
    ContentType["Script"] = "script";
    ContentType["Stylesheet"] = "stylesheet";
    ContentType["Object"] = "object";
    ContentType["Image"] = "image";
    ContentType["XmlHttpRequest"] = "xmlHttpRequest";
    ContentType["Media"] = "media";
    ContentType["Font"] = "font";
    ContentType["Websocket"] = "websocket";
    ContentType["WebRtc"] = "webRtc";
    ContentType["Other"] = "other";
    ContentType["Csp"] = "csp";
    ContentType["PermissionsPolicy"] = "permissionsPolicy";
    ContentType["Cookie"] = "cookie";
    ContentType["Ping"] = "ping";
    ContentType["CspReport"] = "cspReport";
})(ContentType || (ContentType = {}));
/**
 * Returns request type and content type by resource type.
 *
 * @param resourceType Resource type.
 * @returns Request type and content type.
 */
function getRequestType(resourceType) {
    switch (resourceType) {
        case 'main_frame':
            return {
                contentType: ContentType.Document,
                requestType: RequestType.Document,
            };
        case 'sub_frame':
            return {
                contentType: ContentType.Subdocument,
                requestType: RequestType.SubDocument,
            };
        case 'stylesheet':
            return {
                contentType: ContentType.Stylesheet,
                requestType: RequestType.Stylesheet,
            };
        case 'script':
            return {
                contentType: ContentType.Script,
                requestType: RequestType.Script,
            };
        case 'image':
        case 'imageset':
            return {
                contentType: ContentType.Image,
                requestType: RequestType.Image,
            };
        case 'object':
            return {
                contentType: ContentType.Object,
                requestType: RequestType.Object,
            };
        case 'xmlhttprequest':
            return {
                contentType: ContentType.XmlHttpRequest,
                requestType: RequestType.XmlHttpRequest,
            };
        case 'ping':
        case 'beacon':
            return {
                contentType: ContentType.Ping,
                requestType: RequestType.Ping,
            };
        case 'font':
            return {
                contentType: ContentType.Font,
                requestType: RequestType.Font,
            };
        case 'media':
            return {
                contentType: ContentType.Media,
                requestType: RequestType.Media,
            };
        case 'websocket':
            return {
                contentType: ContentType.Websocket,
                requestType: RequestType.WebSocket,
            };
        case 'csp_report':
            return {
                contentType: ContentType.CspReport,
                requestType: RequestType.CspReport,
            };
        default:
            return {
                contentType: ContentType.Other,
                requestType: RequestType.Other,
            };
    }
}

const MAX_URL_LENGTH = (/* unused pure expression or super */ null && (1024 * 16));
/**
 * Request events class.
 */
class RequestEvents {
    static onBeforeRequest = new RequestEvent();
    static onBeforeSendHeaders = new RequestEvent();
    static onSendHeaders = new RequestEvent();
    static onHeadersReceived = new RequestEvent();
    static onAuthRequired = new RequestEvent();
    static onBeforeRedirect = new RequestEvent();
    static onResponseStarted = new RequestEvent();
    static onCompleted = new RequestEvent();
    static onErrorOccurred = new RequestEvent();
    /**
     * Initializes request events service.
     */
    static init() {
        RequestEvents.onBeforeRequest.init(browser.webRequest.onBeforeRequest, RequestEvents.handleOnBeforeRequest, { urls: ['<all_urls>'] }, ['blocking', 'requestBody']);
        const onBeforeSendHeadersOptions = ['requestHeaders', 'blocking'];
        const onBeforeSendHeadersOptionTypes = browser.webRequest.OnBeforeSendHeadersOptions;
        if (typeof onBeforeSendHeadersOptionTypes !== 'undefined'
            && Object.prototype.hasOwnProperty.call(onBeforeSendHeadersOptionTypes, 'EXTRA_HEADERS')) {
            onBeforeSendHeadersOptions.push('extraHeaders');
        }
        RequestEvents.onBeforeSendHeaders.init(browser.webRequest.onBeforeSendHeaders, RequestEvents.handleOnBeforeSendHeaders, { urls: ['<all_urls>'] }, onBeforeSendHeadersOptions);
        RequestEvents.onSendHeaders.init(browser.webRequest.onSendHeaders, RequestEvents.handleSendHeaders, { urls: ['<all_urls>'] });
        const onHeadersReceivedOptions = ['responseHeaders', 'blocking'];
        const onHeadersReceivedOptionTypes = browser.webRequest.OnHeadersReceivedOptions;
        if (typeof onHeadersReceivedOptionTypes !== 'undefined'
            && Object.prototype.hasOwnProperty.call(onBeforeSendHeadersOptionTypes, 'EXTRA_HEADERS')) {
            onHeadersReceivedOptions.push('extraHeaders');
        }
        RequestEvents.onHeadersReceived.init(browser.webRequest.onHeadersReceived, RequestEvents.handleOnHeadersReceived, { urls: ['<all_urls>'] }, onHeadersReceivedOptions);
        RequestEvents.onAuthRequired.init(browser.webRequest.onAuthRequired, RequestEvents.handleOnAuthRequired, { urls: ['<all_urls>'] });
        RequestEvents.onBeforeRedirect.init(browser.webRequest.onBeforeRedirect, RequestEvents.handleOnBeforeRedirect, { urls: ['<all_urls>'] });
        RequestEvents.onResponseStarted.init(browser.webRequest.onResponseStarted, RequestEvents.handleOnResponseStarted, { urls: ['<all_urls>'] });
        RequestEvents.onCompleted.init(browser.webRequest.onCompleted, RequestEvents.handleOnCompleted, { urls: ['<all_urls>'] }, ['responseHeaders']);
        RequestEvents.onErrorOccurred.init(browser.webRequest.onErrorOccurred, RequestEvents.handleOnErrorOccurred, { urls: ['<all_urls>'] });
    }
    /**
     * Handles onBeforeRequest event.
     *
     * @param details WebRequest details.
     * @returns Request data.
     */
    static handleOnBeforeRequest(details) {
        const { requestId, type, tabId, parentFrameId, originUrl, initiator, method, timeStamp, } = details;
        let { url, frameId } = details;
        /**
         * Truncate too long urls.
         *
         * @see {@link https://github.com/AdguardTeam/AdguardBrowserExtension/issues/1493}
         */
        if (url.length > MAX_URL_LENGTH) {
            url = url.slice(0, MAX_URL_LENGTH);
        }
        /**
         * FF sends http instead of ws protocol at the http-listeners layer
         * Although this is expected, as the Upgrade request is indeed an HTTP request,
         * we use a chromium based approach in this case.
         */
        if (type === 'websocket' && isHttpRequest(url)) {
            url = url.replace(/^http(s)?:/, 'ws$1:');
        }
        const { requestType, contentType } = getRequestType(type);
        const isDocumentRequest = requestType === RequestType.Document;
        // Pre-rendered documents can have a frame ID other than zero
        frameId = isDocumentRequest ? MAIN_FRAME_ID : details.frameId;
        let requestFrameId = isDocumentRequest ? frameId : parentFrameId;
        // Relate request to main_frame
        if (requestFrameId === -1) {
            requestFrameId = 0;
        }
        // To mark requests started via navigation from the address bar (real
        // request or pre-render, it does not matter) as first-party requests,
        // we get only part of the request context to record only the tab and
        // frame information before calculating the request referrer.
        const tabFrameRequestContext = {
            requestUrl: url,
            requestType,
            requestId,
            frameId,
            tabId,
        };
        if (isDocumentRequest || requestType === RequestType.SubDocument) {
            // Saves the current tab url to retrieve it correctly below.
            tabsApi.handleFrameRequest(tabFrameRequestContext);
        }
        // Do not reload filtering log on requests that are being redirected by $removeparam
        if (isDocumentRequest && !requestContextStorage.has(requestId)) {
            // dispatch filtering log reload event
            defaultFilteringLog.publishEvent({
                type: FilteringEventType.TabReload,
                data: { tabId },
            });
        }
        const referrerUrl = originUrl
            || initiator
            // Comparison of the requested url with the tab frame url in case of
            // a navigation change from the browser address bar.
            || tabsApi.getTabMainFrame(tabId)?.url
            || tabsApi.getTabFrame(tabId, requestFrameId)?.url
            || url;
        // Retrieve the rest part of the request context for record all fields.
        const requestContext = requestContextStorage.create(requestId, {
            ...tabFrameRequestContext,
            requestFrameId,
            state: "beforeRequest" /* RequestContextState.BeforeRequest */,
            timestamp: timeStamp,
            thirdParty: isThirdPartyRequest(url, referrerUrl),
            referrerUrl,
            contentType,
            method: method,
        });
        return { details, context: requestContext };
    }
    /**
     * Handles onBeforeSendHeaders event.
     *
     * @param details WebRequest details.
     * @returns Request data.
     */
    static handleOnBeforeSendHeaders(details) {
        const { requestId, timeStamp, requestHeaders } = details;
        const context = requestContextStorage.update(requestId, {
            state: "beforeSendHeaders" /* RequestContextState.BeforeSendHeaders */,
            timestamp: timeStamp,
            requestHeaders,
        });
        return { details, context };
    }
    /**
     * Handles onSendHeaders event.
     *
     * @param details WebRequest details.
     * @returns Request data with context.
     */
    static handleSendHeaders(details) {
        const { requestId, timeStamp } = details;
        const context = requestContextStorage.update(requestId, {
            state: "sendHeaders" /* RequestContextState.SendHeaders */,
            timestamp: timeStamp,
        });
        return { details, context };
    }
    /**
     * Handles onHeadersReceived event.
     *
     * @param details WebRequest details.
     * @returns Request data with context.
     */
    static handleOnHeadersReceived(details) {
        const { requestId, responseHeaders, statusCode, } = details;
        /**
         * Firefox packs all cookies in a single set-cookie header concatenated with `\n`
         * https://bugzilla.mozilla.org/show_bug.cgi?id=1349151#c1.
         */
        if (responseHeaders && isFirefox) {
            CookieUtils.splitMultilineCookies(responseHeaders);
        }
        const context = requestContextStorage.update(requestId, {
            state: "headersReceived" /* RequestContextState.HeadersReceived */,
            responseHeaders,
            statusCode,
        });
        return { details, context };
    }
    /**
     * Handles onAuthRequired event.
     *
     * @param details WebRequest details.
     * @returns Request data with context.
     */
    static handleOnAuthRequired(details) {
        const { requestId, timeStamp } = details;
        const context = requestContextStorage.update(requestId, {
            state: "authRequired" /* RequestContextState.AuthRequired */,
            timestamp: timeStamp,
        });
        return { details, context };
    }
    /**
     * Handles onBeforeRedirect event.
     *
     * @param details WebRequest details.
     * @returns Request data with context.
     */
    static handleOnBeforeRedirect(details) {
        const { requestId, timeStamp } = details;
        const context = requestContextStorage.update(requestId, {
            state: "beforeRedirect" /* RequestContextState.BeforeRedirect */,
            timestamp: timeStamp,
        });
        return { details, context };
    }
    /**
     * Handles onResponseStarted event.
     *
     * @param details WebRequest details.
     * @returns Request data with context.
     */
    static handleOnResponseStarted(details) {
        const { requestId, timeStamp } = details;
        const context = requestContextStorage.update(requestId, {
            state: "responseStarted" /* RequestContextState.ResponseStarted */,
            timestamp: timeStamp,
        });
        return { details, context };
    }
    /**
     * Handles onCompleted event.
     *
     * @param details WebRequest details.
     * @returns Request data with context.
     */
    static handleOnCompleted(details) {
        const { requestId, timeStamp } = details;
        const context = requestContextStorage.update(requestId, {
            state: "completed" /* RequestContextState.Completed */,
            timestamp: timeStamp,
        });
        return { details, context };
    }
    /**
     * Handles onErrorOccurred event.
     *
     * @param details WebRequest details.
     * @returns Request data with context.
     */
    static handleOnErrorOccurred(details) {
        const { requestId, timeStamp } = details;
        const context = requestContextStorage.update(requestId, {
            state: "error" /* RequestContextState.Error */,
            timestamp: timeStamp,
        });
        return { details, context };
    }
}

/**
 * Cookie rules manager class.
 */
class CookieRulesFinder {
    /**
     * Filters blocking rules.
     * Used in content scripts.
     *
     * @param url Request url.
     * @param rules List of rules.
     * @returns Blocking rules.
     */
    static getBlockingRules(url, rules) {
        return rules.filter((rule) => !CookieRulesFinder.isModifyingRule(rule));
    }
    /**
     * Finds a rule that doesn't modify cookie:
     *  i.e.: this rule cancels cookie or if it's an allowlist rule.
     *
     * @param cookieName Cookie name.
     * @param rules List of network rules.
     * @param isThirdPartyCookie Flag that indicates if cookie is third-party.
     * @returns Found rule or null.
     */
    static lookupNotModifyingRule(cookieName, rules, isThirdPartyCookie) {
        const blockingRules = [];
        const allowlistRules = [];
        for (let i = 0; i < rules.length; i += 1) {
            const rule = rules[i];
            if (!CookieRulesFinder.matchThirdParty(rule, isThirdPartyCookie)) {
                continue;
            }
            const cookieModifier = rule.getAdvancedModifier();
            if (cookieModifier.matches(cookieName) && !CookieRulesFinder.isModifyingRule(rule)) {
                if (rule.isAllowlist()) {
                    allowlistRules.push(rule);
                }
                else {
                    blockingRules.push(rule);
                }
            }
        }
        if (allowlistRules.length > 0) {
            return allowlistRules[0];
        }
        if (blockingRules.length > 0) {
            return blockingRules[0];
        }
        return null;
    }
    /**
     * Finds rules that modify cookie.
     *
     * @param cookieName Cookie name.
     * @param rules Matching rules.
     * @param isThirdPartyCookie Flag that indicates if cookie is third-party.
     * @returns Modifying rules.
     */
    static lookupModifyingRules(cookieName, rules, isThirdPartyCookie) {
        const result = [];
        const allowlistRules = [];
        if (rules && rules.length > 0) {
            for (let i = 0; i < rules.length; i += 1) {
                const rule = rules[i];
                if (!CookieRulesFinder.matchThirdParty(rule, isThirdPartyCookie)) {
                    continue;
                }
                const cookieModifier = rule.getAdvancedModifier();
                if (!cookieModifier.matches(cookieName)) {
                    continue;
                }
                if (!rule.isAllowlist() && !CookieRulesFinder.isModifyingRule(rule)) {
                    return [];
                }
                if (rule.isAllowlist()) {
                    allowlistRules.push(rule);
                }
                else {
                    result.push(rule);
                }
            }
        }
        if (allowlistRules.length > 0) {
            return allowlistRules;
        }
        return result;
    }
    /**
     * Checks if rule and third party flag matches.
     *
     * @param rule Rule.
     * @param isThirdParty Flag that indicates if cookie is third-party.
     * @returns True if rule and third party flag matches.
     */
    static matchThirdParty(rule, isThirdParty) {
        if (!rule.isOptionEnabled(es/* NetworkRuleOption.ThirdParty */.SJ.ThirdParty)) {
            return true;
        }
        return isThirdParty === rule.isOptionEnabled(es/* NetworkRuleOption.ThirdParty */.SJ.ThirdParty);
    }
    /**
     * Checks if $cookie rule is modifying.
     *
     * @param rule $cookie rule.
     * @returns True if rule is modifying.
     */
    static isModifyingRule(rule) {
        const cookieModifier = rule.getAdvancedModifier();
        return cookieModifier.getSameSite() !== null
            || (cookieModifier.getMaxAge() !== null && cookieModifier.getMaxAge() > 0);
    }
}

/* eslint-disable class-methods-use-this */
/**
 * Cookie api implementation.
 */
class BrowserCookieApi {
    /**
     * Removes cookie.
     *
     * @param name Cookie name.
     * @param url Request url.
     * @returns True if cookie was removed.
     */
    async removeCookie(name, url) {
        try {
            await browser_polyfill_default().cookies.remove({ name, url });
            return true;
        }
        catch (e) {
            logger.error('[tswebextension.removeCookie]: error on removing cookie via browser.cookies.remove: ', e);
        }
        return false;
    }
    /**
     * Updates cookie.
     *
     * @param cookie Cookie for update.
     *
     * @returns Promise resolved with true if cookie was updated, false otherwise.
     */
    async modifyCookie(cookie) {
        try {
            const update = BrowserCookieApi.convertToSetDetailsType(cookie);
            await browser_polyfill_default().cookies.set(update);
            return true;
        }
        catch (e) {
            // If `domain` contains the `path` part, the cookie cannot be saved,
            // since `domain` can only contain hostname.
            if (cookie.domain?.includes('/')
                // if url is not matched with domain, cookie cannot be set
                // https://github.com/AdguardTeam/AdguardBrowserExtension/issues/2683
                || (cookie.domain && !BrowserCookieApi.doesDomainMatchUrl(cookie.domain, cookie.url))) {
                logger.info('[tswebextension.modifyCookie]: error on modifying cookie via browser.cookies.set: ', e);
            }
            else {
                logger.error('[tswebextension.modifyCookie]: error on modifying cookie via browser.cookies.set: ', e);
            }
        }
        return false;
    }
    /**
     * Search for cookies that match a given pattern.
     *
     * @param pattern Pattern of cookies to find.
     *
     * @returns List of found cookies.
     */
    async findCookies(pattern) {
        try {
            const found = await browser_polyfill_default().cookies.getAll(pattern);
            return found;
        }
        catch (e) {
            logger.error('[tswebextension.findCookies]: error on finding cookies via browser.cookies.getAll: ', e);
        }
        return [];
    }
    /**
     * Checks whether the cookie domain matches the url.
     *
     * @param rawCookieDomain Cookie domain.
     * @param url Request url.
     *
     * @returns True if domain matches the url, false otherwise.
     */
    static doesDomainMatchUrl(rawCookieDomain, url) {
        let cookieDomain = rawCookieDomain;
        // cookie domain can be '.example.com'
        if (cookieDomain.startsWith('.')) {
            cookieDomain = cookieDomain.slice(1);
        }
        const urlDomain = (0,es6/* getDomain */.ge)(url);
        return !!urlDomain && cookieDomain.includes(urlDomain);
    }
    /**
     * Converts cookie to SetDetailsType.
     *
     * @param cookie Cookie for convert.
     * @returns SetDetailsType.
     */
    static convertToSetDetailsType(cookie) {
        return {
            /**
             * The request-URI to associate with the setting of the cookie.
             * This value can affect the default domain and path values of the created cookie.
             * If host permissions for this URL are not specified in the manifest file, the API call will fail.
             */
            url: cookie.url,
            /**
             * The name of the cookie. Empty by default if omitted.
             */
            name: cookie.name,
            /**
             * The value of the cookie. Empty by default if omitted.
             */
            value: cookie.value,
            /**
             * The domain of the cookie. If omitted, the cookie becomes a host-only cookie.
             */
            domain: cookie.domain,
            /**
             * Whether the cookie should be marked as Secure. Defaults to false.
             */
            secure: cookie.secure,
            /**
             * Whether the cookie should be marked as HttpOnly. Defaults to false.
             */
            httpOnly: cookie.httpOnly,
            /**
             * The cookie's same-site status.
             */
            sameSite: BrowserCookieApi.getSameSiteStatus(cookie.sameSite),
            /**
             * The expiration date of the cookie as the number of seconds since the UNIX epoch.
             * If omitted, the cookie becomes a session cookie.
             */
            expirationDate: cookie.expires
                ? Math.floor(cookie.expires.getTime() / 1000)
                : undefined,
            /**
             * The path of the cookie. Defaults to the path portion of the url parameter.
             */
            path: cookie.path,
        };
    }
    /**
     * Returns same-site type.
     *
     * @param sameSite Same-site string.
     * @returns Same-site status or undefined if same-site is not specified.
     */
    static getSameSiteStatus(sameSite) {
        if (sameSite) {
            if (sameSite.toLowerCase() === 'lax') {
                return 'lax';
            }
            if (sameSite.toLowerCase() === 'strict') {
                return 'strict';
            }
        }
        return undefined;
    }
}

/**
 * Cookie filtering.
 *
 * The following public methods should be set as suitable webrequest events listeners, check sample extension in this
 * repo for an example.
 *
 * Logic introduction:
 *  CookieFiltering.onBeforeSendHeaders:
 *  - get all cookies for request url;
 *  - store cookies (first-party);
 *  - apply rules via modifying or removing them from headers
 *    and modifying or removing them with browser.cookies api;
 *
 *  CookieFiltering.onHeadersReceived:
 *  - parse set-cookie header, only to detect if the cookie in header will be set from third-party request;
 *  - save third-party flag for this cookie cookie.thirdParty=request.thirdParty;
 *  - apply rules via modifying or removing them from headers
 *    and modifying or removing them with browser.cookies api;
 *
 *  CookieFiltering.onCompleted:
 *  - apply rules via content script
 *  In content-scripts (check /src/content-script/cookie-controller.ts):
 *  - get matching cookie rules;
 *  - apply.
 */
class CookieFiltering {
    filteringLog;
    browserCookieApi = new BrowserCookieApi();
    /**
     * Constructor.
     *
     * @param filteringLog Filtering log.
     */
    constructor(filteringLog) {
        this.filteringLog = filteringLog;
    }
    /**
     * Parses cookies from headers.
     *
     * @param context Request context.
     *
     * @returns True if headers were modified.
     */
    onBeforeSendHeaders(context) {
        const { requestHeaders, requestUrl, requestId } = context;
        if (!requestHeaders || !requestUrl) {
            return false;
        }
        const cookieHeader = findHeaderByName$1(requestHeaders, 'Cookie');
        if (!cookieHeader?.value) {
            return false;
        }
        const cookies = CookieUtils.parseCookies(cookieHeader.value, requestUrl);
        if (cookies.length === 0) {
            return false;
        }
        // Saves cookies to context
        requestContextStorage.update(requestId, { cookies });
        // Removes cookies from browser with browser.cookies api, but not
        // removing them from context to correct process them in headers.
        // IMPORTANT: This method reads cookies from context, so it should be
        // called before method that change headers, since that method will
        // remove or change headers in context.
        this.applyRules(context)
            .catch((e) => {
            logger.error(e.message);
        });
        // Removes cookie from headers and updates context.
        // Note: this method won't work in the extension build with manifest v3.
        const headersModified = this.applyRulesToRequestCookieHeaders(context);
        return headersModified;
    }
    /**
     * Applies cookies to request headers.
     *
     * @param context Request context.
     * @returns True if headers were modified.
     */
    applyRulesToRequestCookieHeaders(context) {
        let headersModified = false;
        const { requestHeaders, cookies, matchingResult, requestUrl, thirdParty, tabId, requestId, } = context;
        if (!requestHeaders
            || !matchingResult
            || !requestUrl
            || typeof thirdParty !== 'boolean'
            || !cookies) {
            return headersModified;
        }
        const cookieRules = matchingResult.getCookieRules();
        for (let i = 0; i < cookies.length; i += 1) {
            const cookie = cookies[i];
            if (!cookie) {
                continue;
            }
            const bRule = CookieRulesFinder.lookupNotModifyingRule(cookie.name, cookieRules, thirdParty);
            if (bRule) {
                if (!bRule.isAllowlist()) {
                    // Remove from cookies array.
                    cookies.splice(i, 1);
                    // Move the loop counter back because we removed one element
                    // from the iterated array.
                    i -= 1;
                    headersModified = true;
                }
                this.recordCookieEvent(tabId, cookie, requestUrl, bRule, false, thirdParty);
            }
            const mRules = CookieRulesFinder.lookupModifyingRules(cookie.name, cookieRules, thirdParty);
            if (mRules.length > 0) {
                const appliedRules = CookieFiltering.applyRuleToBrowserCookie(cookie, mRules);
                if (appliedRules.length > 0) {
                    headersModified = true;
                }
                appliedRules.forEach((r) => {
                    this.recordCookieEvent(tabId, cookie, requestUrl, r, true, thirdParty);
                });
            }
        }
        if (headersModified) {
            const cookieHeaderIndex = requestHeaders.findIndex((header) => header.name.toLowerCase() === 'cookie');
            if (cookieHeaderIndex !== -1) {
                if (cookies.length > 0) {
                    // Update "cookie" header before send request to server.
                    requestHeaders[cookieHeaderIndex].value = CookieUtils.serializeCookieToRequestHeader(cookies);
                }
                else {
                    // Empty cookies, delete header "Cookie".
                    requestHeaders.splice(cookieHeaderIndex, 1);
                }
            }
            // Update headers and cookies in context.
            requestContextStorage.update(requestId, { requestHeaders, cookies });
        }
        return headersModified;
    }
    /**
     * Applies cookies to response headers.
     *
     * @param context Request context.
     * @returns True if headers were modified.
     */
    applyRulesToResponseCookieHeaders(context) {
        let headersModified = false;
        const { responseHeaders, matchingResult, requestUrl, thirdParty, tabId, requestId, } = context;
        if (!responseHeaders
            || !matchingResult
            || !requestUrl
            || typeof thirdParty !== 'boolean') {
            return headersModified;
        }
        const cookieRules = matchingResult.getCookieRules();
        for (let i = responseHeaders.length - 1; i >= 0; i -= 1) {
            const header = responseHeaders[i];
            const cookie = CookieUtils.parseSetCookieHeader(header, requestUrl);
            if (!cookie) {
                continue;
            }
            const bRule = CookieRulesFinder.lookupNotModifyingRule(cookie.name, cookieRules, thirdParty);
            if (bRule) {
                if (!bRule.isAllowlist()) {
                    responseHeaders.splice(i, 1);
                    headersModified = true;
                }
                this.recordCookieEvent(tabId, cookie, requestUrl, bRule, false, thirdParty);
            }
            const mRules = CookieRulesFinder.lookupModifyingRules(cookie.name, cookieRules, thirdParty);
            // Only apply if there is at least one non-allowlist rule
            if (mRules.length > 0 && mRules.some((r) => !r.isAllowlist())) {
                const appliedRules = CookieFiltering.applyRuleToBrowserCookie(cookie, mRules);
                if (appliedRules.length > 0) {
                    headersModified = true;
                    responseHeaders[i] = {
                        name: 'set-cookie',
                        value: CookieUtils.serializeCookieToResponseHeader(cookie),
                    };
                    appliedRules.forEach((r) => {
                        this.recordCookieEvent(tabId, cookie, requestUrl, r, true, thirdParty);
                    });
                }
            }
        }
        if (headersModified) {
            requestContextStorage.update(requestId, { responseHeaders });
        }
        return headersModified;
    }
    /**
     * Parses set-cookie header and looks up third-party cookies.
     * This callback won't work for mv3 extensions.
     * TODO separate or rewrite to mv2 and mv3 methods.
     *
     * @param context Request context.
     * @returns True if headers were modified.
     */
    onHeadersReceived(context) {
        const { responseHeaders, requestUrl, thirdParty, requestId, } = context;
        /**
         * Full context can be created in onBeforeRequest, partial context can
         * be created on every requestContextStorage.update method call and
         * because of that case - we explicitly checks fields in object.
         * TODO: Improve in AG-24428.
         */
        if (responseHeaders && requestUrl && typeof thirdParty !== 'undefined') {
            const cookies = CookieUtils.parseSetCookieHeaders(responseHeaders, requestUrl);
            const newCookies = cookies.filter((c) => !context.cookies?.includes(c));
            for (const cookie of newCookies) {
                cookie.thirdParty = thirdParty;
            }
            requestContextStorage.update(requestId, {
                cookies: context.cookies ? [...context.cookies, ...newCookies] : newCookies,
            });
        }
        // Removes cookies from browser with browser.cookies api, but not
        // removing them from context to correct process them in headers.
        // IMPORTANT: This method reads cookies from context, so it should be
        // called before method that change headers, since that method will
        // remove or change headers in context.
        this.applyRules(context)
            .catch((e) => {
            logger.error(e.message);
        });
        // Remove cookie headers.
        // This method won't work in the extension build with manifest v3.
        const headersModified = this.applyRulesToResponseCookieHeaders(context);
        return headersModified;
    }
    /**
     * TODO: Use isAppStarted with interval to re-request cookie rules if engine
     * is not started, as it implemented in CosmeticController.
     *
     * Looks up blocking rules for content-script.
     *
     * @param frameUrl Frame url.
     * @param tabId Tab id.
     * @param frameId Frame id.
     * @returns List of blocking rules.
     */
    // eslint-disable-next-line class-methods-use-this
    getBlockingRules(frameUrl, tabId, frameId) {
        const tabContext = tabsApi.getTabContext(tabId);
        if (!tabContext?.info.url) {
            return [];
        }
        const matchQuery = createFrameMatchQuery(frameUrl, frameId, tabContext);
        const matchingResult = engineApi.matchRequest(matchQuery);
        if (!matchingResult) {
            return [];
        }
        const cookieRules = matchingResult.getCookieRules();
        return CookieRulesFinder.getBlockingRules(matchQuery.requestUrl, cookieRules);
    }
    /**
     * Applies rules.
     *
     * @param context Request context.
     */
    async applyRules(context) {
        const { matchingResult, cookies, requestUrl, tabId, } = context;
        if (!matchingResult || !cookies) {
            return;
        }
        const cookieRules = matchingResult.getCookieRules();
        const promises = cookies.map(async (cookie) => {
            await this.applyRulesToCookie(cookie, cookieRules, requestUrl, tabId);
        });
        await Promise.all(promises);
    }
    /**
     * Attempts to find a "parent" cookie with a wider "path" field,
     * the scope of which includes the specified cookie from
     * the function parameters.
     *
     * This needs to prevent create of multiple "child"-cookies
     * and only modified expiration of general "parent"-cookie,
     * which covered "children"-cookies by 'path' value.
     *
     * @param cookie Cookie, for which need to find the "parent" cookie.
     *
     * @returns Item of parent cookie {@link ParsedCookie} or null if not found.
     */
    async findParentCookie(cookie) {
        const pattern = {
            url: cookie.url,
            name: cookie.name,
            domain: cookie.domain,
            secure: cookie.secure,
        };
        const parentCookies = await this.browserCookieApi.findCookies(pattern);
        const sortedParentCookies = parentCookies.sort((a, b) => a.path.length - b.path.length);
        for (let i = 0; i < sortedParentCookies.length; i += 1) {
            const parentCookie = sortedParentCookies[i];
            if (cookie.path?.startsWith(parentCookie.path)) {
                return ParsedCookie.fromBrowserCookie(parentCookie, cookie.url);
            }
        }
        return null;
    }
    /**
     * Applies rules to cookie.
     *
     * @param cookie Cookie.
     * @param cookieRules Cookie rules.
     * @param requestUrl Request URL, needs to record filtering event.
     * @param tabId Tab id.
     */
    async applyRulesToCookie(cookie, cookieRules, requestUrl, tabId) {
        const cookieName = cookie.name;
        const isThirdPartyCookie = cookie.thirdParty;
        const bRule = CookieRulesFinder.lookupNotModifyingRule(cookieName, cookieRules, isThirdPartyCookie);
        if (bRule) {
            if (bRule.isAllowlist() || await this.browserCookieApi.removeCookie(cookie.name, cookie.url)) {
                this.recordCookieEvent(tabId, cookie, requestUrl, bRule, false, isThirdPartyCookie);
            }
            return;
        }
        const mRules = CookieRulesFinder.lookupModifyingRules(cookieName, cookieRules, isThirdPartyCookie);
        if (mRules.length > 0) {
            // Try to find "parent" cookie and modify it instead of creating
            // "child copy" cookie.
            const parentCookie = await this.findParentCookie(cookie);
            const cookieToModify = parentCookie || cookie;
            const appliedRules = CookieFiltering.applyRuleToBrowserCookie(cookieToModify, mRules);
            if (appliedRules.length > 0) {
                if (await this.browserCookieApi.modifyCookie(cookieToModify)) {
                    appliedRules.forEach((r) => {
                        this.recordCookieEvent(tabId, cookieToModify, requestUrl, r, true, isThirdPartyCookie);
                    });
                }
            }
        }
    }
    /**
     * Modifies instance of {@link ParsedCookie} with provided rules.
     *
     * @param cookie Cookie modify.
     * @param rules Cookie matching rules.
     * @returns Applied rules.
     */
    static applyRuleToBrowserCookie(cookie, rules) {
        const appliedRules = [];
        for (let i = 0; i < rules.length; i += 1) {
            const rule = rules[i];
            if (rule.isAllowlist()) {
                appliedRules.push(rule);
                continue;
            }
            const cookieModifier = rule.getAdvancedModifier();
            let modified = false;
            const sameSite = cookieModifier.getSameSite();
            if (sameSite && cookie.sameSite !== sameSite) {
                // eslint-disable-next-line no-param-reassign
                cookie.sameSite = sameSite;
                modified = true;
            }
            const maxAge = cookieModifier.getMaxAge();
            if (maxAge) {
                if (CookieUtils.updateCookieMaxAge(cookie, maxAge)) {
                    modified = true;
                }
            }
            if (modified) {
                appliedRules.push(rule);
            }
        }
        return appliedRules;
    }
    /**
     * Records cookie event to filtering log.
     *
     * @param tabId Id of the tab.
     * @param cookie Item of {@link ParsedCookie}.
     * @param requestUrl URL of the request.
     * @param rule Applied modifying or deleting rule.
     * @param isModifyingCookieRule Is applied rule modifying or not.
     * @param requestThirdParty Whether request third party or not.
     */
    recordCookieEvent(tabId, cookie, requestUrl, rule, isModifyingCookieRule, requestThirdParty) {
        this.filteringLog.publishEvent({
            type: FilteringEventType.Cookie,
            data: {
                eventId: index_browser_nanoid(),
                tabId,
                cookieName: cookie.name,
                cookieValue: cookie.value,
                frameDomain: (0,es6/* getDomain */.ge)(requestUrl) || requestUrl,
                filterId: rule.getFilterListId(),
                ruleIndex: rule.getIndex(),
                isModifyingCookieRule,
                requestThirdParty,
                timestamp: Date.now(),
                requestType: ContentType.Cookie,
                isAllowlist: rule.isAllowlist(),
                isImportant: rule.isOptionEnabled(es/* NetworkRuleOption.Important */.SJ.Important),
                isDocumentLevel: rule.isDocumentLevelAllowlistRule(),
                isCsp: rule.isOptionEnabled(es/* NetworkRuleOption.Csp */.SJ.Csp),
                isCookie: rule.isOptionEnabled(es/* NetworkRuleOption.Cookie */.SJ.Cookie),
                advancedModifier: rule.getAdvancedModifierValue(),
            },
        });
    }
}
const cookieFiltering = new CookieFiltering(defaultFilteringLog);

/**
 * @file
 * This file contains constants for communication between background and content scripts.
 * This constants are separated from message.ts to reduce bundle size,
 * because rollup cannot tree-shake tswebextension library code.
 */
/**
 * Name of the message handler.
 * It is needed for determining specific tswebextension message from other messages.
 */
const MESSAGE_HANDLER_NAME = 'tsWebExtension';
/**
 * Message types for communication between background and content scripts.
 */
var MessageType;
(function (MessageType) {
    MessageType["ProcessShouldCollapse"] = "processShouldCollapse";
    MessageType["GetCosmeticData"] = "getCosmeticData";
    MessageType["GetCookieRules"] = "getCookieRules";
    MessageType["SaveCookieLogEvent"] = "saveCookieLogEvent";
    MessageType["InitAssistant"] = "initAssistant";
    MessageType["CloseAssistant"] = "closeAssistant";
    MessageType["AssistantCreateRule"] = "assistantCreateRule";
    MessageType["SaveCssHitsStats"] = "saveCssHitsStats";
})(MessageType || (MessageType = {}));

/**
 * Event channel wrapper for sending messages to the assistant.
 */
class Assistant {
    /**
     * Maximum time delay in milliseconds between the assistant frame creation and the assistant initialization.
     */
    static FRAME_CREATION_LIMIT_MS = 200;
    /**
     * Assistant frame URL.
     */
    static FRAME_URL = 'about:blank';
    static onCreateRule = new EventChannel();
    /**
     * Path to assembled @adguard/assistant module. Necessary for lazy on-demand
     * loading of the assistant.
     */
    static assistantUrl = '';
    /**
     * Sends message to assistant to open it on the page.
     *
     * @param tabId Tab id.
     */
    static async openAssistant(tabId) {
        // Lazy load assistant
        await browser_polyfill_default().tabs.executeScript(tabId, { file: this.assistantUrl });
        await messagesApi.sendMessage(tabId, {
            type: MessageType.InitAssistant,
            tabId,
            assistantUrl: this.assistantUrl,
        });
    }
    /**
     * Sends message to assistant to close it on the page.
     *
     * @param tabId Tab id.
     */
    static async closeAssistant(tabId) {
        await messagesApi.sendMessage(tabId, {
            type: MessageType.CloseAssistant,
        });
    }
    /**
     * Checks whether the frame is an assistant frame. Two conditions must be met:
     * 1. The frame was created less than {@link Assistant.FRAME_CREATION_LIMIT_MS} milliseconds
     *    after the assistant initialization.
     * 2. The frame is a child of the main frame.
     *
     * @see {@link https://github.com/AdguardTeam/AdguardBrowserExtension/issues/1848}
     *
     * @param details Frame details of the onDomContentLoaded event.
     * @param tabContext Tab context.
     *
     * @returns True if the frame is an assistant frame, false otherwise.
     */
    static async isAssistantFrame(details, tabContext) {
        if (!tabContext || !tabContext?.assistantInitTimestamp) {
            return false;
        }
        const { tabId, url, frameId, timeStamp, } = details;
        const newFrameData = await browser_polyfill_default().webNavigation.getFrame({ tabId, frameId });
        const timeSinceFrameCreatedMs = timeStamp - tabContext.assistantInitTimestamp;
        return timeSinceFrameCreatedMs < Assistant.FRAME_CREATION_LIMIT_MS
            && url === Assistant.FRAME_URL
            && newFrameData?.parentFrameId === MAIN_FRAME_ID;
    }
}

/**
 * @file
 * This file contains validation schemas and inferred types for message data.
 */
/**
 * Message DTO validation schema.
 */
const messageValidator = lib.z.object({
    handlerName: lib.z.literal(MESSAGE_HANDLER_NAME),
    type: lib.z.nativeEnum(MessageType),
    payload: lib.z.unknown(),
}).strict();
/**
 * {@link MessageType.ProcessShouldCollapse} Message payload validation schema.
 */
const processShouldCollapsePayloadValidator = lib.z.object({
    elementUrl: lib.z.string(),
    documentUrl: lib.z.string(),
    requestType: lib.z.nativeEnum(es/* RequestType */.xd),
}).strict();
/**
 * {@link MessageType.GetCosmeticData} Message payload validation schema.
 */
const getExtendedCssPayloadValidator = lib.z.object({
    documentUrl: lib.z.string(),
}).strict();
/**
 * {@link MessageType.GetCosmeticData} Message payload validation schema.
 */
const getCosmeticDataPayloadValidator = lib.z.object({
    documentUrl: lib.z.string(),
}).strict();
/**
 * {@link MessageType.GetCookieRules} Message payload validation schema.
 */
const getCookieRulesPayloadValidator = lib.z.object({
    documentUrl: lib.z.string(),
}).strict();
/**
 * {@link MessageType.SaveCookieLogEvent} Message payload validation schema.
 */
const getSaveCookieLogEventPayloadValidator = lib.z.object({
    cookieName: lib.z.string(),
    cookieDomain: lib.z.string(),
    cookieValue: lib.z.string(),
    filterId: lib.z.number(),
    ruleIndex: lib.z.number(),
    thirdParty: lib.z.boolean(),
    isAllowlist: lib.z.boolean(),
    isImportant: lib.z.boolean(),
    isDocumentLevel: lib.z.boolean(),
    isCsp: lib.z.boolean(),
    isCookie: lib.z.boolean(),
    advancedModifier: lib.z.string().nullable(),
}).strict();
/**
 * {@link MessageType.InitAssistant} Message payload validation schema.
 */
const getAssistantCreateRulePayloadValidator = lib.z.object({
    ruleText: lib.z.string(),
}).strict();

/* eslint-disable class-methods-use-this */
// TODO: add long live connection
// TODO: CollectHitStats
/**
 * Messages API implementation. It is used to communicate with content scripts.
 */
class MessagesApi {
    tabsApi;
    filteringLog;
    // TODO: use IoC container?
    /**
     * Assistant event listener.
     */
    onAssistantCreateRuleListener;
    /**
     * Messages API constructor.
     *
     * @param tabsApi Tabs API.
     * @param filteringLog Filtering log.
     */
    constructor(tabsApi, filteringLog) {
        this.tabsApi = tabsApi;
        this.filteringLog = filteringLog;
        this.handleMessage = this.handleMessage.bind(this);
    }
    /**
     * Sends message to the specified tab.
     *
     * @param tabId Tab ID.
     * @param message Message.
     */
    async sendMessage(tabId, message) {
        await browser_polyfill_default().tabs.sendMessage(tabId, message);
    }
    /**
     * Messages handler.
     *
     * @param message Message object.
     * @param sender Tab which sent the message.
     *
     * @returns Promise resolved with response to the message.
     */
    // TODO remove the rule bellow, and any
    // eslint-disable-next-line @typescript-eslint/no-explicit-any
    async handleMessage(message, sender) {
        try {
            message = messageValidator.parse(message);
        }
        catch (e) {
            // ignore
            return undefined;
        }
        const { type } = message;
        switch (type) {
            case MessageType.ProcessShouldCollapse: {
                return this.handleProcessShouldCollapseMessage(sender, message.payload);
            }
            case MessageType.GetCosmeticData: {
                return this.handleContentScriptDataMessage(sender, message.payload);
            }
            case MessageType.GetCookieRules: {
                return this.handleGetCookieRulesMessage(sender, message.payload);
            }
            case MessageType.SaveCookieLogEvent: {
                return this.handleSaveCookieLogEvent(sender, message.payload);
            }
            case MessageType.AssistantCreateRule: {
                return this.handleAssistantCreateRuleMessage(sender, message.payload);
            }
            case MessageType.SaveCssHitsStats: {
                return this.handleSaveCssHitsStats(sender, message.payload);
            }
        }
        return undefined;
    }
    /**
     * Handles should collapse element message.
     *
     * @param sender Tab, which sent message.
     * @param payload Message payload.
     * @returns True if element should be collapsed.
     */
    handleProcessShouldCollapseMessage(sender, payload) {
        if (!payload || !sender?.tab?.id) {
            return false;
        }
        const res = processShouldCollapsePayloadValidator.safeParse(payload);
        if (!res.success) {
            return false;
        }
        const tabId = sender.tab.id;
        const { elementUrl, documentUrl, requestType } = res.data;
        return RequestBlockingApi.shouldCollapseElement(tabId, elementUrl, documentUrl, requestType);
    }
    /**
     * Handles get extended css message.
     *
     * @param sender Tab, which sent message.
     * @param payload Message payload.
     * @returns Extended css string or false or undefined.
     */
    handleContentScriptDataMessage(sender, payload) {
        if (!payload || !sender?.tab?.id) {
            return null;
        }
        const res = getExtendedCssPayloadValidator.safeParse(payload);
        if (!res.success) {
            return null;
        }
        const tabId = sender.tab.id;
        let { frameId } = sender;
        if (!frameId) {
            frameId = 0;
        }
        return CosmeticApi.getContentScriptData(res.data.documentUrl, tabId, frameId);
    }
    /**
     * Handles messages.
     * Returns cookie rules data for content script.
     *
     * @param sender Tab, which sent message.
     * @param payload Message payload.
     * @returns Cookie rules data.
     */
    handleGetCookieRulesMessage(sender, payload) {
        if (!payload || !sender?.tab?.id) {
            return [];
        }
        const res = getCookieRulesPayloadValidator.safeParse(payload);
        if (!res.success) {
            return [];
        }
        const tabId = sender.tab.id;
        let { frameId } = sender;
        if (!frameId) {
            frameId = 0;
        }
        const cookieRules = cookieFiltering.getBlockingRules(res.data.documentUrl, tabId, frameId);
        return cookieRules.map((rule) => ({
            ruleIndex: rule.getIndex(),
            match: rule.getAdvancedModifierValue(),
            isThirdParty: rule.isOptionEnabled(es/* NetworkRuleOption.ThirdParty */.SJ.ThirdParty),
            filterId: rule.getFilterListId(),
            isAllowlist: rule.isAllowlist(),
            isImportant: rule.isOptionEnabled(es/* NetworkRuleOption.Important */.SJ.Important),
            isDocumentLevel: rule.isDocumentLevelAllowlistRule(),
            isCsp: rule.isOptionEnabled(es/* NetworkRuleOption.Csp */.SJ.Csp),
            isCookie: rule.isOptionEnabled(es/* NetworkRuleOption.Cookie */.SJ.Cookie),
            advancedModifier: rule.getAdvancedModifierValue(),
        }));
    }
    /**
     * Calls filtering to add an event from cookie-controller content-script.
     *
     * @param sender Tab which sent the message.
     * @param payload Message payload.
     * @returns True if event was published to filtering log.
     */
    handleSaveCookieLogEvent(sender, payload) {
        if (!payload || !sender?.tab?.id) {
            return false;
        }
        const res = getSaveCookieLogEventPayloadValidator.safeParse(payload);
        if (!res.success) {
            return false;
        }
        const { data } = res;
        this.filteringLog.publishEvent({
            type: FilteringEventType.Cookie,
            data: {
                eventId: index_browser_nanoid(),
                tabId: sender.tab.id,
                cookieName: data.cookieName,
                frameDomain: data.cookieDomain,
                cookieValue: data.cookieValue,
                filterId: data.filterId,
                ruleIndex: data.ruleIndex,
                isModifyingCookieRule: false,
                requestThirdParty: data.thirdParty,
                timestamp: Date.now(),
                requestType: ContentType.Cookie,
                // Additional rule properties
                isAllowlist: data.isAllowlist,
                isImportant: data.isImportant,
                isDocumentLevel: data.isDocumentLevel,
                isCsp: data.isCsp,
                isCookie: data.isCookie,
                advancedModifier: data.advancedModifier,
            },
        });
        return true;
    }
    /**
     * Handles message with new rule from assistant content script.
     *
     * @param sender Tab, which sent message.
     * @param payload Message payload.
     * @returns True if rule was dispatched.
     */
    handleAssistantCreateRuleMessage(sender, payload) {
        if (!payload || !sender?.tab?.id) {
            return false;
        }
        const res = getAssistantCreateRulePayloadValidator.safeParse(payload);
        if (!res.success) {
            return false;
        }
        const { ruleText } = res.data;
        Assistant.onCreateRule.dispatch(ruleText);
        return true;
    }
    /**
     * Handle message about saving css hits stats.
     *
     * @param sender Tab, which sent message.
     * @param payload Message payload.
     * @returns True if stats was saved.
     */
    handleSaveCssHitsStats(sender, 
    // TODO add payload type
    // eslint-disable-next-line @typescript-eslint/no-explicit-any
    payload) {
        if (!payload || !sender?.tab?.id) {
            return false;
        }
        const tabId = sender.tab.id;
        const tabContext = this.tabsApi.getTabContext(tabId);
        if (!tabContext?.info.url) {
            return false;
        }
        const { url } = tabContext.info;
        let published = false;
        for (let i = 0; i < payload.length; i += 1) {
            const stat = payload[i];
            this.filteringLog.publishEvent({
                type: FilteringEventType.ApplyCosmeticRule,
                data: {
                    tabId,
                    eventId: index_browser_nanoid(),
                    filterId: stat.filterId,
                    ruleIndex: stat.ruleIndex,
                    element: stat.element,
                    frameUrl: url,
                    frameDomain: getDomain(url),
                    requestType: ContentType.Document,
                    timestamp: Date.now(),
                    cssRule: true,
                    scriptRule: false,
                    contentRule: false,
                },
            });
            published = true;
        }
        return published;
    }
}

/**
 * Injects cosmetic rules into tabs, opened before app initialization.
 */
class TabsCosmeticInjector {
    engineApi;
    documentApi;
    tabsApi;
    /**
     * Create instance of TabsCosmeticInjector.
     *
     * @param engineApi Engine API.
     * @param documentApi  Document API.
     * @param tabsApi  Tabs API.
     */
    constructor(engineApi, documentApi, tabsApi) {
        this.engineApi = engineApi;
        this.documentApi = documentApi;
        this.tabsApi = tabsApi;
    }
    /**
     * Creates contexts for tabs opened before api initialization and
     * applies cosmetic rules for each frame.
     */
    async processOpenTabs() {
        const currentTabs = await browser.tabs.query({});
        const tasks = currentTabs.map((tab) => this.processOpenTab(tab));
        const promises = await Promise.allSettled(tasks);
        // Handles errors
        promises.forEach((promise) => {
            if (promise.status === 'rejected') {
                logger.error(promise.reason);
            }
        });
        appContext.cosmeticsInjectedOnStartup = true;
    }
    /**
     * Creates context for tab opened before api initialization and
     * applies cosmetic rules for each frame.
     *
     * @param tab Tab details.
     */
    async processOpenTab(tab) {
        if (!TabContext.isBrowserTab(tab)) {
            return;
        }
        const { url } = tab;
        const tabContext = new TabContext(tab, this.documentApi);
        const tabId = tab.id;
        this.tabsApi.context.set(tabId, tabContext);
        // https://github.com/AdguardTeam/AdguardBrowserExtension/issues/2549
        if (url && isHttpRequest(url)) {
            tabContext.mainFrameRule = this.documentApi.matchFrame(url);
        }
        const frames = await browser.webNavigation.getAllFrames({ tabId });
        if (!frames) {
            return;
        }
        frames.forEach(({ frameId, url: frameUrl }) => {
            const frame = new Frame(frameUrl);
            tabContext.frames.set(frameId, frame);
            if (!isHttpOrWsRequest(frameUrl)) {
                return;
            }
            const isDocumentFrame = frameId === MAIN_FRAME_ID;
            frame.matchingResult = this.engineApi.matchRequest({
                requestUrl: frameUrl,
                frameUrl,
                requestType: isDocumentFrame ? RequestType.Document : RequestType.SubDocument,
                frameRule: tabContext.mainFrameRule,
            });
            if (!frame.matchingResult) {
                return;
            }
            // TODO: Instead of this, it’s better to use the runtime.onStartup and runtime.onInstalled
            // events to inject cosmetics once during the extension's initialization
            // and browser startup without flags.
            // However, this would require big refactoring of the extension.
            /**
             * This condition prevents applying cosmetic rules to the tab multiple times.
             * Applying them once after the extension's initialization is sufficient.
             */
            if (appContext.cosmeticsInjectedOnStartup) {
                return;
            }
            const cosmeticOption = frame.matchingResult.getCosmeticOption();
            frame.cosmeticResult = this.engineApi.getCosmeticResult(frameUrl, cosmeticOption);
            const { cosmeticResult } = frame;
            CosmeticApi.applyFrameCssRules(frameId, tabId);
            CosmeticApi.applyFrameJsRules(frameId, tabId);
            CosmeticApi.logScriptRules({
                url: frameUrl,
                tabId,
                cosmeticResult,
                timestamp: Date.now(),
                contentType: isDocumentFrame
                    ? ContentType.Document
                    : ContentType.Subdocument,
            });
        });
    }
}

/**
 * Headers filtering service module.
 */
class RemoveHeadersService {
    filteringLog;
    /**
     * Constructor.
     *
     * @param filteringLog Filtering log.
     */
    constructor(filteringLog) {
        this.filteringLog = filteringLog;
    }
    /**
     * Modifies headers by applying $removeheader rules.
     *
     * @param context Request context.
     * @param isRequestHeaders Is headers are _request_ headers, i.e. `false`
     * for _response_ headers.
     * @param headersToModify Headers to modify.
     *
     * @returns True if headers were modified.
     */
    modifyHeaders(context, isRequestHeaders, headersToModify) {
        const { matchingResult, tabId, requestUrl, contentType, timestamp, } = context;
        if (!headersToModify || !matchingResult) {
            return false;
        }
        const rules = matchingResult.getRemoveHeaderRules();
        if (rules.length === 0) {
            return false;
        }
        let isModified = false;
        rules.forEach((rule) => {
            let isAppliedRule = false;
            if (rule.isAllowlist()) {
                // Allowlist rules must be applicable by header name to be logged
                isAppliedRule = RemoveHeadersService
                    .isApplicableRemoveHeaderRule(headersToModify, rule, isRequestHeaders);
            }
            else {
                isAppliedRule = RemoveHeadersService.applyRule(headersToModify, rule, isRequestHeaders);
                if (!isModified && isAppliedRule) {
                    isModified = true;
                }
            }
            if (isAppliedRule) {
                this.filteringLog.publishEvent({
                    type: FilteringEventType.RemoveHeader,
                    data: {
                        removeHeader: true,
                        headerName: rule.getAdvancedModifierValue(),
                        eventId: index_browser_nanoid(),
                        tabId,
                        requestUrl,
                        frameUrl: requestUrl,
                        frameDomain: getDomain(requestUrl),
                        requestType: contentType,
                        timestamp,
                        filterId: rule.getFilterListId(),
                        ruleIndex: rule.getIndex(),
                        isAllowlist: rule.isAllowlist(),
                        isImportant: rule.isOptionEnabled(es/* NetworkRuleOption.Important */.SJ.Important),
                        isDocumentLevel: rule.isDocumentLevelAllowlistRule(),
                        isCsp: rule.isOptionEnabled(es/* NetworkRuleOption.Csp */.SJ.Csp),
                        isCookie: rule.isOptionEnabled(es/* NetworkRuleOption.Cookie */.SJ.Cookie),
                        advancedModifier: rule.getAdvancedModifierValue(),
                    },
                });
            }
        });
        return isModified;
    }
    /**
     * On before send headers handler.
     * Removes request headers.
     *
     * @param context Request context.
     * @returns True if headers were modified.
     */
    onBeforeSendHeaders(context) {
        const { requestHeaders, requestId } = context;
        const isModified = this.modifyHeaders(context, true, requestHeaders);
        if (isModified) {
            requestContextStorage.update(requestId, { requestHeaders });
        }
        return isModified;
    }
    /**
     * On headers received handler.
     * Removes response headers.
     *
     * @param context Request context.
     * @returns True if headers were modified.
     */
    onHeadersReceived(context) {
        const { responseHeaders, requestId } = context;
        const isModified = this.modifyHeaders(context, false, responseHeaders);
        if (isModified) {
            requestContextStorage.update(requestId, { responseHeaders });
        }
        return isModified;
    }
    /**
     * Applies rule to headers. Removes header from headers if rule matches.
     * Important: this method modifies headers array as they are passed by reference.
     *
     * @param headers Headers.
     * @param rule Rule to apply if it has remove header modifier.
     * @param isRequestHeaders Is headers are _request_ headers, i.e. `false`
     * for _response_ headers.
     *
     * @returns True if headers removed by rule.
     */
    static applyRule(headers, rule, isRequestHeaders) {
        const headerName = RemoveHeadersService.getApplicableHeaderName(rule, isRequestHeaders);
        if (!headerName) {
            return false;
        }
        return removeHeader(headers, headerName);
    }
    /**
     * Checks if rule is applicable to headers.
     *
     * @param headers   Headers.
     * @param rule  Rule with $removeheader modifier.
     * @param isRequestHeaders Is headers are _request_ headers, i.e. `false`
     * for _response_ headers.
     *
     * @returns True if rule is applicable.
     */
    static isApplicableRemoveHeaderRule(headers, rule, isRequestHeaders) {
        const headerName = RemoveHeadersService.getApplicableHeaderName(rule, isRequestHeaders);
        if (!headerName) {
            return false;
        }
        return !!findHeaderByName(headers, headerName);
    }
    /**
     * Returns header name if rule has remove header modifier and it is applicable.
     *
     * @param rule Rule with $removeheader modifier.
     * @param isRequestHeaders Is headers are _request_ headers, i.e. `false`
     * for _response_ headers.
     *
     * @returns Header name or null if rule is not applicable.
     */
    static getApplicableHeaderName(rule, isRequestHeaders) {
        const modifier = rule.getAdvancedModifier();
        if (!modifier) {
            return null;
        }
        const headerName = modifier.getApplicableHeaderName(isRequestHeaders);
        if (!headerName) {
            return null;
        }
        return headerName;
    }
}
const removeHeadersService = new RemoveHeadersService(defaultFilteringLog);

/**
 * Params filtering service module.
 */
class ParamsService {
    filteringLog;
    /**
     * Constructor.
     *
     * @param filteringLog Filtering log.
     */
    constructor(filteringLog) {
        this.filteringLog = filteringLog;
    }
    static SupportedMethods = ['GET', 'POST', 'OPTIONS', 'HEAD'];
    /**
     * Removes request params from url, stored in request context.
     *
     * @param requestId Request id.
     * @returns Modified url or null.
     */
    getPurgedUrl(requestId) {
        const context = requestContextStorage.get(requestId);
        if (!context) {
            return null;
        }
        const { matchingResult, method, requestUrl, contentType, timestamp, } = context;
        if (!matchingResult || !ParamsService.isMethodSupported(method)) {
            return null;
        }
        const removeParamRules = matchingResult.getRemoveParamRules();
        if (removeParamRules.length === 0) {
            return null;
        }
        const purgedUrl = removeParamRules.reduce((url, rule) => {
            if (rule.isAllowlist()) {
                this.filteringLog.publishEvent({
                    type: FilteringEventType.RemoveParam,
                    data: {
                        removeParam: true,
                        eventId: index_browser_nanoid(),
                        tabId: context.tabId,
                        requestUrl: url,
                        frameUrl: url,
                        frameDomain: getDomain(url),
                        requestType: contentType,
                        filterId: rule.getFilterListId(),
                        ruleIndex: rule.getIndex(),
                        timestamp,
                        isAllowlist: rule.isAllowlist(),
                        isImportant: rule.isOptionEnabled(es/* NetworkRuleOption.Important */.SJ.Important),
                        isDocumentLevel: rule.isDocumentLevelAllowlistRule(),
                        isCsp: rule.isOptionEnabled(es/* NetworkRuleOption.Csp */.SJ.Csp),
                        isCookie: rule.isOptionEnabled(es/* NetworkRuleOption.Cookie */.SJ.Cookie),
                        advancedModifier: rule.getAdvancedModifierValue(),
                    },
                });
                return url;
            }
            const modifier = rule.getAdvancedModifier();
            const modifiedUrl = modifier.removeParameters(url);
            const hasUrlChanged = modifiedUrl !== url;
            if (hasUrlChanged) {
                context.isRemoveparamRedirect = true;
                this.filteringLog.publishEvent({
                    type: FilteringEventType.RemoveParam,
                    data: {
                        removeParam: true,
                        eventId: index_browser_nanoid(),
                        tabId: context.tabId,
                        requestUrl: modifiedUrl,
                        frameUrl: modifiedUrl,
                        frameDomain: getDomain(modifiedUrl),
                        requestType: contentType,
                        filterId: rule.getFilterListId(),
                        ruleIndex: rule.getIndex(),
                        timestamp,
                        isAllowlist: rule.isAllowlist(),
                        isImportant: rule.isOptionEnabled(es/* NetworkRuleOption.Important */.SJ.Important),
                        isDocumentLevel: rule.isDocumentLevelAllowlistRule(),
                        isCsp: rule.isOptionEnabled(es/* NetworkRuleOption.Csp */.SJ.Csp),
                        isCookie: rule.isOptionEnabled(es/* NetworkRuleOption.Cookie */.SJ.Cookie),
                        advancedModifier: rule.getAdvancedModifierValue(),
                    },
                });
            }
            return modifier.removeParameters(url);
        }, requestUrl);
        if (purgedUrl === requestUrl) {
            return null;
        }
        return purgedUrl;
    }
    /**
     * Checks if we support requests for specified method.
     *
     * @param method Request method.
     * @returns True if method supported.
     */
    static isMethodSupported(method) {
        return ParamsService.SupportedMethods.includes(method.toUpperCase());
    }
}
const paramsService = new ParamsService(defaultFilteringLog);

/**
 * Handles HTML entities.
 * This is a workaround for the following issue:
 * https://github.com/AdguardTeam/AdguardBrowserExtension/issues/2249
 * website was broken because win-1251 charset doesn't support some entities, e.g., ❤,
 * which initially in the html string was &#10084 and after parsing became ❤.
 */
class EntityHandler {
    /**
     * Escapes specific entities in an HTML string.
     * @param html String to escape.
     * @returns Escaped string.
     */
    static escapeEntities(html) {
        return html.replace(/&#x([A-Fa-f0-9]{4});/g, '&amp;#x$1;');
    }
    /**
     * Reverts escaped entities back to their original form.
     * @param html String to revert.
     * @returns Reverted string.
     */
    static revertEntities(html) {
        return html.replace(/&amp;#x([A-Fa-f0-9]{4});/g, '&#x$1;');
    }
}

/**
 * Document parser wrapper.
 */
class DocumentParser {
    parser;
    parsererrorNS;
    /**
     * Constructor.
     */
    constructor() {
        // eslint-disable-next-line no-undef
        this.parser = new DOMParser();
        const errorneousParse = this.parser.parseFromString('<', 'text/xml');
        this.parsererrorNS = errorneousParse.getElementsByTagName('parsererror')[0].namespaceURI;
    }
    /**
     * Checks for parse errors.
     * {@link https://developer.mozilla.org/en-US/docs/Web/API/DOMParser#Error_handling}.
     *
     * @param parsedDocument Parsed document.
     * @returns True if document cannot be parsed.
     */
    isParseError(parsedDocument) {
        if (this.parsererrorNS === 'http://www.w3.org/1999/xhtml') {
            return parsedDocument.getElementsByTagName('parsererror').length > 0;
        }
        return parsedDocument.getElementsByTagNameNS(this.parsererrorNS, 'parsererror').length > 0;
    }
    /**
     * Parse html to document.
     *
     * @param html HTML content.
     * @returns Document or null if parse error occurred.
     */
    parse(html) {
        const doc = this.parser.parseFromString(EntityHandler.escapeEntities(html), 'text/html');
        if (this.isParseError(doc)) {
            return null;
        }
        return doc;
    }
}
const documentParser = new DocumentParser();

/**
 * Html rule wildcard.
 */
class Wildcard {
    regexp;
    shortcut;
    /**
     * Constructor.
     *
     * @param pattern Wildcard pattern.
     */
    constructor(pattern) {
        this.regexp = new RegExp(Wildcard.wildcardToRegex(pattern), 'i');
        this.shortcut = Wildcard.extractShortcut(pattern);
    }
    /**
     * Returns 'true' if input text is matching wildcard.
     * This method first checking shortcut -- if shortcut exists in input string -- than it checks regexp.
     *
     * @param input Input string.
     * @returns Boolean if input string matches wildcard.
     */
    matches(input) {
        if (!input) {
            return false;
        }
        if (input.toLowerCase().indexOf(this.shortcut) < 0) {
            return false;
        }
        return this.regexp.test(input);
    }
    /**
     * Converts wildcard to regular expression.
     *
     * @param pattern The wildcard pattern to convert.
     * @returns A regex equivalent of the given wildcard.
     */
    static wildcardToRegex(pattern) {
        const specials = [
            '\\', '*', '+', '?', '|', '{', '}', '[', ']', '(', ')', '^', '$', '.', '#',
        ];
        const specialsRegex = new RegExp(`[${specials.join('\\')}]`, 'g');
        let result = pattern.replace(specialsRegex, '\\$&');
        result = replaceAll(result, '\\*', '[\\s\\S]*');
        result = replaceAll(result, '\\?', '.');
        return `^${result}$`;
    }
    /**
     * Extracts the longest string that does not contain "*" or "?" symbols.
     *
     * @param pattern Wildcard pattern.
     * @returns Longest string without special symbols.
     */
    static extractShortcut(pattern) {
        const wildcardChars = ['*', '?'];
        let startIndex = 0;
        let endIndex = indexOfAny(pattern, wildcardChars);
        if (endIndex < 0) {
            return pattern.toLowerCase();
        }
        let shortcut = endIndex === startIndex ? '' : pattern.substring(startIndex, endIndex - startIndex);
        while (endIndex >= 0) {
            startIndex = startIndex + endIndex + 1;
            if (pattern.length <= startIndex) {
                break;
            }
            endIndex = indexOfAny(pattern.substring(startIndex), wildcardChars);
            // eslint-disable-next-line max-len
            const tmpShortcut = endIndex < 0 ? pattern.substring(startIndex) : pattern.substring(startIndex, endIndex + startIndex);
            if (tmpShortcut.length > shortcut.length) {
                shortcut = tmpShortcut;
            }
        }
        return shortcut.toLowerCase();
    }
}

/**
 * Html rule attributes.
 *
 * @example
 * rule = [domains] "$$" tagName [attributes]
 * domains = [domain0, domain1[, ...[, domainN]]]
 * attributes = "[" name0 = value0 "]" "[" name1 = value2 "]" ... "[" nameN = valueN "]"
 *
 * https://kb.adguard.com/en/general/how-to-create-your-own-ad-filters#html-filtering-rules-syntax-1
 */
class HtmlRuleAttributes {
    /**
     * Tag name attribute.
     */
    tagName;
    /**
     * Composed selector.
     * Parsed [attributes] excepting special attributes are joined here to be a valid css selector string.
     * Example:
     * For "example.org$$div[id="ad_text"][tag-content="teas""ernet"]" rule, css selector will be "div[id*="ad_text"]".
     */
    selector;
    /**
     * Parent search level attribute.
     */
    parentSearchLevel;
    /**
     * Max length attribute
     * 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.
     */
    maxLength;
    /**
     * This is the most frequently used special attribute.
     * It limits selection with those elements whose innerHTML code contains the specified substring.
     */
    tagContentFilter;
    /**
     * This special attribute works almost like tag-content and allows you to check the innerHTML code of the document.
     * Rule will check if HTML code of the element fits to the search pattern.
     */
    wildcard;
    /**
     * Specifies the minimum length for content of HTML element.
     * If this parameter is set and the content length is less than preset value - a rule does not apply to the element.
     */
    minLength;
    /**
     * Parent elements attributes.
     */
    parentElements;
}

/**
 * Encapsulates html rule attributes parsing.
 */
class HtmlRuleParser {
    static ATTRIBUTE_START_MARK = (/* unused pure expression or super */ null && ('['));
    static ATTRIBUTE_END_MARK = (/* unused pure expression or super */ null && (']'));
    static QUOTES = (/* unused pure expression or super */ null && ('"'));
    static TAG_CONTENT_MASK = (/* unused pure expression or super */ null && ('tag-content'));
    static WILDCARD_MASK = (/* unused pure expression or super */ null && ('wildcard'));
    static TAG_CONTENT_MAX_LENGTH = (/* unused pure expression or super */ null && ('max-length'));
    static TAG_CONTENT_MIN_LENGTH = (/* unused pure expression or super */ null && ('min-length'));
    static PARENT_ELEMENTS = (/* unused pure expression or super */ null && ('parent-elements'));
    static PARENT_SEARCH_LEVEL = (/* unused pure expression or super */ null && ('parent-search-level'));
    static DEFAULT_PARENT_SEARCH_LEVEL = (/* unused pure expression or super */ null && (3));
    static DEFAULT_MAX_LENGTH = (/* unused pure expression or super */ null && (8192));
    /**
     * Parses html rule.
     *
     * @param rule Rule to parse.
     * @returns Parsed rule attributes.
     */
    static parse(rule) {
        const result = new HtmlRuleAttributes();
        result.parentSearchLevel = HtmlRuleParser.DEFAULT_PARENT_SEARCH_LEVEL;
        result.maxLength = HtmlRuleParser.DEFAULT_MAX_LENGTH;
        const ruleContent = rule.getContent();
        let htmlAttributesStartIndex = ruleContent.indexOf(HtmlRuleParser.ATTRIBUTE_START_MARK);
        // Cutting tag name from string
        if (htmlAttributesStartIndex === -1) {
            result.tagName = ruleContent;
        }
        else {
            result.tagName = ruleContent.substring(0, htmlAttributesStartIndex);
        }
        const selector = [result.tagName];
        // Loading attributes filter
        while (htmlAttributesStartIndex !== -1) {
            const equalityIndex = ruleContent.indexOf('=', htmlAttributesStartIndex + 1);
            const quoteStartIndex = ruleContent.indexOf(HtmlRuleParser.QUOTES, equalityIndex + 1);
            const quoteEndIndex = HtmlRuleParser.getClosingQuoteIndex(ruleContent, quoteStartIndex + 1);
            if (quoteStartIndex === -1 || quoteEndIndex === -1) {
                break;
            }
            const ruleEndIndex = ruleContent.indexOf(HtmlRuleParser.ATTRIBUTE_END_MARK, quoteEndIndex + 1);
            const attributeName = ruleContent.substring(htmlAttributesStartIndex + 1, equalityIndex);
            let attributeValue = ruleContent.substring(quoteStartIndex + 1, quoteEndIndex);
            attributeValue = replaceAll(attributeValue, '""', '"');
            switch (attributeName) {
                case HtmlRuleParser.TAG_CONTENT_MASK:
                    result.tagContentFilter = attributeValue;
                    break;
                case HtmlRuleParser.WILDCARD_MASK:
                    result.wildcard = new Wildcard(attributeValue);
                    break;
                case HtmlRuleParser.TAG_CONTENT_MAX_LENGTH:
                    result.maxLength = parseInt(attributeValue, 10);
                    break;
                case HtmlRuleParser.TAG_CONTENT_MIN_LENGTH:
                    result.minLength = parseInt(attributeValue, 10);
                    break;
                case HtmlRuleParser.PARENT_ELEMENTS:
                    result.parentElements = attributeValue.split(',');
                    break;
                case HtmlRuleParser.PARENT_SEARCH_LEVEL:
                    result.parentSearchLevel = parseInt(attributeValue, 10);
                    break;
                default:
                    selector.push('[');
                    selector.push(attributeName);
                    selector.push('*="');
                    selector.push(attributeValue);
                    selector.push('"]');
                    break;
            }
            if (ruleEndIndex === -1) {
                break;
            }
            htmlAttributesStartIndex = ruleContent.indexOf(HtmlRuleParser.ATTRIBUTE_START_MARK, ruleEndIndex + 1);
        }
        result.selector = selector.join('');
        // Validates selector immediately
        // eslint-disable-next-line no-undef
        if (typeof window !== 'undefined') {
            window.document.querySelectorAll(result.selector);
        }
        return result;
    }
    /**
     * Looks up next closing quotation starting from start index.
     * Skips double quotes in text like:
     *  [tag-content="teas""ernet"].
     *
     * @param text Text to search.
     * @param startIndex Start index.
     * @returns Index of closing double quotation `"` found, or `-1` if not found.
     */
    static getClosingQuoteIndex(text, startIndex) {
        let nextChar = HtmlRuleParser.QUOTES;
        let quoteIndex = startIndex - 2;
        while (nextChar === '"') {
            quoteIndex = text.indexOf(HtmlRuleParser.QUOTES, quoteIndex + 2);
            if (quoteIndex === -1) {
                return -1;
            }
            nextChar = text.length === (quoteIndex + 1) ? '0' : text.charAt(quoteIndex + 1);
        }
        return quoteIndex;
    }
}

/**
 * Encapsulates document element matching.
 */
class HtmlRuleSelector {
    /**
     * Html Rule parse result.
     */
    ruleAttributes;
    /**
     * Constructor.
     *
     * @param parsedHtmlRule Html rule attributes.
     */
    constructor(parsedHtmlRule) {
        this.ruleAttributes = parsedHtmlRule;
    }
    /**
     * Returns elements matched by provided html rule.
     *
     * @param doc Document object.
     * @returns Array of elements or null.
     */
    getMatchedElements(doc) {
        const elements = doc.querySelectorAll(this.ruleAttributes.selector);
        let result = null;
        for (let i = 0; i < elements.length; i += 1) {
            const element = elements[i];
            let elementToDelete = null;
            if (this.isFiltered(element)) {
                if (this.ruleAttributes.parentElements) {
                    const parentElement = this.searchForParentElement(element);
                    if (parentElement) {
                        elementToDelete = parentElement;
                    }
                }
                else {
                    elementToDelete = element;
                }
                if (elementToDelete) {
                    if (result === null) {
                        result = [];
                    }
                    result.push(elementToDelete);
                }
            }
        }
        return result;
    }
    /**
     * Checks if element is filtered by provided rule.
     *
     * @param element Element to check.
     * @returns True if element is filtered.
     */
    isFiltered(element) {
        // Checking tag content length limits
        const content = element.innerHTML || '';
        if (this.ruleAttributes.maxLength && this.ruleAttributes.maxLength > 0) {
            // If max-length is set - checking content length (it should be lesser than max length)
            if (content.length > this.ruleAttributes.maxLength) {
                return false;
            }
        }
        if (this.ruleAttributes.minLength && this.ruleAttributes.minLength > 0) {
            // If min-length is set - checking content length (it should be greater than min length)
            if (content.length < this.ruleAttributes.minLength) {
                return false;
            }
        }
        if (!this.ruleAttributes.tagContentFilter && !this.ruleAttributes.wildcard) {
            // Rule does not depend on content
            return true;
        }
        if (!content) {
            return false;
        }
        // Checking tag content against filter
        if (this.ruleAttributes.tagContentFilter && content.indexOf(this.ruleAttributes.tagContentFilter) < 0) {
            return false;
        }
        // Checking tag content against the wildcard
        if (this.ruleAttributes.wildcard && !this.ruleAttributes.wildcard.matches(content)) {
            return false;
        }
        // All filters are passed, tag is filtered
        return true;
    }
    /**
     * Searches for parent element.
     * Suitable parent elements are set by 'parent-elements' attribute.
     * If suitable element found - returns it. Otherwise - returns null.
     *
     * @param element Element evaluated against this rule.
     * @returns Parent element.
     */
    searchForParentElement(element) {
        let parentElement = element.parentNode;
        for (let i = 0; i < this.ruleAttributes.parentSearchLevel; i += 1) {
            if (!parentElement) {
                return null;
            }
            if (this.ruleAttributes.parentElements.indexOf(parentElement.tagName.toLowerCase()) > 0) {
                return parentElement;
            }
            parentElement = parentElement.parentNode;
        }
        return null;
    }
}

/**
 * Content string filter.
 */
class ContentStringFilter {
    context;
    htmlRules;
    replaceRules;
    filteringLog;
    /**
     * Creates an instance of ContentStringFilter.
     *
     * @param context Request context.
     * @param htmlRules Html rules.
     * @param replaceRules Replace rules.
     * @param filteringLog Filtering log.
     */
    constructor(context, htmlRules, replaceRules, filteringLog) {
        this.context = context;
        this.htmlRules = htmlRules;
        this.replaceRules = replaceRules;
        this.filteringLog = filteringLog;
    }
    /**
     * Applies Html and Replace rules to content string.
     *
     * @see {@link https://adguard.com/kb/general/ad-filtering/create-own-filters/#html-filtering-rules}
     * @see {@link https://adguard.com/kb/general/ad-filtering/create-own-filters/#replace-modifier}
     *
     * @param content Content string.
     * @returns Modified content string.
     */
    applyRules(content) {
        if (this.htmlRules && this.htmlRules.length > 0) {
            content = this.applyHtmlRules(content);
        }
        if (this.replaceRules
            && this.replaceRules.length > 0
            // response content is over 3MB, ignore it
            && content.length <= 3 * 1024 * 1024) {
            content = this.applyReplaceRules(content);
        }
        return content;
    }
    /**
     * Applies Html rules to content string.
     *
     * @see {@link https://adguard.com/kb/general/ad-filtering/create-own-filters/#html-filtering-rules}
     *
     * @param content Content string.
     * @returns Modified content string.
     */
    applyHtmlRules(content) {
        const doc = documentParser.parse(content);
        if (!doc) {
            return content;
        }
        const deleted = [];
        for (let i = 0; i < this.htmlRules.length; i += 1) {
            const rule = this.htmlRules[i];
            const parsed = HtmlRuleParser.parse(rule);
            const elements = new HtmlRuleSelector(parsed).getMatchedElements(doc);
            if (elements) {
                for (let j = 0; j < elements.length; j += 1) {
                    const element = elements[j];
                    if (element.parentNode && deleted.indexOf(element) < 0) {
                        element.parentNode.removeChild(element);
                        const { tabId, requestUrl, timestamp, contentType, } = this.context;
                        const ruleType = rule.getType();
                        this.filteringLog.publishEvent({
                            type: FilteringEventType.ApplyCosmeticRule,
                            data: {
                                tabId,
                                eventId: nanoid(),
                                element: element.innerHTML,
                                frameUrl: requestUrl,
                                filterId: rule.getFilterListId(),
                                ruleIndex: rule.getIndex(),
                                frameDomain: getDomain(requestUrl),
                                requestType: contentType,
                                timestamp,
                                cssRule: ruleType === CosmeticRuleType.ElementHidingRule
                                    || ruleType === CosmeticRuleType.CssInjectionRule,
                                scriptRule: ruleType === CosmeticRuleType.ScriptletInjectionRule
                                    || ruleType === CosmeticRuleType.JsInjectionRule,
                                contentRule: ruleType === CosmeticRuleType.HtmlFilteringRule,
                            },
                        });
                        deleted.push(element);
                    }
                }
            }
        }
        // Add <!DOCTYPE html ... >
        // https://github.com/AdguardTeam/AdguardBrowserExtension/issues/959
        // XMLSerializer is used to serialize doctype object
        // eslint-disable-next-line no-undef
        const doctype = doc.doctype ? `${new XMLSerializer().serializeToString(doc.doctype)}\r\n` : '';
        if (deleted.length > 0) {
            return doctype + EntityHandler.revertEntities(doc.documentElement.outerHTML);
        }
        return content;
    }
    /**
     * Applies "replace" rules to content string.
     *
     * @param content Content string.
     * @returns Modified content string.
     */
    applyReplaceRules(content) {
        const appliedRules = [];
        let modifiedContent = content;
        for (let i = 0; i < this.replaceRules.length; i += 1) {
            const replaceRule = this.replaceRules[i];
            const replaceRuleInfo = {
                filterId: replaceRule.getFilterListId(),
                ruleIndex: replaceRule.getIndex(),
            };
            if (replaceRule.isAllowlist()) {
                appliedRules.push(replaceRuleInfo);
            }
            else {
                const advancedModifier = replaceRule.getAdvancedModifier();
                modifiedContent = advancedModifier.getApplyFunc()(modifiedContent);
                appliedRules.push(replaceRuleInfo);
            }
        }
        const { tabId, eventId } = this.context;
        if (appliedRules.length > 0) {
            this.filteringLog.publishEvent({
                type: FilteringEventType.ReplaceRuleApply,
                data: {
                    tabId,
                    eventId,
                    rules: appliedRules,
                },
            });
        }
        return modifiedContent;
    }
}

const DEFAULT_CHARSET = 'utf-8';
const LATIN_1 = 'iso-8859-1';
const WIN_1251 = 'windows-1251';
const WIN_1252 = 'windows-1252';
/**
 * Supported charsets array.
 */
const SUPPORTED_CHARSETS = [DEFAULT_CHARSET, WIN_1251, WIN_1252, LATIN_1];
/**
 * Parses charset from content-type header.
 *
 * @param contentType Content-type header.
 * @returns Charset string or null.
 */
function parseCharsetFromHeader(contentType) {
    if (!contentType) {
        return null;
    }
    const match = /charset="?(.*?)"?$/.exec(contentType.toLowerCase());
    if (match && match.length > 1) {
        return match[1].toLowerCase();
    }
    return null;
}
/**
 * Parses charset from html, looking for:
 * <meta charset="utf-8" />
 * <meta charset=utf-8 />
 * <meta charset=utf-8>
 * <meta http-equiv="content-type" content="text/html; charset=utf-8" />
 * <meta content="text/html; charset=utf-8" http-equiv="content-type" />.
 *
 * @param text Html content.
 * @returns Charset string or null.
 */
function parseCharsetFromHtml(text) {
    let match = /<meta\s*charset\s*=\s*['"]?(.*?)['"]?\s*\/?>/.exec(text.toLowerCase());
    if (match && match.length > 1) {
        return match[1].trim().toLowerCase();
    }
    // eslint-disable-next-line max-len
    match = /<meta\s*http-equiv\s*=\s*['"]?content-type['"]?\s*content\s*=\s*[\\]?['"]text\/html;\s*charset=(.*?)[\\]?['"]/.exec(text.toLowerCase());
    if (match && match.length > 1) {
        return match[1].trim().toLowerCase();
    }
    // eslint-disable-next-line max-len
    match = /<meta\s*content\s*=\s*[\\]?['"]text\/html;\s*charset=(.*?)[\\]?['"]\s*http-equiv\s*=\s*['"]?content-type['"]?/.exec(text.toLowerCase());
    if (match && match.length > 1) {
        return match[1].trim().toLowerCase();
    }
    return null;
}
/**
 * Parses charset from css.
 *
 * @param text Css content.
 * @returns Charset string or null.
 */
function parseCharsetFromCss(text) {
    const match = /^@charset\s*['"](.*?)['"]/.exec(text.toLowerCase());
    if (match && match.length > 1) {
        return match[1].trim().toLowerCase();
    }
    return null;
}

// Do not destruct inside import, because it somehow breaks build in browser
// extension via "ReferenceError: TextDecoder is not defined".
const { TextEncoder, TextDecoder } = text_encoding_polyfill.T;
/**
 * Content Stream Filter class.
 *
 * Encapsulates response data stream filtering logic
 * https://mail.mozilla.org/pipermail/dev-addons/2017-April/002729.html.
 */
class ContentStream {
    /**
     * Request context.
     *
     * This object is mutated during request processing.
     */
    context;
    /**
     * Content filter.
     *
     * Modifies content with specified rules.
     */
    contentStringFilter;
    /**
     * Web request filter.
     */
    filter;
    /**
     * Request charset.
     */
    charset;
    /**
     * Content.
     */
    content;
    /**
     * Decoder instance.
     */
    decoder;
    /**
     * Encoder instance.
     */
    encoder;
    /**
     * Filtering log.
     */
    filteringLog;
    /**
     * Contains collection of accepted content types for stream filtering.
     */
    allowedContentTypes = [
        'text/',
        'application/json',
        'application/xml',
        'application/xhtml+xml',
        'application/javascript',
        'application/x-javascript',
    ];
    /**
     * Content stream constructor.
     *
     * @param context Request context.
     * @param contentStringFilter Content filter.
     * @param streamFilterCreator Stream filter creator.
     * @param filteringLog Filtering log.
     */
    constructor(context, contentStringFilter, streamFilterCreator, filteringLog) {
        this.content = '';
        this.context = context;
        this.contentStringFilter = contentStringFilter;
        this.filteringLog = filteringLog;
        this.filter = streamFilterCreator(context.requestId);
        this.onResponseData = this.onResponseData.bind(this);
        this.onResponseFinish = this.onResponseFinish.bind(this);
        this.onResponseError = this.onResponseError.bind(this);
    }
    /**
     * Initializes encoders and filter.
     */
    init() {
        this.initEncoders();
        this.initFilter();
    }
    /**
     * Writes data to stream.
     *
     * @param content Content to write.
     */
    write(content) {
        this.filter.write(this.encoder.encode(content));
        this.filter.close();
    }
    /**
     * Sets charset.
     *
     * @param charset Charset.
     */
    setCharset(charset) {
        if (charset) {
            this.charset = charset;
            this.initEncoders();
        }
    }
    /**
     * Disconnects filter from stream.
     *
     * @param data Data to write.
     */
    disconnect(data) {
        this.filter.write(data);
        this.filter.disconnect();
    }
    /**
     * Initializes encoders.
     */
    initEncoders() {
        let set = this.charset ? this.charset : DEFAULT_CHARSET;
        // Redefining it as TextDecoder does not understand the iso- name
        if (set === LATIN_1) {
            set = WIN_1252;
        }
        this.decoder = new TextDecoder(set);
        if (set === DEFAULT_CHARSET) {
            this.encoder = new TextEncoder();
        }
        else {
            this.encoder = new TextEncoder(set, { NONSTANDARD_allowLegacyEncoding: true });
        }
    }
    /**
     * Initializes filter.
     */
    initFilter() {
        this.filter.ondata = this.onResponseData;
        this.filter.onstop = this.onResponseFinish;
        this.filter.onerror = this.onResponseError;
    }
    /**
     * We do not support stream filtering for some content types.
     *
     * @returns True if content type is supported.
     */
    shouldProcessFiltering() {
        const { requestType, contentTypeHeader } = this.context;
        if (requestType === RequestType$1.Other || requestType === RequestType$1.XmlHttpRequest) {
            return !!contentTypeHeader && this.allowedContentTypes.some((contentType) => {
                return contentTypeHeader.indexOf(contentType) === 0;
            });
        }
        return true;
    }
    /**
     * Handler for response data.
     *
     * @param event Stream filter event.
     */
    onResponseData(event) {
        if (!this.shouldProcessFiltering()) {
            this.disconnect(event.data);
            return;
        }
        if (!this.charset) {
            try {
                let charset;
                /**
                 * If this.charset is undefined and requestType is Document or Subdocument, we try to detect charset
                 * from page <meta> tags.
                 */
                if (this.context.requestType === RequestType$1.SubDocument
                    || this.context.requestType === RequestType$1.Document) {
                    charset = ContentStream.parseHtmlCharset(event.data);
                }
                /**
                 * If this.charset is undefined and requestType is Stylesheet, we try to detect charset from css
                 * directive.
                 */
                if (this.context.requestType === RequestType$1.Stylesheet) {
                    charset = ContentStream.parseCssCharset(event.data);
                }
                if (!charset) {
                    charset = DEFAULT_CHARSET;
                }
                if (charset && SUPPORTED_CHARSETS.indexOf(charset) >= 0) {
                    this.charset = charset;
                    this.initEncoders();
                    this.content += this.decoder.decode(event.data, { stream: true });
                }
                else {
                    // Charset is not supported
                    this.disconnect(event.data);
                }
            }
            catch (e) {
                logger.warn(e.message);
                // on error we disconnect the filter from the request
                this.disconnect(event.data);
            }
        }
        else {
            this.content += this.decoder.decode(event.data, { stream: true });
        }
    }
    /**
     * Handler for response error.
     */
    onResponseError() {
        if (this.filter.error && this.filter.error) {
            logger.info(this.filter.error);
        }
    }
    /**
     * Handler for the end of response data.
     */
    onResponseFinish() {
        this.content += this.decoder.decode(); // finish stream
        this.filteringLog.publishEvent({
            type: FilteringEventType.ContentFilteringStart,
            data: {
                requestId: this.context.requestId,
            },
        });
        const { contentTypeHeader, statusCode } = this.context;
        if (statusCode !== 200) {
            this.write(this.content);
            return;
        }
        const charset = parseCharsetFromHeader(contentTypeHeader);
        if (charset) {
            if (SUPPORTED_CHARSETS.indexOf(charset) < 0) {
                // Charset is detected and it is not supported
                // eslint-disable-next-line max-len
                logger.warn(`Skipping request ${this.context.requestId} with Content-Type ${this.context.contentTypeHeader}`);
                this.write(this.content);
                return;
            }
            this.setCharset(charset);
        }
        this.content = this.contentStringFilter.applyRules(this.content);
        this.write(this.content);
        this.filteringLog.publishEvent({
            type: FilteringEventType.ContentFilteringFinish,
            data: {
                requestId: this.context.requestId,
            },
        });
    }
    /**
     * Parses charset from html.
     *
     * @param data Data to parse.
     * @returns Parsed charset or null.
     */
    static parseHtmlCharset(data) {
        const decoded = new TextDecoder('utf-8').decode(data).toLowerCase();
        return parseCharsetFromHtml(decoded);
    }
    /**
     * Parses charset from css.
     *
     * @param data Data to parse.
     * @returns Parsed charset or null.
     */
    static parseCssCharset(data) {
        const decoded = new TextDecoder('utf-8').decode(data).toLowerCase();
        return parseCharsetFromCss(decoded);
    }
}

/**
 * Content filtering module.
 * Handles Html filtering and replace rules.
 */
class ContentFiltering {
    /**
     * Contains collection of supported request types for replace rules.
     */
    static supportedReplaceRulesRequestTypes = [
        es/* RequestType.Document */.xd.Document,
        es/* RequestType.SubDocument */.xd.SubDocument,
        es/* RequestType.Script */.xd.Script,
        es/* RequestType.Stylesheet */.xd.Stylesheet,
        es/* RequestType.XmlHttpRequest */.xd.XmlHttpRequest,
        es/* RequestType.Other */.xd.Other,
    ];
    /**
     * Retrieves html rules.
     *
     * @param context Request context.
     * @returns Html rules or null.
     */
    static getHtmlRules(context) {
        const { cosmeticResult } = context;
        /**
         * "cosmeticResult" is defined only for Document and Subdocument request types
         * do not need extra request type checking.
         */
        if (!cosmeticResult) {
            return null;
        }
        const htmlRules = cosmeticResult.Html.getRules();
        if (htmlRules.length === 0) {
            return null;
        }
        return htmlRules;
    }
    /**
     * Retrieves replace rules and sorts them alphabetically.
     *
     * @param context Request context.
     * @returns Replace rules or null.
     */
    static getReplaceRules(context) {
        const { requestType, matchingResult } = context;
        if (!requestType
            || !matchingResult
            || !ContentFiltering.supportedReplaceRulesRequestTypes.includes(requestType)) {
            return null;
        }
        const replaceRules = matchingResult.getReplaceRules();
        if (replaceRules.length === 0) {
            return null;
        }
        // Sort replace rules alphabetically as noted here
        // https://github.com/AdguardTeam/CoreLibs/issues/45
        return replaceRules.sort((prev, next) => {
            if (prev.getText() > next.getText()) {
                return 1;
            }
            if (prev.getText() < next.getText()) {
                return -1;
            }
            return 0;
        });
    }
    /**
     * Checks if request content filtering disabled by exception rule with $content modifier.
     *
     * @param context Request context.
     *
     * @returns `true`, if content filtering disabled by exception rule with $content modifier,
     * overwise returns `false`.
     */
    static hasContentExceptionRule(context) {
        const { matchingResult } = context;
        if (!matchingResult) {
            return false;
        }
        const rule = matchingResult.getBasicResult();
        if (!rule) {
            return false;
        }
        // The $content modifier only applies with the exception rule.
        // We don't need additional `rule.isAllowlist()` check.
        return rule.isOptionEnabled(NetworkRuleOption.Content);
    }
    /**
     * Checks if request method is supported.
     *
     * @param context Request context.
     * @returns `true`, if request method is supported,
     * overwise returns `false`.
     */
    static isRequestMethodSupported(context) {
        const { method } = context;
        return method === 'GET' || method === 'POST';
    }
    /**
     * On before request event handler.
     *
     * @param context Request context.
     */
    static onBeforeRequest(context) {
        if (!browser.webRequest.filterResponseData
            || !ContentFiltering.isRequestMethodSupported(context)
            || ContentFiltering.hasContentExceptionRule(context)) {
            return;
        }
        const htmlRules = ContentFiltering.getHtmlRules(context);
        const replaceRules = ContentFiltering.getReplaceRules(context);
        if (htmlRules || replaceRules) {
            const contentStringFilter = new ContentStringFilter(context, htmlRules, replaceRules, defaultFilteringLog);
            const contentStream = new ContentStream(context, contentStringFilter, browser.webRequest.filterResponseData, defaultFilteringLog);
            contentStream.init();
        }
    }
}

/**
 * Content Security Policy Headers filtering service module.
 */
class CspService {
    /**
     * Filtering log.
     */
    filteringLog;
    /**
     * Constructor.
     *
     * @param filteringLog Filtering log.
     */
    constructor(filteringLog) {
        this.filteringLog = filteringLog;
    }
    /**
     * Applies CSP rules to response headers and returns modified headers.
     * It is applied when webRequest.onHeadersReceived event is fired.
     *
     * @param context Request context.
     * @returns True if headers were modified.
     */
    onHeadersReceived(context) {
        const { matchingResult, responseHeaders, requestId, tabId, requestUrl, referrerUrl, } = context;
        if (!matchingResult) {
            return false;
        }
        const cspHeaders = [];
        const cspRules = matchingResult.getCspRules();
        for (let i = 0; i < cspRules.length; i += 1) {
            const rule = cspRules[i];
            if (rule.isOptionEnabled(es/* NetworkRuleOption.Header */.SJ.Header)) {
                const responseHeaderMatch = rule.matchResponseHeaders(responseHeaders);
                if (!responseHeaderMatch || rule.isAllowlist()) {
                    continue;
                }
            }
            // Don't forget: getCspRules returns all $csp rules, we must directly check that the rule is blocking.
            if (RequestBlockingApi.isRequestBlockedByRule(rule)) {
                const cspHeaderValue = rule.getAdvancedModifierValue();
                if (cspHeaderValue) {
                    cspHeaders.push({
                        name: es/* CSP_HEADER_NAME */.LD,
                        value: cspHeaderValue,
                    });
                }
            }
            this.filteringLog.publishEvent({
                type: FilteringEventType.ApplyCspRule,
                data: {
                    tabId,
                    eventId: index_browser_nanoid(),
                    requestUrl,
                    frameUrl: referrerUrl,
                    frameDomain: (0,es6/* getDomain */.ge)(referrerUrl),
                    requestType: ContentType.Csp,
                    filterId: rule.getFilterListId(),
                    ruleIndex: rule.getIndex(),
                    timestamp: Date.now(),
                    isAllowlist: rule.isAllowlist(),
                    isImportant: rule.isOptionEnabled(es/* NetworkRuleOption.Important */.SJ.Important),
                    isDocumentLevel: rule.isDocumentLevelAllowlistRule(),
                    isCsp: rule.isOptionEnabled(es/* NetworkRuleOption.Csp */.SJ.Csp),
                    isCookie: rule.isOptionEnabled(es/* NetworkRuleOption.Cookie */.SJ.Cookie),
                    advancedModifier: rule.getAdvancedModifierValue(),
                },
            });
        }
        if (cspHeaders.length > 0) {
            requestContextStorage.update(requestId, {
                responseHeaders: responseHeaders ? [...responseHeaders, ...cspHeaders] : cspHeaders,
            });
            return true;
        }
        return false;
    }
}
const cspService = new CspService(defaultFilteringLog);

/**
 * Permissions Policy service.
 */
class PermissionsPolicyService {
    /**
     * Filtering log.
     */
    filteringLog;
    /**
     * Request context storage.
     */
    contextStorage;
    /**
     * Constructor.
     *
     * @param contextStorage Request context storage.
     * @param filteringLog Filtering log.
     */
    constructor(contextStorage, filteringLog) {
        this.filteringLog = filteringLog;
        this.contextStorage = contextStorage;
    }
    /**
     * Checks if a network rule is sub document rule.
     *
     * @param rule Rule to check.
     * @returns `true` if the rule is sub document rule.
     */
    static isSubDocumentRule(rule) {
        return (rule.getPermittedRequestTypes() & es/* RequestType.SubDocument */.xd.SubDocument) === es/* RequestType.SubDocument */.xd.SubDocument;
    }
    /**
     * Applies permissions policy directives to the response headers.
     * @param context Request context.
     * @returns True if policies were set successfully.
     */
    onHeadersReceived(context) {
        const { matchingResult, responseHeaders, requestId, requestType, tabId, requestUrl, referrerUrl, } = context;
        if (!matchingResult) {
            return false;
        }
        const permissionsPolicyRules = matchingResult.getPermissionsPolicyRules();
        const permissionsPolicyHeaders = [];
        if (permissionsPolicyRules.length === 0) {
            return false;
        }
        // Check if a global allowlist rule is present.
        if (permissionsPolicyRules.some((rule) => rule.isAllowlist()
            && !rule.getAdvancedModifierValue()
            && !PermissionsPolicyService.isSubDocumentRule(rule))) {
            return false;
        }
        for (let i = 0; i < permissionsPolicyRules.length; i += 1) {
            const rule = permissionsPolicyRules[i];
            // Sub frames can only be affected by a rule where the $subdocument modifier has been set.
            if (PermissionsPolicyService.isSubDocumentRule(rule) !== (requestType === es/* RequestType.SubDocument */.xd.SubDocument)) {
                continue;
            }
            const directives = rule.getAdvancedModifierValue();
            if (directives) {
                if (!rule.isAllowlist()) {
                    permissionsPolicyHeaders.push({
                        name: es/* PERMISSIONS_POLICY_HEADER_NAME */.oF,
                        value: directives,
                    });
                }
                this.filteringLog.publishEvent({
                    type: FilteringEventType.ApplyPermissionsRule,
                    data: {
                        tabId,
                        eventId: index_browser_nanoid(),
                        requestUrl,
                        frameUrl: referrerUrl,
                        frameDomain: (0,es6/* getDomain */.ge)(referrerUrl),
                        requestType: ContentType.PermissionsPolicy,
                        filterId: rule.getFilterListId(),
                        ruleIndex: rule.getIndex(),
                        timestamp: Date.now(),
                        isAllowlist: rule.isAllowlist(),
                        isImportant: rule.isOptionEnabled(es/* NetworkRuleOption.Important */.SJ.Important),
                        isDocumentLevel: rule.isDocumentLevelAllowlistRule(),
                        isCsp: rule.isOptionEnabled(es/* NetworkRuleOption.Csp */.SJ.Csp),
                        isCookie: rule.isOptionEnabled(es/* NetworkRuleOption.Cookie */.SJ.Cookie),
                        advancedModifier: rule.getAdvancedModifierValue(),
                    },
                });
            }
        }
        this.contextStorage.update(requestId, {
            responseHeaders: responseHeaders ? [
                ...responseHeaders,
                ...permissionsPolicyHeaders,
            ] : permissionsPolicyHeaders,
        });
        return true;
    }
}
const permissionsPolicyService = new PermissionsPolicyService(requestContextStorage, defaultFilteringLog);

/**
 * CSP Trusted Types service module.
 */
class TrustedTypesService {
    static SPACE = ' ';
    static CSP_DIRECTIVE_VALUES_SEPARATOR = TrustedTypesService.SPACE;
    static CSP_DIRECTIVES_SEPARATOR = ';';
    /**
     * Content Security Policy header name.
     *
     * @see {@link https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy}
     */
    static CSP_HEADER_NAME = 'content-security-policy';
    /**
     * Content Security Policy Report-Only header name.
     *
     * @see {@link https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy-Report-Only}
     */
    static CSP_REPORT_ONLY_HEADER_NAME = 'content-security-policy-report-only';
    /**
     * TrustedTypes directive.
     *
     * @see {@link https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy/trusted-types}
     */
    static CSP_TRUSTED_TYPES_DIRECTIVE_NAME = 'trusted-types';
    /**
     * TrustedTypes directive value that disallows creating any trusted types policy.
     *
     * @see {@link https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy/trusted-types}
     */
    static NONE_TRUSTED_TYPES_POLICY_VALUE = "'none'";
    /**
     * Allows for creating Trusted Types policies with a name that was already used.
     *
     * Related:.
     *
     *
     * @see {@link https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy/trusted-types}
     */
    static ALLOW_DUPLICATES_POLICY_VALUE = "'allow-duplicates'";
    /**
     * Trusted Types policy name for AdGuard scripts.
     *
     * Related issues:
     * {@link https://github.com/AdguardTeam/AdguardBrowserExtension/issues/2068 | #2068},
     * AG-3320,
     * AG-18204.
     */
    static AG_POLICY_NAME = 'AGPolicy';
    /**
     * Checks whether the CSP header should be modified at all.
     * It is required if there are any scriptlet rules in the cosmetic result.
     *
     * Important: trusted types policy with name `AGPolicy` is being created only in scriptlets now,
     * so if some other dependency will do the same — this method should be updated.
     *
     * @param cosmeticResult Cosmetic result.
     *
     * @returns True if the CSP header should be modified, false otherwise.
     */
    static isModifyingRequired(cosmeticResult) {
        const scriptRules = cosmeticResult.getScriptRules();
        if (scriptRules.length === 0) {
            return false;
        }
        // simply check if there are any scriptlet rules
        return scriptRules.some((rule) => rule.isScriptlet);
    }
    /**
     * Checks whether the header is a CSP header.
     * CSP headers are `Content-Security-Policy` and `Content-Security-Policy-Report-Only`.
     *
     * @param header Header.
     *
     * @returns True if the header is a CSP header, false otherwise.
     */
    static isCspHeader(header) {
        // header names are case-insensitive
        // https://datatracker.ietf.org/doc/html/rfc2616#section-4.2
        return header.name.toLowerCase() === TrustedTypesService.CSP_HEADER_NAME
            || header.name.toLowerCase() === TrustedTypesService.CSP_REPORT_ONLY_HEADER_NAME;
    }
    /**
     * Modifies the value of CSP directive:
     * 1. If there are no `value` or if `value` contains only `'none'` —
     *    returns `AGPolicy` and `'allow-duplicates'` combined;
     * 2. Otherwise — adds `AGPolicy` and `'allow-duplicates'` to the directive value..
     *
     * @param value CSP directive value.
     *
     * @returns CSP directive value.
     */
    static modifyDirectiveValue(value) {
        const valueChunks = value
            .split(TrustedTypesService.CSP_DIRECTIVE_VALUES_SEPARATOR)
            .map((chunk) => chunk.trim())
            .filter((chunk) => !!chunk);
        const modifiedValueChunks = [];
        if (valueChunks.length > 0
            && !valueChunks.includes(TrustedTypesService.NONE_TRUSTED_TYPES_POLICY_VALUE)) {
            // copy `trusted-types` policy names from the directive value
            modifiedValueChunks.push(...valueChunks);
        }
        // add `AGPolicy` to the directive value if there is no such policy yet
        if (!modifiedValueChunks.includes(TrustedTypesService.AG_POLICY_NAME)) {
            modifiedValueChunks.push(TrustedTypesService.AG_POLICY_NAME);
        }
        // make sure that `'allow-duplicates'` is present
        if (!modifiedValueChunks.includes(TrustedTypesService.ALLOW_DUPLICATES_POLICY_VALUE)) {
            modifiedValueChunks.push(TrustedTypesService.ALLOW_DUPLICATES_POLICY_VALUE);
        }
        return modifiedValueChunks.join(TrustedTypesService.CSP_DIRECTIVE_VALUES_SEPARATOR);
    }
    /**
     * Modifies CSP header — checks whether it has a `trusted-types` directive,
     * and if so — adds `AGPolicy` and `'allow-duplicates'` to the directive value if needed.
     *
     * @param header Content Security Policy header.
     *
     * @returns Modified header.
     */
    static modifyCspHeader(header) {
        const { value } = header;
        if (!value) {
            return header;
        }
        const directives = value.split(TrustedTypesService.CSP_DIRECTIVES_SEPARATOR);
        const resultDirectives = [];
        for (let i = 0; i < directives.length; i += 1) {
            const directive = directives[i].trim();
            if (!directive) {
                continue;
            }
            const separatorIndex = directive.indexOf(TrustedTypesService.CSP_DIRECTIVE_VALUES_SEPARATOR);
            const directiveName = separatorIndex === -1
                ? directive
                : directive.slice(0, separatorIndex);
            if (directiveName !== TrustedTypesService.CSP_TRUSTED_TYPES_DIRECTIVE_NAME) {
                // do nothing if it is not a `trusted-types` directive
                resultDirectives.push(directive);
                continue;
            }
            const directiveValue = separatorIndex === -1
                ? ''
                : directive.slice(separatorIndex + 1);
            const modifiedDirectiveValue = TrustedTypesService.modifyDirectiveValue(directiveValue);
            resultDirectives.push(`${directiveName}${TrustedTypesService.CSP_DIRECTIVE_VALUES_SEPARATOR}${modifiedDirectiveValue}`);
        }
        return {
            name: header.name,
            // eslint-disable-next-line max-len
            value: `${resultDirectives.join(`${TrustedTypesService.CSP_DIRECTIVES_SEPARATOR}${TrustedTypesService.SPACE}`)}`,
        };
    }
    /**
     * TODO: Should we log it for filtering log?
     * Modifies CSP header of response headers —
     * adds `AGPolicy` and `'allow-duplicates'` to CSP header if there is a `trusted-types` directive,
     * and returns modified headers.
     *
     * It happens only if `context.cosmeticResult` contain any scriptlets.
     *
     * It is applied when webRequest.onHeadersReceived event is fired.
     *
     * @param context Request context.
     *
     * @returns True if headers were modified.
     */
    static onHeadersReceived(context) {
        const { responseHeaders, cosmeticResult } = context;
        if (!responseHeaders || responseHeaders.length === 0) {
            return false;
        }
        // no need to modify CSP header if there is no cosmetic result
        if (!cosmeticResult) {
            return false;
        }
        if (!TrustedTypesService.isModifyingRequired(cosmeticResult)) {
            return false;
        }
        const anyCspHeaders = [];
        const notCspHeaders = [];
        responseHeaders.forEach((header) => {
            // separate CSP headers from others
            if (TrustedTypesService.isCspHeader(header)) {
                anyCspHeaders.push(header);
            }
            else {
                notCspHeaders.push(header);
            }
        });
        // nothing to do if there are no CSP headers
        if (anyCspHeaders.length === 0) {
            return false;
        }
        // flag that indicates whether any of CSP header value was modified
        let isModified = false;
        const modifiedCspHeaders = [];
        anyCspHeaders.forEach((header) => {
            const modifiedHeader = TrustedTypesService.modifyCspHeader(header);
            // check if header value was modified
            if (modifiedHeader.value !== header.value) {
                isModified = isModified || true;
            }
            modifiedCspHeaders.push(modifiedHeader);
        });
        if (!isModified) {
            return false;
        }
        requestContextStorage.update(context.requestId, {
            responseHeaders: [
                ...notCspHeaders,
                ...modifiedCspHeaders,
            ],
        });
        return true;
    }
}

/**
 * This API is used to remove traceable data from requests initiated by the background extension.
 */
class SanitizeApi {
    /**
     * Removes Cookie headers from background extension's requests.
     *
     * @param context Request context.
     * @returns Blocking response or null.
     */
    static onBeforeSendHeaders(context) {
        const { requestHeaders, referrerUrl, tabId, } = context;
        if (tabId !== BACKGROUND_TAB_ID || !requestHeaders) {
            return null;
        }
        // removeHeader modifies 'context.requestHeaders'
        if (isExtensionUrl(referrerUrl) && removeHeader(requestHeaders, 'Cookie')) {
            return { requestHeaders };
        }
        return null;
    }
}

/**
 * @file
 * API for applying rules from background service
 * by handling web Request API and web navigation events.
 *
 * Event data is aggregated into two contexts: {@link RequestContext},
 * which contains data about the specified request
 * and {@link TabContext} which contains data about the specified tab.
 *
 *
 *  Applying {@link NetworkRule} from the background page:
 *
 * The {@link MatchingResult} of specified request is calculated and stored in context storages,
 * at the time {@link RequestEvents.onBeforeRequest} is processed.
 * The handler for this event also computes the response based on {@link MatchingResult}
 * via {@link RequestBlockingApi.getBlockingResponse}.
 * If the rule is blocking rule, the request will be cancelled, otherwise it will be handled by the next handlers.
 * If content filtering is supported, it will be initialized for non-blocking requests.
 *
 * At {@link RequestEvents.onBeforeSendHeaders}, the request headers are modified or deleted
 * based on the {@link MatchingResult} stored in {@link requestContextStorage}.
 * At {@link RequestEvents.onHeadersReceived}, the response headers are handled in the same way,
 * and also the 'trusted-types' directive is modified for CSP headers, @see {@link TrustedTypesService}.
 *
 * The specified {@link RequestContext} will be removed from {@link requestContextStorage}
 * on {@link RequestEvents.onCompleted} or {@link RequestEvents.onErrorOccurred} events.
 *
 *
 *  Applying {@link CosmeticRule} from the background page.
 *
 * We calculate {@link CosmeticResult} and store it in {@link TabContext} context
 * at the time {@link RequestEvents.onBeforeRequest} is processed.
 *
 * To get the scripts up and running as quickly as possible
 * we try to inject them the first time during the {@link RequestEvents.onResponseStarted}.
 *
 * All cosmetic rules are then injected on the {@link browser.webNavigation.onCommitted} event.
 *
 * In Firefox, {@link browser.webNavigation.onCommitted} may not work for child frames,
 * so we also try to inject cosmetic rules on {@link RequestEvents.onCompleted}.
 *
 * For frames without a source, we inject cosmetics on the {@link browser.webNavigation.onDOMContentLoaded} event.
 *
 * The frame data will be removed from the specified {@link TabContext} on {@link browser.webNavigation.onCompleted} or
 * {@link browser.webNavigation.onErrorOccurred } events.
 *
 *  Web Request API Event Handling:
 *
 *                                       ┌─────────────────────────────┐
 * Matches {@link MatchingResult}        │                             │
 * for the request.                      │       onBeforeRequest       ◄─┐
 * If this is a frame request,           │                             │ │
 * also matches the                      └──────────────┬──────────────┘ │
 * {@link CosmeticResult}                               │                │
 * for the specified frame.                             │                │
 * If the request is neither blocked                    │                │
 * nor redirected, apply the                            │                │
 * $removeparam rules.                                  │                │
 * In Firefox, if the request                           │                │
 * is not blocked,                                      │                │
 * initialize content filtering.                        │                │
 * After that, check if a request is                    │                │
 * third-party and has type CSP_REPORT                  │                │
 * - then block it.                                     │                │
 *                                                      │                │
 *                                                      │                │
 *                                       ┌──────────────▼──────────────┐ │
 * Removes or modifies request           │                             │ │
 * headers based on                      │      onBeforeSendHeaders    ◄─┼┐
 * {@link MatchingResult}.               │                             │ ││
 *                                       └──────────────┬──────────────┘ ││
 *                                                      │                ││
 *                                       ┌──────────────▼──────────────┐ ││
 *                                       │                             │ ││
 *                                       │        onSendHeaders        │ ││
 *                                       │                             │ ││
 *                                       └──────────────┬──────────────┘ ││
 *                                                      │                ││
 *                                       ┌──────────────▼──────────────┐ ││
 * Removes or modifies response          │                             │ ││
 * headers based on                    ┌─┤      onHeadersReceived      │ ││
 * {@link MatchingResult}.             │ │                             │ ││
 * Modifies 'trusted-types' directive  │ └─────────────────────────────┘ ││
 * for CSP headers:                    │                                 ││.
 * @see {@link TrustedTypesService}.   │                                 ││
 *                                     │                                 ││
 *                                     │                                 ││
 *                                     │ ┌─────────────────────────────┐ ││
 *                                     │ │                             │ ││
 *                                     ├─►       onBeforeRedirect      ├─┴┤
 *                                     │ │                             │  │
 *                                     │ └─────────────────────────────┘  │
 *                                     │                                  │
 *                                     │ ┌─────────────────────────────┐  │
 *                                     │ │                             │  │
 *                                     ├─►        onAuthRequired       ├──┘
 *                                     │ │                             │
 *                                     │ └─────────────────────────────┘
 *                                     │
 *                                     │ ┌─────────────────────────────┐
 * Try injecting JS rules into the     │ │                             │
 * frame based on                      └─►      onResponseStarted      │
 * {@link CosmeticRule}.                 │                             │
 *                                       └──────────────┬──────────────┘
 *                                                      │
 *                                       ┌──────────────▼──────────────┐
 * In Firefox, try injecting the         │                             │
 * CSS and JS into the                   │         onCompleted         │
 * subdocument frame based on            │                             │
 * {@link CosmeticResult}.               └─────────────────────────────┘
 * Remove the request information
 * from {@link requestContextStorage}.
 *
 *                                       ┌─────────────────────────────┐
 * Remove the request information        │                             │
 * from {@link requestContextStorage}.   │       onErrorOccurred       │
 *                                       │                             │
 *                                       └─────────────────────────────┘.
 *
 *
 *  Web Navigation API Event Handling:
 *
 *                                       ┌─────────────────────────────┐
 *                                       │                             │
 *                                       │  onCreatedNavigationTarget  │
 *                                       │                             │
 *                                       └──────────────┬──────────────┘
 *                                                      │
 *                                       ┌──────────────▼──────────────┐
 * Update main frame data with           │                             │
 * {@link updateMainFrameData}           │       onBeforeNavigate      │
 *                                       │                             │
 *                                       └──────────────┬──────────────┘
 *                                                      │
 *                                       ┌──────────────▼──────────────┐
 * Try injecting CSS and JS rules        │                             │
 * into the frame with source            │         onCommitted         │
 * based on {@link CosmeticRule}.        │                             │
 *                                       └──────────────┬──────────────┘
 *                                                      │
 *                                       ┌──────────────▼──────────────┐
 * Try injecting CSS and JS rules        │                             │
 * into the subdocument frame            │      onDOMContentLoaded     ├─┐
 * without source based on               │                             │ │
 * {@link CosmeticRule}.                 └──────────────┬──────────────┘ │
 *                                                      │                │
 *                                       ┌──────────────▼──────────────┐ │
 * Remove the frame data                 │                             │ │
 * from {@link TabContext}.            ┌─┤         onCompleted         │ │
 *                                     │ │                             │ │
 *                                     │ └─────────────────────────────┘ │
 *                                     │                                 │
 *                                     │ ┌─────────────────────────────┐ │
 *                                     │ │                             │ │
 *                                     ├─►    onHistoryStateUpdated    ◄─┤
 *                                     │ │                             │ │
 *                                     │ └─────────────────────────────┘ │
 *                                     │                                 │
 *                                     │ ┌─────────────────────────────┐ │
 *                                     │ │                             │ │
 *                                     └─►  onReferenceFragmentUpdated ◄─┘
 *                                       │                             │
 *                                       └─────────────────────────────┘.
 *
 *                                       ┌─────────────────────────────┐
 * Remove the frame data                 │                             │
 * from {@link TabContext}.              │       onErrorOccurred       │
 *                                       │                             │
 *                                       └─────────────────────────────┘.
 */
/**
 * API for applying rules from background service by handling
 * Web Request API and web navigation events.
 */
class WebRequestApi {
    /**
     * Adds listeners to web request events.
     */
    static start() {
        // browser.webRequest Events
        RequestEvents.onBeforeRequest.addListener(WebRequestApi.onBeforeRequest);
        // Note: onBeforeCspReport should be registered after onBeforeRequest
        // because it depends on the MatchingResult calculation for the request
        // that is performed in onBeforeRequest, and in WebRequestApi all
        // request handlers will be called in the order of registration.
        RequestEvents.onBeforeRequest.addListener(WebRequestApi.onBeforeCspReport);
        RequestEvents.onBeforeSendHeaders.addListener(WebRequestApi.onBeforeSendHeaders);
        RequestEvents.onHeadersReceived.addListener(WebRequestApi.onHeadersReceived);
        RequestEvents.onResponseStarted.addListener(WebRequestApi.onResponseStarted);
        RequestEvents.onErrorOccurred.addListener(WebRequestApi.onErrorOccurred);
        RequestEvents.onCompleted.addListener(WebRequestApi.onCompleted);
        // browser.webNavigation Events
        // Note: We need to force set matching result in Opera before run `WebRequestApi.onCommitted`
        // TODO: remove this when Opera bug is fixed.
        browser.webNavigation.onCommitted.addListener(WebRequestApi.onCommittedOperaHook);
        browser.webNavigation.onCommitted.addListener(WebRequestApi.onCommitted);
        browser.webNavigation.onBeforeNavigate.addListener(WebRequestApi.onBeforeNavigate);
        browser.webNavigation.onDOMContentLoaded.addListener(WebRequestApi.onDomContentLoaded);
        browser.webNavigation.onCompleted.addListener(WebRequestApi.deleteFrameContext);
        browser.webNavigation.onErrorOccurred.addListener(WebRequestApi.deleteFrameContext);
    }
    /**
     * Removes web request event handlers.
     */
    static stop() {
        RequestEvents.onBeforeRequest.removeListener(WebRequestApi.onBeforeRequest);
        RequestEvents.onBeforeRequest.removeListener(WebRequestApi.onBeforeCspReport);
        RequestEvents.onBeforeSendHeaders.removeListener(WebRequestApi.onBeforeSendHeaders);
        RequestEvents.onHeadersReceived.removeListener(WebRequestApi.onHeadersReceived);
        RequestEvents.onResponseStarted.removeListener(WebRequestApi.onResponseStarted);
        RequestEvents.onErrorOccurred.removeListener(WebRequestApi.onErrorOccurred);
        RequestEvents.onCompleted.removeListener(WebRequestApi.onCompleted);
        browser.webNavigation.onCommitted.removeListener(WebRequestApi.onCommitted);
        browser.webNavigation.onCommitted.removeListener(WebRequestApi.onCommittedOperaHook);
        browser.webNavigation.onDOMContentLoaded.removeListener(WebRequestApi.onDomContentLoaded);
        browser.webNavigation.onCompleted.removeListener(WebRequestApi.deleteFrameContext);
        browser.webNavigation.onErrorOccurred.removeListener(WebRequestApi.deleteFrameContext);
    }
    /**
     * Flush browser in-memory cache.
     *
     * This function is called after an engine update or filtering switch to ensure
     * that new rules are applied to requests that may have been cached by the browser.
     */
    static async flushMemoryCache() {
        try {
            await browser.webRequest.handlerBehaviorChanged();
        }
        catch (e) {
            // TODO: use getErrorMessage instead
            const message = e instanceof Error ? e.message : String(e);
            logger.error(message);
        }
    }
    /**
     * On before request event handler. This is the earliest event in the chain of the web request events.
     *
     * @param details Request details.
     * @param details.context Request context.
     * @returns Web request response or void if there is nothing to do.
     */
    static onBeforeRequest({ context }) {
        if (!context) {
            return undefined;
        }
        const { requestType, tabId, frameId, requestUrl, referrerUrl, eventId, requestId, contentType, timestamp, thirdParty, method, requestFrameId, } = context;
        if (!isHttpOrWsRequest(requestUrl)) {
            return undefined;
        }
        defaultFilteringLog.publishEvent({
            type: FilteringEventType.SendRequest,
            data: {
                tabId,
                eventId,
                requestUrl,
                requestDomain: getDomain(requestUrl),
                frameUrl: referrerUrl,
                frameDomain: getDomain(referrerUrl),
                requestType: contentType,
                timestamp,
                requestThirdParty: thirdParty,
                method,
            },
        });
        let frameRule = tabsApi.getTabFrameRule(tabId);
        // If filtering is disabled for the main frame, we don't need to check the subdocument frame.
        if (!frameRule?.isFilteringDisabled() && requestType === RequestType.SubDocument) {
            frameRule = documentApi.matchFrame(referrerUrl);
        }
        const result = engineApi.matchRequest({
            requestUrl,
            frameUrl: referrerUrl,
            requestType,
            frameRule,
            method,
        });
        if (!result) {
            return undefined;
        }
        requestContextStorage.update(requestId, {
            matchingResult: result,
        });
        if (requestType === RequestType.Document || requestType === RequestType.SubDocument) {
            tabsApi.handleFrameMatchingResult(tabId, frameId, result);
            const cosmeticOption = result.getCosmeticOption();
            const cosmeticResult = engineApi.getCosmeticResult(requestUrl, cosmeticOption);
            tabsApi.handleFrameCosmeticResult(tabId, frameId, cosmeticResult);
            requestContextStorage.update(requestId, {
                cosmeticResult,
            });
        }
        const basicResult = result.getBasicResult();
        // For a $replace rule, response will be undefined since we need to get
        // the response in order to actually apply $replace rules to it.
        const response = RequestBlockingApi.getBlockingResponse({
            rule: basicResult,
            popupRule: result.getPopupRule(),
            eventId,
            requestId,
            requestUrl,
            referrerUrl,
            requestType,
            contentType,
            tabId,
        });
        if (!response) {
            /*
             Strip url by $removeparam rules
             $removeparam rules are applied after URL blocking rules
             https://github.com/AdguardTeam/CoreLibs/issues/1462
            */
            const purgedUrl = paramsService.getPurgedUrl(requestId);
            if (purgedUrl) {
                return { redirectUrl: purgedUrl };
            }
        }
        if (response?.cancel) {
            tabsApi.incrementTabBlockedRequestCount(tabId, referrerUrl);
            const mainFrameUrl = tabsApi.getTabMainFrame(tabId)?.url;
            hideRequestInitiatorElement(tabId, requestFrameId, requestUrl, mainFrameUrl || referrerUrl, requestType, thirdParty);
        }
        else {
            ContentFiltering.onBeforeRequest(context);
        }
        return response;
    }
    /**
     * On before send headers event handler.
     *
     * !IMPORTANT! This method modifies headers in the context. This non-pure action needs
     * to increase performance: exclude copying of headers for each service.
     *
     * @param details On before send headers details.
     * @param details.context Details context.
     * @returns Web request event response.
     */
    static onBeforeSendHeaders({ context, }) {
        if (!context) {
            return undefined;
        }
        // If current request from the background - we don't need to modify headers,
        // only remove Cookie and immediately return modified headers
        const sanitizedRequest = SanitizeApi.onBeforeSendHeaders(context);
        if (sanitizedRequest) {
            return sanitizedRequest;
        }
        let requestHeadersModified = false;
        if (stealthApi.onBeforeSendHeaders(context)) {
            requestHeadersModified = true;
        }
        // If the current request does not comply with any rules - we do not
        // need to call any other processing services (e.g. cookie, header)
        if (context?.matchingResult) {
            if (cookieFiltering.onBeforeSendHeaders(context)) {
                requestHeadersModified = true;
            }
            if (removeHeadersService.onBeforeSendHeaders(context)) {
                requestHeadersModified = true;
            }
        }
        if (requestHeadersModified) {
            return { requestHeaders: context.requestHeaders };
        }
        return undefined;
    }
    /**
     * On headers received event handler.
     *
     * @param event On headers received event.
     * @param event.context Event context.
     * @param event.details On headers received details.
     * @returns Web request event response.
     */
    static onHeadersReceived({ context, details, }) {
        if (!context) {
            return undefined;
        }
        defaultFilteringLog.publishEvent({
            type: FilteringEventType.ReceiveResponse,
            data: {
                tabId: context.tabId,
                eventId: context.eventId,
                statusCode: details.statusCode,
            },
        });
        if (!context?.matchingResult || context.matchingResult.getBasicResult()?.isFilteringDisabled()) {
            return undefined;
        }
        const { requestId, requestUrl, referrerUrl, requestType, contentType, responseHeaders, matchingResult, requestFrameId, thirdParty, tabId, } = context;
        const headerResult = matchingResult.getResponseHeadersResult(responseHeaders);
        const response = RequestBlockingApi.getResponseOnHeadersReceived(responseHeaders, {
            tabId,
            eventId: context.eventId,
            rule: headerResult,
            referrerUrl,
            requestUrl,
            requestId,
            requestType,
            contentType,
        });
        if (response?.cancel) {
            tabsApi.incrementTabBlockedRequestCount(tabId, referrerUrl);
            const mainFrameUrl = tabsApi.getTabMainFrame(tabId)?.url;
            hideRequestInitiatorElement(tabId, requestFrameId, requestUrl, mainFrameUrl || referrerUrl, requestType, thirdParty);
            return response;
        }
        const contentTypeHeader = findHeaderByName$1(responseHeaders, 'content-type')?.value;
        if (contentTypeHeader) {
            requestContextStorage.update(requestId, { contentTypeHeader });
        }
        let responseHeadersModified = false;
        if (requestUrl && (requestType === RequestType.Document || requestType === RequestType.SubDocument)) {
            if (cspService.onHeadersReceived(context)) {
                responseHeadersModified = true;
            }
            if (permissionsPolicyService.onHeadersReceived(context)) {
                responseHeadersModified = true;
            }
            if (TrustedTypesService.onHeadersReceived(context)) {
                responseHeadersModified = true;
            }
        }
        if (cookieFiltering.onHeadersReceived(context)) {
            responseHeadersModified = true;
        }
        if (removeHeadersService.onHeadersReceived(context)) {
            responseHeadersModified = true;
        }
        if (responseHeadersModified) {
            return { responseHeaders: context.responseHeaders };
        }
        return undefined;
    }
    /**
     * On response started event handler.
     *
     * @param event On response started event.
     * @param event.context Event context.
     */
    static onResponseStarted({ context, }) {
        if (!context) {
            return;
        }
        const { tabId, frameId, requestType, } = context;
        if (requestType !== RequestType.Document && requestType !== RequestType.SubDocument) {
            return;
        }
        const tabContext = tabsApi.getTabContext(tabId);
        if (!tabContext) {
            return;
        }
        const frame = tabContext.frames.get(frameId);
        if (!frame || !frame.cosmeticResult) {
            return;
        }
        /**
         * Actual tab url may not be committed by navigation event during response processing.
         * If {@link tabContext.info.url} and {@link url} are not the same, this means
         * that tab navigation steel is being processed and js injection may be causing the error.
         * In this case, js will be injected in the {@link WebNavigation.onCommitted} event.
         */
        if (requestType === RequestType.Document
            /**
             * Check if url exists because it might be empty for new tabs.
             * In this case we may inject on response started
             * (https://github.com/AdguardTeam/AdguardBrowserExtension/issues/2571).
             */
            && tabContext.info.url && tabContext.info.url !== frame.url) {
            return;
        }
        CosmeticApi.applyFrameJsRules(frameId, tabId);
    }
    /**
     * This is handler for the last event from the request lifecycle.
     *
     * @param event On completed event.
     * @param event.context Request context.
     * @private
     */
    static onCompleted({ context, }) {
        if (!context) {
            return;
        }
        const { requestId, requestType, tabId, frameId, requestUrl, timestamp, contentType, cosmeticResult, } = context;
        /**
         * If the request is a subdocument request in Firefox, try injecting frame cosmetic result into frame,
         * because {@link WebRequestApi.onCommitted} can be not triggered.
         */
        if (isFirefox || requestType === RequestType.SubDocument) {
            WebRequestApi.injectCosmetic({
                frameId,
                tabId,
                timestamp,
                url: requestUrl,
            });
        }
        if (cosmeticResult
            && (requestType === RequestType.Document || requestType === RequestType.SubDocument)) {
            CosmeticApi.logScriptRules({
                tabId,
                cosmeticResult,
                url: requestUrl,
                contentType,
                timestamp,
            });
        }
        requestContextStorage.delete(requestId);
    }
    /**
     * Event handler for onErrorOccurred event. It fires when an error occurs.
     *
     * @param event On error occurred event.
     * @param event.details On error occurred event details.
     */
    static onErrorOccurred({ details, }) {
        requestContextStorage.delete(details.requestId);
    }
    /**
     * Injects cosmetic rules to specified frame based on data from frame and response context.
     *
     * If cosmetic result does not exist or it has been already applied, ignore injection.
     *
     * @param params Data required for rule injection.
     */
    static injectCosmetic(params) {
        const { frameId, tabId, url, } = params;
        const tabContext = tabsApi.getTabContext(tabId);
        if (!tabContext) {
            return;
        }
        let frame = tabContext.frames.get(frameId);
        /**
         * Subdocument frame context may not be created durning worker request processing.
         * We create new one in this case.
         */
        if (!frame) {
            frame = new Frame(url);
            tabContext.frames.set(frameId, frame);
        }
        /**
         * Cosmetic result may not be committed to frame context during worker request processing.
         * We use engine request as a fallback for this case.
         */
        if (!frame.cosmeticResult && isHttpOrWsRequest(url)) {
            frame.cosmeticResult = engineApi.matchCosmetic({
                requestUrl: url,
                frameUrl: url,
                requestType: frameId === MAIN_FRAME_ID ? RequestType.Document : RequestType.SubDocument,
                frameRule: tabContext.mainFrameRule,
            });
        }
        CosmeticApi.applyFrameCssRules(frameId, tabId);
        CosmeticApi.applyFrameJsRules(frameId, tabId);
    }
    /**
     * On before navigate web navigation event handler.
     *
     * @param details Event details.
     */
    static onBeforeNavigate(details) {
        const { frameId, tabId, url } = details;
        if (frameId === MAIN_FRAME_ID) {
            tabsApi.handleTabNavigation(tabId, url);
        }
    }
    /**
     * On committed web navigation event handler.
     *
     * Injects necessary CSS and scripts into the web page.
     *
     * @param details Event details.
     */
    static onCommitted(details) {
        const { frameId, tabId, timeStamp, url, } = details;
        WebRequestApi.injectCosmetic({
            frameId,
            tabId,
            timestamp: timeStamp,
            url,
        });
    }
    /**
     * On DOM content loaded web navigation event handler.
     *
     * This method injects css and js code in iframes without remote source.
     * Usual webRequest callbacks don't fire for iframes without remote source.
     * Also urls in these iframes may be "about:blank", "about:srcdoc", etc.
     * Due to this reason we prepare injections for them as for mainframe
     * and inject them only when onDOMContentLoaded fires.
     *
     * @see https://github.com/AdguardTeam/AdguardBrowserExtension/issues/1046
     * @param details Event details.
     */
    static async onDomContentLoaded(details) {
        const { tabId, frameId, url, } = details;
        const tabContext = tabsApi.getTabContext(tabId);
        const mainFrameUrl = tabContext?.info.url;
        if (!mainFrameUrl || !isLocalFrame(url, frameId, mainFrameUrl)) {
            return;
        }
        const isAssistant = await Assistant.isAssistantFrame(details, tabContext);
        // do not inject cosmetic rules into the assistant frame
        if (isAssistant) {
            return;
        }
        const cosmeticResult = engineApi.matchCosmetic({
            requestUrl: mainFrameUrl,
            frameUrl: mainFrameUrl,
            requestType: RequestType.Document,
            frameRule: tabContext.mainFrameRule,
        });
        CosmeticApi
            .applyCssRules({
            tabId,
            frameId,
            cosmeticResult,
        })
            .catch(logger.debug);
        CosmeticApi
            .applyJsRules({
            tabId,
            frameId,
            cosmeticResult,
            url,
        })
            .catch(logger.debug);
    }
    /**
     * Intercepts csp_report requests.
     * Check the URL of the report.
     * For chromium and firefox:
     * If it's sent to a third party, block it right away.
     * For firefox only:
     * If it contains moz://extension with our extension ID, block it as well.
     * @see https://github.com/AdguardTeam/AdguardBrowserExtension/issues/1792.
     *
     * @param details Request details.
     * @param details.context Request context.
     *
     * @returns Web request response or void if there is nothing to do.
     */
    static onBeforeCspReport({ context }) {
        // If filtering is disabled - skip process request.
        if (!engineApi.isFilteringEnabled) {
            return undefined;
        }
        if (!context) {
            return undefined;
        }
        const { requestType, matchingResult, tabId, eventId, referrerUrl, thirdParty, } = context;
        /**
         * Checks request type here instead of creating two event listener with
         * different filter types via {@link RequestEvent.init} to simplify
         * event handlers flow and create only one {@link RequestEvents.onBeforeRequest}
         * listener and two WebRequest listeners: {@link WebRequestApi.onBeforeCspReport}
         * and {@link WebRequestApi.onBeforeRequest}.
         */
        if (requestType !== RequestType.CspReport) {
            return undefined;
        }
        // If filtering disabled for this request.
        if (matchingResult?.getBasicResult()?.isFilteringDisabled()) {
            return undefined;
        }
        if (thirdParty) {
            defaultFilteringLog.publishEvent({
                type: FilteringEventType.CspReportBlocked,
                data: {
                    tabId,
                    eventId,
                    cspReportBlocked: true,
                },
            });
            tabsApi.incrementTabBlockedRequestCount(tabId, referrerUrl);
            return { cancel: true };
        }
        // Don't check for moz://extension because it was fixed in
        // https://bugzilla.mozilla.org/show_bug.cgi?id=1588957#c10.
        return undefined;
    }
    /**
     * Delete frame data from tab context when navigation is finished.
     * @param details Navigation event details.
     */
    static deleteFrameContext(details) {
        const { tabId, frameId } = details;
        const tabContext = tabsApi.getTabContext(tabId);
        if (!tabContext) {
            return;
        }
        /**
         * On creation of an empty iframe with subsequent url assignment,
         * WebNavigation.onCompleted of the frame could fire before WebRequest.onCommitted,
         * removing the frame context with it's matching and cosmetic results before it could be applied.
         *
         * TODO add the ability to prolong request and tab/frame contexts lives if it was not yet consumed
         * at webRequest or webNavigation events, i.e
         *   - keep requestContext, if webRequest.onCommitted has not been fired,
         *   - keep tab context if webNavigation.omCompleted has not been fired,
         * etc.
         */
        setTimeout(() => tabContext.frames.delete(frameId), FRAME_DELETION_TIMEOUT_MS);
    }
    /**
     * On committed web navigation event handler only for Opera.
     *
     * There is Opera bug that prevents firing WebRequest events for document
     * and subdocument requests.
     * We now handle this by checking if matching result exists for main frame
     * and if not - we force create it.
     *
     * TODO: remove this when Opera bug is fixed.
     *
     * @param details Event details.
     */
    static onCommittedOperaHook(details) {
        const { frameId, tabId, url, } = details;
        if (isOpera && frameId === MAIN_FRAME_ID) {
            const tabContext = tabsApi.getTabContext(tabId);
            if (!tabContext) {
                return;
            }
            const frame = tabContext.frames.get(frameId);
            if (!frame || frame.matchingResult) {
                return;
            }
            const matchingResult = engineApi.matchRequest({
                requestUrl: url,
                frameUrl: url,
                requestType: RequestType.Document,
                frameRule: tabContext.mainFrameRule,
            });
            frame.matchingResult = matchingResult;
        }
    }
}

var version$1 = "2.4.0-alpha.11";

var version = "2.0.56";

const TSWEBEXTENSION_VERSION = (/* unused pure expression or super */ null && (version$1));
/**
 * Stealth mode configuration schema.
 */
const stealthConfigValidator = lib.z.object({
    /**
     * Should the application set a fixed lifetime from
     * {@link StealthConfig.selfDestructFirstPartyCookiesTime} for first-party
     * cookies.
     */
    selfDestructFirstPartyCookies: lib.z.boolean(),
    /**
     * Time in minutes to delete first-party cookies.
     */
    selfDestructFirstPartyCookiesTime: lib.z.number(),
    /**
     * Should the application set a fixed lifetime from
     * {@link StealthConfig.selfDestructThirdPartyCookiesTime} for third-party
     * cookies.
     */
    selfDestructThirdPartyCookies: lib.z.boolean(),
    /**
     * Time in minutes to delete third-party cookies.
     */
    selfDestructThirdPartyCookiesTime: lib.z.number(),
    /**
     * Should the application hide the origin referrer in third-party requests
     * by replacing the referrer url with the request url.
     */
    hideReferrer: lib.z.boolean(),
    /**
     * Should the application hide the original referrer from the search page
     * containing the search query in third-party queries, replacing
     * the referrer url with the request url.
     */
    hideSearchQueries: lib.z.boolean(),
    /**
     * For Google Chrome, it removes the 'X-Client-Data' header from
     * the requests, which contains information about the browser version
     * and modifications.
     */
    blockChromeClientData: lib.z.boolean(),
    /**
     * Includes HTTP headers 'DNT' and 'Sec-GPC' in all requests.
     *
     * @see https://en.wikipedia.org/wiki/Do_Not_Track
     * @see https://globalprivacycontrol.org
     */
    sendDoNotTrack: lib.z.boolean(),
    /**
     * Blocks the possibility of leaking your IP address through WebRTC, even if
     * you use a proxy server or VPN.
     */
    blockWebRTC: lib.z.boolean(),
}).strict();
/**
 * Filter list configuration validator for MV2.
 */
const basicFilterValidator = lib.z.object({
    /**
     * Filter list text content.
     */
    content: es/* filterListChunksValidator */.g3,
    /**
     * Source map.
     */
    sourceMap: es/* filterListSourceMapValidator.optional */.Ff.optional(),
});
/**
 * Settings configuration schema.
 */
const settingsConfigValidator = lib.z.object({
    /**
     * If this flag is true, the application will work ONLY with domains
     * from the {@link Configuration.allowlist},
     * otherwise it will work everywhere EXCLUDING domains from the list.
     */
    allowlistInverted: lib.z.boolean(),
    /**
     * Flag specifying {@link Configuration.allowlist} enable state.
     * We don't use allowlist array length condition for calculate enable state,
     * because it's not cover case with empty list in inverted mode.
     */
    allowlistEnabled: lib.z.boolean(),
    /**
     * Enables css hits counter if true.
     */
    collectStats: lib.z.boolean(),
    /**
     * Enables verbose scriptlets logging if true.
     */
    debugScriptlets: lib.z.boolean().default(false),
    /**
     * Enables stealth mode if true.
     */
    stealthModeEnabled: lib.z.boolean(),
    /**
     * Enables filtering if true.
     */
    filteringEnabled: lib.z.boolean(),
    /**
     * Redirect url for $document rules.
     */
    documentBlockingPageUrl: lib.z.string().optional(),
    /**
     * Path to the assembled @adguard/assistant module. Necessary for lazy
     * on-demand loading of the assistant.
     */
    assistantUrl: lib.z.string(),
    /**
     * Stealth mode options.
     */
    stealth: stealthConfigValidator,
});
/**
 * Generic app configuration schema.
 */
const configurationValidator = lib.z.object({
    /**
     * List of hostnames or domains of sites, which should be excluded
     * from blocking or which should be included in blocking
     * depending on the value of {@link SettingsConfig.allowlistInverted} setting value.
     */
    allowlist: lib.z.string().array(),
    /**
     * List of rules added by user.
     */
    userrules: basicFilterValidator,
    /**
     * Flag responsible for logging.
     *
     * @deprecated  Will be removed in the next minor version.
     * Use {@link Configuration.logLevel} instead.
     */
    verbose: lib.z.boolean().optional(),
    /**
     * Logging level.
     */
    logLevel: lib.z["enum"]([
        LogLevel.Error,
        LogLevel.Warn,
        LogLevel.Info,
        LogLevel.Debug,
        LogLevel.Trace,
    ]).optional(),
    settings: settingsConfigValidator,
}).strict();

/**
 * Filter list configuration validator for MV2.
 */
const filterMV2Validator = basicFilterValidator.extend({
    /**
     * Filter identifier.
     */
    filterId: lib.z.number(),
    /**
     * Filter trusted flag. If true, js rules from list can be executed.
     */
    trusted: lib.z.boolean(),
});
/**
 * Configuration validator for MV2.
 */
const configurationMV2Validator = configurationValidator.extend({
    /**
     * List of domain names of sites, which should be temporary excluded from document blocking.
     */
    trustedDomains: lib.z.string().array(),
    filters: filterMV2Validator.array(),
});

/* eslint-disable class-methods-use-this */
/**
 * App implementation for MV2.
 */
class TsWebExtension {
    appContext;
    tabsApi;
    engineApi;
    stealthApi;
    messagesApi;
    tabCosmeticInjector;
    redirectsService;
    documentBlockingService;
    filteringLog;
    extSessionStorage;
    /**
     * Fires on filtering log event.
     */
    onFilteringLogEvent;
    /**
     * Fires when a rule has been created from the helper.
     */
    onAssistantCreateRule = Assistant.onCreateRule;
    /**
     * Gets app running status.
     *
     * @returns True if app started, else false.
     */
    get isStarted() {
        // TODO: Remove this check after moving call of storage initialization in extension code.
        // Check this flag before access storage values, because engine methods
        // can be triggered before initialization by extension `onCheckRequestFilterReady` method.
        if (!this.appContext.isStorageInitialized) {
            return false;
        }
        return this.appContext.isAppStarted;
    }
    /**
     * Sets app running status.
     *
     * @param value Status value.
     */
    set isStarted(value) {
        this.appContext.isAppStarted = value;
    }
    /**
     * Gets app configuration context.
     *
     * @throws Error if value not set.
     * @returns True if app started, else false.
     */
    get configuration() {
        if (!this.appContext.configuration) {
            throw new Error('Configuration not set!');
        }
        return this.appContext.configuration;
    }
    /**
     * Sets app configuration context.
     *
     * @param value Status value.
     */
    set configuration(value) {
        this.appContext.configuration = value;
    }
    /**
     * Creates new instance of {@link TsWebExtension}.
     *
     * @param appContext Top level app context storage.
     * @param tabsApi Wrapper around browser.tabs API.
     * @param engineApi TSUrlFilter Engine wrapper.
     * @param stealthApi Stealth api implementation.
     * @param messagesApi Wrapper around browser.runtime API.
     * @param tabCosmeticInjector Used to inject cosmetic rules into opened tabs on extension start.
     * @param redirectsService Service for working with redirects.
     * @param documentBlockingService Service encapsulate processing of $document modifier rules.
     * @param filteringLog Filtering log API.
     * @param extSessionStorage API for storing data described by SessionStorageSchema in the browser.storage.session.
     */
    constructor(appContext, tabsApi, engineApi, stealthApi, messagesApi, tabCosmeticInjector, redirectsService, documentBlockingService, filteringLog, extSessionStorage) {
        this.appContext = appContext;
        this.tabsApi = tabsApi;
        this.engineApi = engineApi;
        this.stealthApi = stealthApi;
        this.messagesApi = messagesApi;
        this.tabCosmeticInjector = tabCosmeticInjector;
        this.redirectsService = redirectsService;
        this.documentBlockingService = documentBlockingService;
        this.filteringLog = filteringLog;
        this.extSessionStorage = extSessionStorage;
        this.onFilteringLogEvent = this.filteringLog.onLogEvent;
        this.getMessageHandler = this.getMessageHandler.bind(this);
    }
    /**
     * Initialize app persistent data.
     * This method called as soon as possible and allows access
     * to the actual context before the app is started.
     */
    async initStorage() {
        await this.extSessionStorage.init();
        this.appContext.isStorageInitialized = true;
    }
    /**
     * Initializes {@link EngineApi} with passed {@link configuration}.
     * Starts request processing via {@link WebRequestApi} and tab tracking via {@link tabsApi}.
     *
     * Also updates webRTC privacy.network settings on demand and flushes browser in-memory request cache.
     *
     * @param configuration App configuration.
     *
     * @throws Error if configuration is not valid.
     */
    async start(configuration) {
        if (!this.appContext.startTimeMs) {
            this.appContext.startTimeMs = Date.now();
        }
        configurationMV2Validator.parse(configuration);
        this.configuration = TsWebExtension.createConfigurationMV2Context(configuration);
        TsWebExtension.updateLogLevel(configuration.logLevel);
        RequestEvents.init();
        await this.redirectsService.start();
        this.documentBlockingService.configure(configuration);
        await this.engineApi.startEngine(configuration);
        await this.tabCosmeticInjector.processOpenTabs();
        await this.tabsApi.start();
        WebRequestApi.start();
        Assistant.assistantUrl = configuration.settings.assistantUrl;
        await WebRequestApi.flushMemoryCache();
        await this.stealthApi.updateWebRtcPrivacyPermissions();
        this.isStarted = true;
    }
    /**
     * Fully stop request and tab processing.
     */
    async stop() {
        WebRequestApi.stop();
        this.tabsApi.stop();
        this.isStarted = false;
    }
    /**
     * Re-initializes {@link EngineApi} with passed {@link configuration}
     * and update tabs main frame rules based on new engine state.
     *
     * Also updates webRTC privacy.network settings on demand and flushes browser in-memory request cache.
     *
     * Requires app is started.
     *
     * @param configuration App configuration.
     *
     * @throws Error if app is not started or configuration is not valid.
     */
    async configure(configuration) {
        if (!this.isStarted) {
            throw new Error('App is not started!');
        }
        configurationMV2Validator.parse(configuration);
        TsWebExtension.updateLogLevel(configuration.logLevel);
        this.configuration = TsWebExtension.createConfigurationMV2Context(configuration);
        this.documentBlockingService.configure(configuration);
        await this.engineApi.startEngine(configuration);
        await this.tabsApi.updateCurrentTabsMainFrameRules();
        await WebRequestApi.flushMemoryCache();
        await this.stealthApi.updateWebRtcPrivacyPermissions();
    }
    /**
     * Opens assistant in the tab.
     *
     * @param tabId Tab id where assistant will be opened.
     */
    async openAssistant(tabId) {
        this.tabsApi.setAssistantInitTimestamp(tabId);
        await Assistant.openAssistant(tabId);
    }
    /**
     * Close assistant in the required tab.
     *
     * @param tabId Tab id.
     */
    async closeAssistant(tabId) {
        this.tabsApi.resetAssistantInitTimestamp(tabId);
        await Assistant.closeAssistant(tabId);
    }
    /**
     * Return rules count for current configuration.
     *
     * @returns Rules count.
     */
    getRulesCount() {
        return this.engineApi.getRulesCount();
    }
    /**
     * Returns a message handler that will listen to internal messages,
     * for example: message for get computed css for content-script.
     *
     * @returns Messages handler.
     */
    getMessageHandler() {
        return this.messagesApi.handleMessage;
    }
    /**
     * It is possible to follow all places using this logic by searching JS_RULES_EXECUTION.
     *
     * This is STEP 2.2: Local script rules are passed to the engine via this API method.
     */
    /**
     * Sets prebuild local script rules.
     *
     * @param localScriptRules JSON object with pre-build JS rules. @see {@link LocalScriptRulesService}.
     */
    setLocalScriptRules(localScriptRules) {
        localScriptRulesService.setLocalScriptRules(localScriptRules);
    }
    /**
     * Updates `filteringEnabled` configuration value without re-initialization of engine.
     *
     * Also updates webRTC privacy.network settings on demand and flushes browser in-memory request cache.
     *
     * @throws Error if {@link configuration} not set.
     * @param isFilteringEnabled `filteringEnabled` config value.
     */
    async setFilteringEnabled(isFilteringEnabled) {
        this.configuration.settings.filteringEnabled = isFilteringEnabled;
        await WebRequestApi.flushMemoryCache();
        await this.stealthApi.updateWebRtcPrivacyPermissions();
    }
    /**
     * Updates `collectStats` configuration value without re-initialization of engine.
     *
     * @throws Error if {@link configuration} not set.
     * @param isCollectStats `collectStats` config value.
     */
    setCollectHitStats(isCollectStats) {
        this.configuration.settings.collectStats = isCollectStats;
    }
    /**
     * Updates `debugScriptlets` configuration value without re-initialization of engine.
     *
     * @throws Error if {@link configuration} not set.
     * @param isDebugScriptlets `debugScriptlets` config value.
     */
    setDebugScriptlets(isDebugScriptlets) {
        this.configuration.settings.debugScriptlets = isDebugScriptlets;
    }
    /**
     * Updates `stealthModeEnabled` configuration value without re-initialization of engine.
     * Also updates webRTC privacy.network settings on demand.
     *
     * @throws Error if {@link configuration} not set.
     * @param isStealthModeEnabled `stealthModeEnabled` config value.
     */
    async setStealthModeEnabled(isStealthModeEnabled) {
        this.configuration.settings.stealthModeEnabled = isStealthModeEnabled;
        await this.stealthApi.updateWebRtcPrivacyPermissions();
    }
    /**
     * Updates `selfDestructFirstPartyCookies` stealth config value without re-initialization of engine.
     *
     * @throws Error if {@link configuration} not set.
     * @param isSelfDestructFirstPartyCookies `selfDestructFirstPartyCookies` stealth config value.
     */
    setSelfDestructFirstPartyCookies(isSelfDestructFirstPartyCookies) {
        this.configuration.settings.stealth.selfDestructFirstPartyCookies = isSelfDestructFirstPartyCookies;
    }
    /**
     * Updates `selfDestructThirdPartyCookies` stealth config value without re-initialization of engine.
     *
     * @throws Error if {@link configuration} not set.
     * @param isSelfDestructThirdPartyCookies `selfDestructThirdPartyCookies` stealth config value.
     */
    setSelfDestructThirdPartyCookies(isSelfDestructThirdPartyCookies) {
        this.configuration.settings.stealth.selfDestructThirdPartyCookies = isSelfDestructThirdPartyCookies;
    }
    /**
     * Updates `selfDestructFirstPartyCookiesTime` stealth config value without re-initialization of engine.
     *
     * @throws Error if {@link configuration} not set.
     * @param selfDestructFirstPartyCookiesTime `selfDestructFirstPartyCookiesTime` stealth config value.
     */
    setSelfDestructFirstPartyCookiesTime(selfDestructFirstPartyCookiesTime) {
        this.configuration.settings.stealth.selfDestructFirstPartyCookiesTime = selfDestructFirstPartyCookiesTime;
    }
    /**
     * Updates `selfDestructThirdPartyCookiesTime` stealth config value without re-initialization of engine.
     *
     * @throws Error if {@link configuration} not set.
     * @param selfDestructThirdPartyCookiesTime `selfDestructThirdPartyCookiesTime` stealth config value.
     */
    setSelfDestructThirdPartyCookiesTime(selfDestructThirdPartyCookiesTime) {
        this.configuration.settings.stealth.selfDestructThirdPartyCookiesTime = selfDestructThirdPartyCookiesTime;
    }
    /**
     * Updates `hideReferrer` stealth config value without re-initialization of engine.
     *
     * @throws Error if {@link configuration} not set.
     * @param isHideReferrer `isHideReferrer` stealth config value.
     */
    setHideReferrer(isHideReferrer) {
        this.configuration.settings.stealth.hideReferrer = isHideReferrer;
    }
    /**
     * Updates `hideSearchQueries` stealth config value without re-initialization of engine.
     *
     * @throws Error if {@link configuration} not set.
     * @param isHideSearchQueries `hideSearchQueries` stealth config value.
     */
    setHideSearchQueries(isHideSearchQueries) {
        this.configuration.settings.stealth.hideSearchQueries = isHideSearchQueries;
    }
    /**
     * Updates `blockChromeClientData` stealth config value without re-initialization of engine.
     *
     * @throws Error if {@link configuration} not set.
     * @param isBlockChromeClientData `blockChromeClientData` stealth config value.
     */
    setBlockChromeClientData(isBlockChromeClientData) {
        this.configuration.settings.stealth.blockChromeClientData = isBlockChromeClientData;
    }
    /**
     * Updates `sendDoNotTrack` stealth config value without re-initialization of engine.
     *
     * @throws Error if {@link configuration} not set.
     * @param isSendDoNotTrack `sendDoNotTrack` stealth config value.
     */
    setSendDoNotTrack(isSendDoNotTrack) {
        this.configuration.settings.stealth.sendDoNotTrack = isSendDoNotTrack;
    }
    /**
     * Updates `blockWebRTC` stealth config value without re-initialization of engine.
     * Also updates webRTC privacy.network settings on demand.
     *
     * @throws Error if {@link configuration} not set.
     * @param isBlockWebRTC `blockWebRTC` stealth config value.
     */
    async setBlockWebRTC(isBlockWebRTC) {
        this.configuration.settings.stealth.blockWebRTC = isBlockWebRTC;
        await this.stealthApi.updateWebRtcPrivacyPermissions();
    }
    /**
     * Retrieves rule node from a dynamic filter.
     * Dynamic filters are filters that are not loaded from the storage but created on the fly.
     *
     * @param filterId Filter id.
     * @param ruleIndex Rule index.
     * @returns Rule node or null.
     */
    retrieveDynamicRuleNode(filterId, ruleIndex) {
        return this.engineApi.retrieveDynamicRuleNode(filterId, ruleIndex);
    }
    /**
     * Creates configuration context.
     *
     * @param configuration Configuration.
     * @returns Configuration context.
     */
    static createConfigurationMV2Context(configuration) {
        const { filters, verbose, logLevel, settings, } = configuration;
        return {
            filters: filters.map(({ filterId }) => filterId),
            verbose,
            logLevel,
            settings,
        };
    }
    /**
     * Updates the log level.
     *
     * @param logLevel Log level.
     */
    static updateLogLevel(logLevel) {
        try {
            logger.currentLevel = logLevel || LogLevel.Info;
        }
        catch (e) {
            logger.currentLevel = LogLevel.Info;
        }
    }
}

/**
 * Prevent web pages to identify extension through its web accessible resources.
 *
 * Inspired by:
 *  https://github.com/gorhill/uBlock/blob/7f999b759fe540e457e297363f55b25d9860dd3e/platform/chromium/vapi-background.
 */
class ResourcesService {
    secrets = [];
    root = browser_polyfill_default().runtime.getURL('/');
    lastSecretTime = 0;
    warDir;
    generateSecretKey;
    /**
     * Constructor.
     *
     * @param generateSecretKey Function to generate secret key.
     */
    constructor(generateSecretKey) {
        this.generateSecretKey = generateSecretKey;
        this.guardWar = this.guardWar.bind(this);
    }
    /**
     * Init service.
     *
     * @param warDir Web accessible resources directory.
     */
    init(warDir) {
        this.warDir = warDir;
        const filter = {
            urls: [`${this.root}${this.warDir}/*`],
        };
        const extraInfoSpec = ['blocking'];
        browser_polyfill_default().webRequest.onBeforeRequest.addListener(this.guardWar, filter, extraInfoSpec);
    }
    /**
     * Stops service.
     */
    stop() {
        this.warDir = undefined;
        this.secrets = [];
        browser_polyfill_default().webRequest.onBeforeRequest.removeListener(this.guardWar);
    }
    /**
     * Creates url for war file.
     *
     * @param path Resource relative path.
     * @param params Additional params appended to url, by default empty.
     * @throws Error, if web accessible resources path is not defined.
     *
     * @returns Url to resource with secret param.
     */
    createResourceUrl(path, params = new URLSearchParams()) {
        if (!this.warDir) {
            throw new Error('Resources path is not defined. Did you init the service?');
        }
        const secretParams = new URLSearchParams(this.createSecretParam());
        const resultParams = new URLSearchParams([...secretParams, ...params]);
        return browser_polyfill_default().runtime.getURL(`/${this.warDir}/${path}?${resultParams.toString()}`);
    }
    /**
     * Loads war resource by path.
     *
     * @param path Resource relative path.
     *
     * @returns Promise resolved with resource content as a string.
     */
    async loadResource(path) {
        const url = this.createResourceUrl(path);
        const response = await fetch(url);
        // redefine url property of the response
        // https://github.com/AdguardTeam/AdguardBrowserExtension/issues/2278
        Object.defineProperty(response, 'url', { value: path });
        return response.text();
    }
    /**
     * Generates secret key, persists it in the secrets array and formats querystring.
     *
     * @returns Querystring with secret.
     */
    createSecretParam() {
        if (this.secrets.length !== 0) {
            // TODO move magic numbers to constants
            if ((Date.now() - this.lastSecretTime) > 5000) {
                this.secrets.splice(0);
            }
            else if (this.secrets.length > 256) {
                this.secrets.splice(0, this.secrets.length - 192);
            }
        }
        this.lastSecretTime = Date.now();
        const secret = this.generateSecretKey();
        this.secrets.push(secret);
        return `?secret=${secret}`;
    }
    /**
     * If secret is not found redirects to the main url of extension, otherwise removes secret from the stored values.
     *
     * @param details Web request details.
     * @returns Redirect or nothing.
     */
    guardWar(details) {
        const { url } = details;
        const pos = this.secrets.findIndex((secret) => url.lastIndexOf(`?secret=${secret}`) !== -1);
        if (pos === -1) {
            return { redirectUrl: this.root };
        }
        this.secrets.splice(pos, 1);
        return undefined;
    }
}

/**
 * RedirectsCache is used for new type of blocking redirects, like click2load.html.
 * Here we save redirected urls to check later for being able to view hidden frame after user
 * clicked on button "click to load".
 */
class RedirectsCache {
    /**
     * Instance or LRUMap.
     */
    cache = new lru.LRUMap(100);
    /**
     * Adds url to the cache.
     *
     * @param url Url added to cache.
     */
    add = (url) => {
        this.cache.set(url, true);
    };
    /**
     * Checks if url is in the cache.
     *
     * @param url Url to check.
     * @returns True if url is in the cache.
     */
    hasUrl = (url) => {
        return this.cache.has(url);
    };
}
const redirectsCache = new RedirectsCache();

/**
 * Used for new type of redirects, i.e.: click2load.html.
 * This tokens are transferred to redirect and used later to unblock page after user clicked button
 * "click to load".
 */
class RedirectsTokensCache {
    cache = new lru.LRUMap(1000);
    /**
     * Generates random unblock token for url and saves it to cache.
     * Used for blocking redirect params creation {@link resourcesService.blockingUrlParams}.
     *
     * @returns Generated random string.
     */
    generateToken = () => {
        const token = index_browser_nanoid();
        this.cache.set(token, true);
        return token;
    };
    /**
     * Checks whether token exist in cache.
     * Used when redirect is checked in {@link resourcesService.shouldCreateRedirectUrl}.
     *
     * @param token Some string or null.
     * @returns True if cache has such token.
     */
    hasToken = (token) => {
        if (!token) {
            return false;
        }
        return this.cache.has(token);
    };
}
const redirectsTokensCache = new RedirectsTokensCache();

/**
 * Service for working with redirects.
 */
class RedirectsService {
    resourcesService;
    redirects = null;
    /**
     * Creates {@link RedirectsService} instance.
     * @param resourcesService Prevent web pages to identify extension through its web accessible resources.
     */
    constructor(resourcesService) {
        this.resourcesService = resourcesService;
    }
    /**
     * Starts redirects service.
     */
    async start() {
        try {
            const rawYaml = await this.resourcesService.loadResource('redirects.yml');
            this.redirects = new scriptlets_umd.redirects.Redirects(rawYaml);
        }
        catch (e) {
            throw new Error(e.message);
        }
    }
    /**
     * Returns redirect url for the specified title.
     *
     * @param title Redirect title or null.
     * @param requestUrl Request url.
     * @returns Redirect url or null if redirect is not found.
     */
    createRedirectUrl(title, requestUrl) {
        if (!title) {
            return null;
        }
        if (!this.redirects) {
            return null;
        }
        const redirectSource = this.redirects.getRedirect(title);
        if (!redirectSource) {
            logger.debug(`There is no redirect source with title: "${title}"`);
            return null;
        }
        const shouldRedirect = this.shouldCreateRedirectUrl(title, requestUrl);
        if (!shouldRedirect) {
            return null;
        }
        // For blocking redirects we generate additional search params.
        const params = this.blockingUrlParams(title, requestUrl);
        return this.resourcesService.createResourceUrl(`redirects/${redirectSource.file}`, params);
    }
    /**
     * Check whether redirect creating is needed i.e.: for click2load.html it's not needed after
     * button click.
     *
     * @param redirectTitle A name of the redirect.
     * @param requestUrl Request url.
     * @returns True if should create redirect url.
     */
    shouldCreateRedirectUrl = (redirectTitle, requestUrl) => {
        // if no redirects loaded we won't be able to create redirect url;
        if (!this.redirects) {
            return false;
        }
        // no further checking is needed for most of the redirects
        // except blocking redirects, i.e. click2load.html
        if (!this.redirects.isBlocking(redirectTitle)) {
            return true;
        }
        // unblock token passed to redirect by createRedirectFileUrl and returned back.
        // it should be last parameter in url
        const UNBLOCK_TOKEN_PARAM = '__unblock';
        let cleanRequestUrl = requestUrl;
        const url = new URL(requestUrl);
        const params = new URLSearchParams(url.search);
        const unblockToken = params.get(UNBLOCK_TOKEN_PARAM);
        if (unblockToken) {
            // if redirect has returned unblock token back,
            // add url to cache for no further redirecting on button click;
            // save cleaned origin url so unblock token parameter should be cut off
            params.delete(UNBLOCK_TOKEN_PARAM);
            cleanRequestUrl = `${url.origin}${url.pathname}?${params.toString()}`;
            redirectsCache.add(cleanRequestUrl);
        }
        return !redirectsCache.hasUrl(cleanRequestUrl)
            || !redirectsTokensCache.hasToken(unblockToken);
    };
    /**
     * Builds blocking url search params.
     *
     * @param redirectTitle Title of the redirect.
     * @param requestUrl Request url.
     * @throws Error if this method called before redirects where set.
     * @returns Url search params.
     * @private
     */
    blockingUrlParams(redirectTitle, requestUrl) {
        if (!this.redirects) {
            throw new Error('This method should be called after redirects are loaded');
        }
        const params = new URLSearchParams();
        if (this.redirects.isBlocking(redirectTitle)) {
            const unblockToken = redirectsTokensCache.generateToken();
            params.set('__unblock', unblockToken);
            params.set('__origin', requestUrl);
        }
        return params;
    }
}

/**
 * This service encapsulate processing of $document modifier rules.
 *
 * Service is initialized in {@link configure} method, called from {@link EngineApi#startEngine}.
 *
 * Request rule is processed in {@link getDocumentBlockingResponse} method, called
 * from {@link RequestBlockingApi.getBlockingResponse}.
 *
 * Request rule is processed following scenario:
 * - if domain is trusted, ignore request
 * - if rule is document blocking and {@link documentBlockingPageUrl} is undefined, return
 * {@link WebRequestApi.onBeforeRequest} blocking response
 * - if rule is document blocking and {@link documentBlockingPageUrl} is defined, return redirect response with
 * required params.
 * - if browser is Firefox, update page url by {@link browser.tabs} API, because FF doesn't support redirects to
 * extension pages.
 */
class DocumentBlockingService {
    tabsApi;
    // base url of document blocking page
    documentBlockingPageUrl;
    // list of domain names of sites, which should be excluded from document blocking
    trustedDomains = [];
    /**
     * Creates instance of {@link DocumentBlockingService}.
     * @param tabsApi Wrapper around browser.tabs API.
     */
    constructor(tabsApi) {
        this.tabsApi = tabsApi;
    }
    /**
     * Configures service instance {@link documentBlockingPageUrl}.
     *
     * @param configuration App {@link Configuration}.
     */
    configure(configuration) {
        const { settings, trustedDomains } = configuration;
        this.documentBlockingPageUrl = settings?.documentBlockingPageUrl;
        this.trustedDomains = trustedDomains;
    }
    /**
     * Processes $document modifier rule matched request in {@link RequestBlockingApi.getBlockingResponse}.
     *
     * @param data Data for document request processing.
     * @returns Blocking response or null {@link WebRequestApi.onBeforeRequest}.
     */
    getDocumentBlockingResponse(data) {
        const { tabId, eventId, rule, referrerUrl, requestId, requestUrl, } = data;
        // if request url domain is trusted, ignore document blocking rule
        if (this.isTrustedDomain(requestUrl)) {
            return undefined;
        }
        // public filtering log event
        defaultFilteringLog.publishEvent({
            type: FilteringEventType.ApplyBasicRule,
            data: {
                eventId,
                tabId,
                filterId: rule.getFilterListId(),
                ruleIndex: rule.getIndex(),
                requestUrl,
                requestId,
                frameUrl: referrerUrl,
                requestType: ContentType.Document,
                isAllowlist: rule.isAllowlist(),
                isImportant: rule.isOptionEnabled(es/* NetworkRuleOption.Important */.SJ.Important),
                isDocumentLevel: rule.isDocumentLevelAllowlistRule(),
                isCsp: rule.isOptionEnabled(es/* NetworkRuleOption.Csp */.SJ.Csp),
                isCookie: rule.isOptionEnabled(es/* NetworkRuleOption.Cookie */.SJ.Cookie),
                advancedModifier: rule.getAdvancedModifierValue(),
            },
        });
        // if documentBlockingPage is undefined, block request
        if (!this.documentBlockingPageUrl) {
            return { cancel: true };
        }
        // get document blocking url with required params
        const blockingUrl = DocumentBlockingService.createBlockingUrl(this.documentBlockingPageUrl, requestUrl, rule.getText());
        // Chrome doesn't allow to show extension pages in incognito mode
        if (isChromium && this.tabsApi.isIncognitoTab(tabId)) {
            // Closing tab before opening a new one may lead to browser crash (Chromium)
            browser_polyfill_default().tabs.create({ url: blockingUrl })
                .then(() => {
                browser_polyfill_default().tabs.remove(tabId);
            })
                .catch((e) => {
                logger.warn(`Can't open info page about blocked domain. Err: ${e}`);
            });
        }
        else {
            // Browser doesn't allow redirects to extension pages which are not listed in web
            // accessible resources. We set blocking page url via browser.tabs
            // api for bypassing this limitation.
            this.reloadTabWithBlockingPage(tabId, blockingUrl);
        }
        return { cancel: true };
    }
    /**
     * Checks if request url domain is trusted.
     *
     * @param url Request url.
     * @returns True, if request url domain is trusted, else false.
     */
    isTrustedDomain(url) {
        const domain = (0,es6/* getHostname */.Fo)(url);
        if (domain) {
            return this.trustedDomains.includes(domain);
        }
        return false;
    }
    /**
     * Updates tab with document blocking page url.
     *
     * @param tabId Tab id.
     * @param url Blocking page url.
     */
    reloadTabWithBlockingPage(tabId, url) {
        const tabContext = this.tabsApi.getTabContext(tabId);
        if (!tabContext) {
            return;
        }
        browser_polyfill_default().tabs.update(tabId, { url });
    }
    /**
     * Sets required url and rule query params to document-blocking page url.
     *
     * @param  documentBlockingPageUrl Url of document-blocking page.
     * @param  requestUrl Processed request url.
     * @param  ruleText Matched rule text.
     * @returns Document blocking page url with required params.
     */
    static createBlockingUrl(documentBlockingPageUrl, requestUrl, ruleText) {
        const url = new URL(documentBlockingPageUrl);
        url.searchParams.set('url', requestUrl);
        url.searchParams.set('rule', ruleText);
        return url.toString();
    }
}

/**
 * @file Temporary entry point for global background submodule instances.
 * Needed for backward compatibility during internal API updates.
 * Will be removed in the future.
 */
const allowlist = new Allowlist();
const engineApi = new EngineApi(allowlist, appContext, stealthApi);
const documentApi = new DocumentApi(allowlist, engineApi);
const tabsApi = new TabsApi(documentApi);
const documentBlockingService = new DocumentBlockingService(tabsApi);
const messagesApi = new MessagesApi(tabsApi, defaultFilteringLog);
const resourcesService = new ResourcesService(() => {
    return Math.floor(Math.random() * 982451653 + 982451653).toString(36);
});
const redirectsService = new RedirectsService(resourcesService);
/**
 * Creates new instance of {@link TsWebExtension}.
 * @param webAccessibleResourcesPath Path to web accessible resources for {@link resourcesService}.
 * @returns New instance of {@link TsWebExtension}.
 */
function createTsWebExtension(webAccessibleResourcesPath) {
    resourcesService.init(webAccessibleResourcesPath);
    const tabCosmeticInjector = new TabsCosmeticInjector(engineApi, documentApi, tabsApi);
    return new TsWebExtension(appContext, tabsApi, engineApi, stealthApi, messagesApi, tabCosmeticInjector, redirectsService, documentBlockingService, defaultFilteringLog, extSessionStorage);
}

// TODO check if we can return typed message here
/**
 * Sends message to the background page.
 *
 * @param message Message to send.
 * @param message.payload Payload of the message.
 * @param message.type Message type.
 *
 * @returns Promise resolved with response from the background page.
 */
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const sendAppMessage = async (message) => {
    return browser.runtime.sendMessage({ handlerName: MESSAGE_HANDLER_NAME, ...message });
};




/***/ }),

/***/ 18721:
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "rawCompaniesDb": () => (/* binding */ rawCompaniesDb)
/* harmony export */ });
const rawCompaniesDb = {
	"timeUpdated": "2024-10-14T10:04:53.310Z",
	"categories": {
		"0": "audio_video_player",
		"1": "comments",
		"2": "customer_interaction",
		"3": "pornvertising",
		"4": "advertising",
		"5": "essential",
		"6": "site_analytics",
		"7": "social_media",
		"8": "misc",
		"9": "cdn",
		"10": "hosting",
		"11": "unknown",
		"12": "extensions",
		"13": "email",
		"14": "consent",
		"15": "telemetry",
		"101": "mobile_analytics"
	},
	"trackerDomains": {
		"mmtro.com": 6,
		"creative-serving.com": 4,
		"p161.net": 4,
		"analytics.163.com": 4,
		"1822direkt.de": 8,
		"1dmp.io": 4,
		"opecloud.com": 6,
		"1sponsor.com": 4,
		"tm.dentsu.de": 6,
		"1and1.com": 8,
		"1und1.de": 8,
		"uicdn.com": 8,
		"website-start.de": 8,
		"24-ads.com": 4,
		"247-inc.net": 2,
		"d1af033869koo7.cloudfront.net": 2,
		"counter.24log.ru": 6,
		"24smi.net": 8,
		"24smi.org": 8,
		"2leep.com": 4,
		"33across.com": 4,
		"3dstats.com": 6,
		"3gpp.org": 5,
		"3gppnetwork.org": 5,
		"4cdn.org": 8,
		"4finance.com": 2,
		"4wnet.com": 4,
		"d3aa0ztdn3oibi.cloudfront.net": 2,
		"51.la": 6,
		"5min.com": 0,
		"d1lm7kd3bd3yo9.cloudfront.net": 6,
		"grepdata.com": 6,
		"77tracking.com": 6,
		"swm.digital": 0,
		"7tv.de": 0,
		"888media.net": 4,
		"hit.8digits.com": 6,
		"94j7afz2nr.xyz": 12,
		"statsanalytics.com": 6,
		"a3cloud.net": 11,
		"a8.net": 4,
		"aaxads.com": 4,
		"abtasty.com": 6,
		"d1447tq2m68ekg.cloudfront.net": 6,
		"ab.co": 8,
		"abc-cdn.net.au": 8,
		"abc-host.net": 8,
		"abc-host.net.au": 8,
		"abc-prod.net.au": 8,
		"abc-stage.net.au": 8,
		"abc-test.net.au": 8,
		"abc.net.au": 8,
		"abcaustralia.net.au": 8,
		"abcradio.net.au": 8,
		"ablida.de": 4,
		"ablida.net": 4,
		"durasite.net": 4,
		"accengage.net": 4,
		"ax.xrea.com": 6,
		"accesstrade.net": 4,
		"agcdn.com": 4,
		"accmgr.com": 4,
		"p-td.com": 4,
		"acestream.net": 12,
		"acint.net": 6,
		"acloudimages.com": 4,
		"acpm.fr": 6,
		"acquia.com": 6,
		"ziyu.net": 7,
		"actionpay.ru": 4,
		"adnwb.ru": 4,
		"adonweb.ru": 4,
		"active-agent.com": 4,
		"trackcmp.net": 6,
		"active-srv02.de": 4,
		"active-tracking.de": 4,
		"activeconversion.com": 4,
		"a-cast.jp": 6,
		"activemeter.com": 4,
		"go.activengage.com": 2,
		"actonsoftware.com": 4,
		"acuityplatform.com": 4,
		"acxiom-online.com": 4,
		"acxiom.com": 4,
		"ad-blocker.org": 11,
		"ads.ad-center.com": 6,
		"ad-delivery.net": 11,
		"ad-sys.com": 4,
		"adagionet.com": 4,
		"ad2click.go2cloud.org": 4,
		"ad2games.com": 4,
		"ad360.vn": 4,
		"ads.ad4game.com": 4,
		"ad4mat.ar": 4,
		"ad4mat.at": 4,
		"ad4mat.be": 4,
		"ad4mat.bg": 4,
		"ad4mat.br": 4,
		"ad4mat.ch": 4,
		"ad4mat.co.uk": 4,
		"ad4mat.cz": 4,
		"ad4mat.de": 4,
		"ad4mat.dk": 4,
		"ad4mat.es": 4,
		"ad4mat.fi": 4,
		"ad4mat.fr": 4,
		"ad4mat.gr": 4,
		"ad4mat.hu": 4,
		"ad4mat.it": 4,
		"ad4mat.mx": 4,
		"ad4mat.net": 4,
		"ad4mat.nl": 4,
		"ad4mat.no": 4,
		"ad4mat.pl": 4,
		"ad4mat.ro": 4,
		"ad4mat.ru": 4,
		"ad4mat.se": 4,
		"ad4mat.tr": 4,
		"ad6.fr": 4,
		"ad6media.co.uk": 4,
		"ad6media.com": 4,
		"ad6media.es": 4,
		"ad6media.fr": 4,
		"a2dfp.net": 4,
		"addynamo.net": 4,
		"ebis.ne.jp": 4,
		"adlightning.com": 4,
		"admagnet.net": 4,
		"amimg.net": 4,
		"adspirit.de": 4,
		"adspirit.net": 4,
		"adac.de": 8,
		"adacado.com": 4,
		"ozonemedia.com": 4,
		"adrtx.net": 4,
		"adalliance.io": 4,
		"adalyser.com": 6,
		"adaos-ads.net": 4,
		"adap.tv": 4,
		"smrtlnks.com": 2,
		"yieldoptimizer.com": 4,
		"adnetwork.adasiaholdings.com": 4,
		"adbetclickin.pink": 4,
		"adbetnet.com": 4,
		"adblade.com": 4,
		"adbooth.com": 4,
		"adbooth.net": 4,
		"adbox.lv": 4,
		"adbrn.com": 6,
		"adbrite.com": 4,
		"adbull.com": 4,
		"adbutler.com": 4,
		"adc-serv.net": 4,
		"adc-srv.net": 4,
		"adcash.com": 4,
		"vuroll.in": 6,
		"acs86.com": 4,
		"csbew.com": 4,
		"irs09.com": 4,
		"adcito.com": 4,
		"adcitomedia.com": 4,
		"adclear.net": 4,
		"swift.adclerks.com": 4,
		"adclickmedia.com": 4,
		"adclickzone.go2cloud.org": 4,
		"ad-cloud.jp": 4,
		"admarvel.s3.amazonaws.com": 4,
		"ads.admarvel.com": 4,
		"adcolony.com": 4,
		"adrdgt.com": 4,
		"amgdgt.com": 4,
		"adcrowd.com": 4,
		"shop2market.com": 4,
		"addtocalendar.com": 2,
		"dpmsrv.com": 4,
		"yagiay.com": 4,
		"addfreestats.com": 6,
		"addinto.com": 2,
		"addshoppers.com": 7,
		"shop.pe": 7,
		"addthis.com": 4,
		"addthiscdn.com": 4,
		"addthisedge.com": 4,
		"b2btracking.addvalue.de": 6,
		"addyon.com": 4,
		"adeasy.ru": 4,
		"ipredictive.com": 6,
		"adengage.com": 4,
		"adespresso.com": 4,
		"adexcite.com": 4,
		"adextent.com": 4,
		"adf.ly": 4,
		"adfalcon.com": 4,
		"adfoc.us": 4,
		"js.adforgames.com": 4,
		"adform.net": 4,
		"adformdsp.net": 4,
		"seadform.net": 4,
		"adfox.ru": 4,
		"adwolf.ru": 4,
		"adfreestyle.pl": 4,
		"adfront.org": 4,
		"adfrontiers.com": 4,
		"adgebra.co.in": 4,
		"adgenie.co.uk": 4,
		"ad.adgile.com": 4,
		"ad.antventure.com": 4,
		"adglare.net": 4,
		"adsafety.net": 4,
		"smartadcheck.de": 4,
		"smartredirect.de": 4,
		"adgorithms.com": 4,
		"adgoto.com": 4,
		"adguard.com": 8,
		"adguard.app": 8,
		"adguard.info": 8,
		"adguard.io": 8,
		"adguard.org": 8,
		"adtidy.org": 8,
		"agrd.io": 8,
		"agrd.eu": 8,
		"adguard-dns.com": 8,
		"adguard-dns.io": 8,
		"adguard-vpn.com": 8,
		"adguard-vpn.online": 8,
		"adguardvpn.com": 8,
		"adhands.ru": 4,
		"adhese.be": 4,
		"adhese.com": 4,
		"adhese.net": 4,
		"adhitzads.com": 4,
		"adhood.com": 4,
		"afy11.net": 4,
		"cdn.adikteev.com": 4,
		"adimpact.com": 4,
		"adinch.com": 4,
		"adition.com": 4,
		"adjal.com": 4,
		"cdn.adjs.net": 4,
		"adjug.com": 4,
		"adjust.com": 101,
		"adj.st": 101,
		"adjust.io": 101,
		"adjust.net.in": 101,
		"adjust.world": 101,
		"apptrace.com": 101,
		"adk2.com": 4,
		"cdn.adsrvmedia.com": 4,
		"cdn.cdnrl.com": 4,
		"adklip.com": 4,
		"adkengage.com": 4,
		"adknowledge.com": 4,
		"bidsystem.com": 4,
		"blogads.com": 4,
		"cubics.com": 4,
		"yarpp.org": 4,
		"adsearch.adkontekst.pl": 4,
		"netsprint.eu": 4,
		"adlabs.ru": 4,
		"clickiocdn.com": 4,
		"luxup.ru": 4,
		"mixmarket.biz": 4,
		"ad-serverparc.nl": 4,
		"adimg.net": 4,
		"adlantis.jp": 4,
		"cdn.adless.io": 4,
		"api.publishers.adlive.io": 4,
		"adlooxtracking.com": 4,
		"adx1.com": 4,
		"adman.gr": 4,
		"adman.in.gr": 4,
		"admanmedia.com": 4,
		"admantx.com": 4,
		"admaster.net": 4,
		"cdnmaster.com": 4,
		"admaster.com.cn": 4,
		"admasterapi.com": 4,
		"admatic.com.tr": 4,
		"ads5.admatic.com.tr": 4,
		"cdn2.admatic.com.tr": 4,
		"lib-3pas.admatrix.jp": 4,
		"admaxserver.com": 4,
		"admaxim.com": 4,
		"admaya.in": 4,
		"admedia.com": 4,
		"adizio.com": 4,
		"admedo.com": 4,
		"admeira.ch": 4,
		"admeld.com": 4,
		"admeo.ru": 4,
		"admaym.com": 4,
		"atemda.com": 4,
		"admicro.vn": 4,
		"vcmedia.vn": 4,
		"admitad.com": 4,
		"admixer.net": 4,
		"admixer.com": 4,
		"admized.com": 8,
		"admo.tv": 4,
		"a.admob.com": 4,
		"mm.admob.com": 4,
		"mmv.admob.com": 4,
		"p.admob.com": 4,
		"run.admost.com": 4,
		"dmmotion.com": 4,
		"nspmotion.com": 4,
		"admulti.com": 4,
		"adnegah.net": 4,
		"adnet.vn": 4,
		"adnet.biz": 4,
		"adnet.de": 4,
		"adclick.lt": 4,
		"adnet.lt": 4,
		"ad.adnetwork.net": 4,
		"adnetworkperformance.com": 11,
		"adserver.adnexio.com": 4,
		"adnium.com": 4,
		"heias.com": 4,
		"smaclick.com": 4,
		"st-n.ads3-adnow.com": 4,
		"adnymics.com": 4,
		"adobe.com": 4,
		"demdex.net": 4,
		"everestjs.net": 4,
		"everesttech.net": 4,
		"adobe.io": 8,
		"scene7.com": 4,
		"adobedtm.com": 5,
		"2o7.net": 6,
		"du8783wkf05yr.cloudfront.net": 6,
		"hitbox.com": 6,
		"imageg.net": 6,
		"nedstat.com": 6,
		"omtrdc.net": 6,
		"sitestat.com": 6,
		"adobedc.net": 6,
		"adobelogin.com": 2,
		"adobetag.com": 4,
		"typekit.com": 5,
		"typekit.net": 5,
		"adocean.pl": 4,
		"dmtry.com": 4,
		"adomik.com": 4,
		"adcde.com": 4,
		"addlvr.com": 4,
		"adfeedstrk.com": 4,
		"adtrgt.com": 4,
		"bannertgt.com": 4,
		"cptgt.com": 4,
		"cpvfeed.com": 4,
		"cpvtgt.com": 4,
		"mygeek.com": 4,
		"popcde.com": 4,
		"sdfje.com": 4,
		"urtbk.com": 4,
		"adonion.com": 4,
		"t.adonly.com": 4,
		"adoperator.com": 4,
		"adoric.com": 6,
		"adorika.com": 4,
		"adorika.net": 4,
		"adosia.com": 4,
		"adotmob.com": 4,
		"adotube.com": 4,
		"adparlor.com": 4,
		"adparlour.com": 4,
		"a4p.adpartner.pro": 4,
		"adpeepshosted.com": 4,
		"adperfect.com": 4,
		"adperium.com": 4,
		"adpilot.at": 4,
		"erne.co": 4,
		"adplan-ds.com": 4,
		"advg.jp": 4,
		"c.p-advg.com": 4,
		"adplus.co.id": 4,
		"adprofex.com": 4,
		"ads2.bid": 4,
		"adframesrc.com": 4,
		"adserve.adpulse.ir": 4,
		"ads.adpv.com": 4,
		"adreactor.com": 4,
		"adrecord.com": 4,
		"adrecover.com": 4,
		"ad.vcm.jp": 4,
		"adresult.jp": 4,
		"adriver.ru": 4,
		"adroll.com": 4,
		"adrom.net": 4,
		"txt.eu": 4,
		"adru.net": 4,
		"adrunnr.com": 4,
		"adsame.com": 4,
		"adsbookie.com": 4,
		"adscale.de": 4,
		"adscience.nl": 4,
		"adsco.re": 4,
		"adsensecamp.com": 4,
		"adserverpub.com": 4,
		"online.adservicemedia.dk": 4,
		"adsfactor.net": 4,
		"ads.doclix.com": 4,
		"adskeeper.co.uk": 4,
		"ssp.adskom.com": 4,
		"adslot.com": 4,
		"adsnative.com": 4,
		"adsniper.ru": 4,
		"adspeed.com": 4,
		"adspeed.net": 4,
		"o333o.com": 4,
		"adstage-analytics.herokuapp.com": 4,
		"code.adstanding.com": 4,
		"adstars.co.id": 4,
		"ad-stir.com": 4,
		"4dsply.com": 4,
		"cdn.engine.adsupply.com": 4,
		"trklnks.com": 4,
		"adswizz.com": 4,
		"adtaily.com": 4,
		"adtaily.pl": 4,
		"adtarget.me": 4,
		"adtech.de": 6,
		"adtechus.com": 6,
		"adtegrity.net": 4,
		"adtpix.com": 4,
		"adtelligence.de": 4,
		"adentifi.com": 4,
		"adthink.com": 4,
		"advertstream.com": 4,
		"audienceinsights.net": 4,
		"adtiger.de": 4,
		"adtimaserver.vn": 4,
		"adtng.com": 3,
		"adtoma.com": 4,
		"adtomafusion.com": 4,
		"adtr02.com": 11,
		"track.adtraction.com": 4,
		"adtraxx.de": 4,
		"adtriba.com": 6,
		"adtrue.com": 4,
		"adtrustmedia.com": 4,
		"ad.adtube.ir": 4,
		"awempire.com": 3,
		"dditscdn.com": 3,
		"livejasmin.com": 3,
		"adultadworld.com": 3,
		"adworldmedia.com": 3,
		"adup-tech.com": 4,
		"advaction.ru": 4,
		"aucourant.info": 4,
		"schetu.net": 4,
		"dqfw2hlp4tfww.cloudfront.net": 4,
		"ahcdn.com": 9,
		"pix-cdn.org": 9,
		"s3.advarkads.com": 4,
		"adventori.com": 8,
		"adnext.fr": 4,
		"adverline.com": 4,
		"surinter.net": 4,
		"adversaldisplay.com": 4,
		"adversalservers.com": 4,
		"go.adversal.com": 4,
		"adverserve.net": 4,
		"ad.adverteerdirect.nl": 4,
		"adverticum.net": 4,
		"advertise.com": 4,
		"advertisespace.com": 4,
		"adsdk.com": 4,
		"advertising.com": 4,
		"aol.com": 4,
		"atwola.com": 4,
		"pictela.net": 4,
		"verizonmedia.com": 4,
		"advertlets.com": 4,
		"advertserve.com": 4,
		"advidi.com": 4,
		"am10.ru": 4,
		"am15.net": 4,
		"advolution.de": 4,
		"adwebster.com": 4,
		"ads.adwitserver.com": 4,
		"adworx.at": 4,
		"adworxs.net": 4,
		"adxion.com": 4,
		"adxpansion.com": 3,
		"ads.adxpose.com": 4,
		"event.adxpose.com": 4,
		"servedby.adxpose.com": 4,
		"adxprtz.com": 4,
		"adyoulike.com": 4,
		"omnitagjs.com": 4,
		"adzerk.net": 4,
		"adzly.com": 4,
		"aemediatraffic.com": 6,
		"hprofits.com": 6,
		"amxdt.com": 4,
		"aerisapi.com": 2,
		"aerisweather.com": 2,
		"affectv.com": 4,
		"go.affec.tv": 4,
		"hybridtheory.com": 4,
		"affilbox.com": 4,
		"affilbox.cz": 4,
		"track.affiliate-b.com": 4,
		"affiliate4you.nl": 4,
		"ads.affbuzzads.com": 4,
		"affiliatefuture.com": 4,
		"affiliatelounge.com": 4,
		"affiliation-france.com": 4,
		"affiliator.com": 4,
		"affiliaweb.fr": 4,
		"banner-rotation.com": 4,
		"webmasterplan.com": 4,
		"affimax.de": 4,
		"affinity.com": 4,
		"countby.com": 4,
		"affiz.net": 4,
		"pml.afftrack.com": 6,
		"afgr2.com": 3,
		"v2.afilio.com.br": 6,
		"afsanalytics.com": 6,
		"ads.aftonbladet.se": 4,
		"aftv-serving.bid": 4,
		"agkn.com": 4,
		"agilone.com": 6,
		"adview.pl": 4,
		"pingagenow.com": 7,
		"aimediagroup.com": 4,
		"advombat.ru": 4,
		"aidata.io": 4,
		"aim4media.com": 4,
		"muscache.com": 6,
		"musthird.com": 6,
		"airbrake.io": 4,
		"airpr.com": 6,
		"ab.airpush.com": 4,
		"abmr.net": 9,
		"akamai.net": 9,
		"akamaihd.net": 9,
		"akamaized.net": 9,
		"akstat.io": 9,
		"edgekey.net": 9,
		"edgesuite.net": 9,
		"imiclk.com": 9,
		"akadns.net": 9,
		"akamaiedge.net": 9,
		"akaquill.net": 9,
		"akamoihd.net": 12,
		"adn-d.sp.gmossp-sp.jp": 4,
		"akanoo.com": 6,
		"akavita.com": 4,
		"ads.albawaba.com": 4,
		"serve.albacross.com": 4,
		"aldi-international.com": 8,
		"alenty.com": 4,
		"alephd.com": 4,
		"alexametrics.com": 6,
		"d31qbv1cthcecs.cloudfront.net": 6,
		"d5nxst8fruw4z.cloudfront.net": 6,
		"alexa.com": 4,
		"algolia.com": 4,
		"algolia.net": 4,
		"algovid.com": 11,
		"alibaba.com": 8,
		"alicdn.com": 8,
		"aliapp.org": 8,
		"alibabachengdun.com": 8,
		"alibabausercontent.com": 8,
		"aliexpress.com": 8,
		"alikunlun.com": 8,
		"aliyuncs.com": 8,
		"alibabacloud.com": 10,
		"alibabadns.com": 10,
		"aliyun.com": 10,
		"ucweb.com": 8,
		"alipay.com": 2,
		"alipayobjects.com": 2,
		"websitealive.com": 2,
		"allegroimg.com": 8,
		"allegrostatic.com": 8,
		"allegrostatic.pl": 8,
		"ngacm.com": 8,
		"ngastatic.com": 8,
		"i.btg360.com.br": 6,
		"allo-pages.fr": 2,
		"allotraffic.com": 4,
		"edge.alluremedia.com.au": 4,
		"allyes.com": 4,
		"inputs.alooma.com": 4,
		"arena.altitude-arena.com": 4,
		"amadesa.com": 4,
		"amap.com": 2,
		"amazon.ca": 8,
		"amazon.co.jp": 8,
		"amazon.co.uk": 8,
		"amazon.com": 8,
		"amazon.de": 8,
		"amazon.es": 8,
		"amazon.fr": 8,
		"amazon.it": 8,
		"d3io1k5o0zdpqr.cloudfront.net": 8,
		"a2z.com": 8,
		"aamazoncognito.com": 8,
		"amazon-corp.com": 8,
		"amazon-dss.com": 8,
		"amazon.com.au": 8,
		"amazon.com.mx": 8,
		"amazon.dev": 8,
		"amazon.in": 8,
		"amazon.nl": 8,
		"amazon.sa": 8,
		"amazonbrowserapp.co.uk": 8,
		"amazonbrowserapp.es": 8,
		"amazoncrl.com": 8,
		"firetvcaptiveportal.com": 8,
		"ntp-fireos.com": 8,
		"amazon-adsystem.com": 4,
		"serving-sys.com": 4,
		"sizmek.com": 4,
		"assoc-amazon.ca": 4,
		"assoc-amazon.co.uk": 4,
		"assoc-amazon.com": 4,
		"assoc-amazon.de": 4,
		"assoc-amazon.fr": 4,
		"assoc-amazon.jp": 4,
		"images-amazon.com": 9,
		"media-amazon.com": 9,
		"ssl-images-amazon.com": 9,
		"amazontrust.com": 9,
		"associates-amazon.com": 9,
		"cloudfront.net": 10,
		"ota-cloudfront.net": 10,
		"axx-eu.amazon-adsystem.com": 4,
		"amazonpay.com": 2,
		"payments-amazon.com": 2,
		"amazonpay.in": 2,
		"aiv-cdn.net": 0,
		"aiv-delivery.net": 0,
		"amazonvideo.com": 0,
		"pv-cdn.net": 0,
		"primevideo.com": 0,
		"amazonaws.com": 10,
		"amazonwebservices.com": 10,
		"awsstatic.com": 10,
		"adnetwork.net.vn": 4,
		"adnetwork.vn": 4,
		"ambientplatform.vn": 4,
		"amgload.net": 11,
		"amoad.com": 4,
		"ad.amgdgt.com": 4,
		"ads.amgdgt.com": 4,
		"amobee.com": 4,
		"collective-media.net": 4,
		"amplitude.com": 6,
		"d24n15hnbwhuhn.cloudfront.net": 6,
		"ampproject.org": 8,
		"anametrix.net": 6,
		"ancestrycdn.com": 9,
		"ancoraplatform.com": 6,
		"anetwork.ir": 4,
		"aniview.com": 4,
		"a-ads.com": 4,
		"anormal-tracker.de": 6,
		"answerscloud.com": 1,
		"anthill.vn": 7,
		"ants.vn": 7,
		"rt.analytics.anvato.net": 0,
		"tkx2-prod.anvato.net": 0,
		"w3.cdn.anvato.net": 0,
		"player.anyclip.com": 0,
		"video-loader.com": 4,
		"aolcdn.com": 6,
		"isp.netscape.com": 6,
		"apa.at": 8,
		"apester.com": 4,
		"apicit.net": 4,
		"carrierzone.com": 6,
		"appcenter.ms": 5,
		"appcues.com": 2,
		"appdynamics.com": 6,
		"de8of677fyt0b.cloudfront.net": 6,
		"eum-appdynamics.com": 6,
		"jscdn.appier.net": 4,
		"apple.com": 8,
		"aaplimg.com": 8,
		"apple-cloudkit.com": 8,
		"apple-dns.net": 8,
		"apple-livephotoskit.com": 8,
		"apple-mapkit.com": 8,
		"apple.news": 8,
		"apzones.com": 8,
		"cdn-apple.com": 8,
		"icloud-content.com": 8,
		"icloud.com": 8,
		"icons.axm-usercontent-apple.com": 8,
		"itunes.com": 8,
		"me.com": 8,
		"mzstatic.com": 8,
		"safebrowsing.apple": 8,
		"safebrowsing.g.applimg.com": 8,
		"iadsdk.apple.com": 4,
		"applifier.com": 4,
		"assets.applovin.com": 4,
		"applovin.com": 4,
		"applvn.com": 4,
		"appmetrx.com": 4,
		"adnxs.com": 4,
		"adnxs.net": 4,
		"appsflyer.com": 101,
		"appsflyersdk.com": 101,
		"adne.tv": 4,
		"readserver.net": 4,
		"www.apture.com": 2,
		"arcpublishing.com": 6,
		"ard.de": 0,
		"areyouahuman.com": 6,
		"arkoselabs.com": 6,
		"art19.com": 4,
		"banners.advsnx.net": 4,
		"artlebedev.ru": 8,
		"ammadv.it": 4,
		"arubamediamarketing.it": 4,
		"cya2.net": 6,
		"asambeauty.com": 8,
		"ask.com": 7,
		"aspnetcdn.com": 9,
		"ads.assemblyexchange.com": 4,
		"cdn.astronomer.io": 6,
		"ati-host.net": 6,
		"aticdn.net": 6,
		"xiti.com": 6,
		"atedra.com": 4,
		"oadts.com": 4,
		"as00.estara.com": 4,
		"atgsvcs.com": 4,
		"adbureau.net": 4,
		"atdmt.com": 4,
		"atlassbx.com": 4,
		"track.roiservice.com": 4,
		"atl-paas.net": 2,
		"atlassian.com": 2,
		"atlassian.net": 2,
		"d12ramskps3070.cloudfront.net": 2,
		"bitbucket.org": 2,
		"jira.com": 2,
		"ss-inf.net": 2,
		"d1xfq2052q7thw.cloudfront.net": 9,
		"marketplace.atlassian.com": 9,
		"atomz.com": 2,
		"atsfi.de": 11,
		"cdn.attracta.com": 4,
		"locayta.com": 6,
		"ads.audience2media.com": 4,
		"qwobl.net": 4,
		"revsci.net": 4,
		"wunderloop.net": 4,
		"12mlbe.com": 4,
		"audiencesquare.com": 4,
		"auditude.com": 0,
		"audtd.com": 4,
		"cdn.augur.io": 6,
		"aumago.com": 4,
		"clicktracks.com": 4,
		"ausgezeichnet.org": 2,
		"advertising.gov.au": 4,
		"auth0.com": 6,
		"ai.autoid.com": 6,
		"optimost.com": 4,
		"oc-track.autonomycloud.com": 4,
		"track.yieldsoftware.com": 4,
		"api.autopilothq.com": 4,
		"autoscout24.com": 8,
		"autoscout24.net": 8,
		"avail.net": 4,
		"analytics.avanser.com.au": 2,
		"avmws.com": 6,
		"avantlink.com": 4,
		"ads.avazu.net": 4,
		"avenseo.com": 4,
		"adspdbl.com": 0,
		"avocet.io": 8,
		"aweber.com": 4,
		"awin.com": 4,
		"awin1.com": 4,
		"perfb.com": 4,
		"ad.globe7.com": 4,
		"azadify.com": 4,
		"azure.com": 10,
		"azure.net": 10,
		"azurefd.net": 10,
		"trafficmanager.net": 10,
		"blob.core.windows.net": 8,
		"azureedge.net": 9,
		"b2bcontext.ru": 4,
		"b2bvideo.ru": 4,
		"babator.com": 6,
		"backbeatmedia.com": 4,
		"widgets.backtype.com": 4,
		"bahn.de": 8,
		"img-bahn.de": 8,
		"baidu.com": 4,
		"baidustatic.com": 4,
		"bdimg.com": 8,
		"bdstatic.com": 8,
		"baletingo.com": 11,
		"bangdom.com": 3,
		"widgets.bankrate.com": 4,
		"bannerconnect.net": 4,
		"bannerflow.com": 4,
		"bannerplay.com": 4,
		"cdn.bannersnack.com": 4,
		"dn3y71tq7jf07.cloudfront.net": 4,
		"getbarometer.s3.amazonaws.com": 2,
		"basilic.io": 6,
		"batanga.com": 4,
		"t4ft.de": 4,
		"bauernative.com": 4,
		"baur.de": 8,
		"baynote.net": 4,
		"bazaarvoice.com": 2,
		"bbci.co.uk": 10,
		"tracking.bd4travel.com": 4,
		"beopinion.com": 2,
		"bfmio.com": 4,
		"beaconads.com": 4,
		"beampulse.com": 4,
		"beanstalkdata.com": 4,
		"bebi.com": 4,
		"beeketing.com": 4,
		"beeline.ru": 4,
		"bidr.io": 4,
		"tracker.beezup.com": 4,
		"begun.ru": 4,
		"behavioralengine.com": 4,
		"belboon.de": 8,
		"cdn.belco.io": 2,
		"belstat.be": 6,
		"belstat.com": 6,
		"belstat.de": 6,
		"belstat.fr": 6,
		"belstat.nl": 6,
		"bemobile.ua": 10,
		"tag.benchplatform.com": 4,
		"betterttv.net": 7,
		"betweendigital.com": 4,
		"intencysrv.com": 4,
		"bid.run": 4,
		"bidgear.com": 6,
		"bidswitch.net": 4,
		"exe.bid": 4,
		"bttrack.com": 4,
		"bidtheatre.com": 4,
		"bidvertiser.com": 4,
		"bigmobileads.com": 4,
		"bigcommerce.com": 6,
		"bigmir.net": 6,
		"bigpoint-payment.com": 8,
		"bigpoint.com": 8,
		"bigpoint.net": 8,
		"bpcdn.net": 8,
		"bpsecure.com": 8,
		"bildstatic.de": 8,
		"ad-cdn.bilgin.pro": 4,
		"pixel.bilinmedia.net": 4,
		"bat.r.msn.com": 4,
		"bing.com": 4,
		"bing.net": 4,
		"virtualearth.net": 2,
		"binge.com.au": 0,
		"view.binlayer.com": 4,
		"widgets.binotel.com": 4,
		"esendra.fi": 4,
		"bitcoinplus.com": 2,
		"bit.ly": 6,
		"bitrix.de": 4,
		"bitrix.info": 4,
		"bitrix.ru": 4,
		"bitrix24.com": 4,
		"bitrix24.com.br": 4,
		"bitwarden.com": 8,
		"traffic.adxprts.com": 4,
		"jssr.jd.com": 4,
		"blau.de": 8,
		"bnmla.com": 4,
		"blismedia.com": 6,
		"blogad.com.tw": 4,
		"blogbang.com": 4,
		"www.blogcatalog.com": 2,
		"track.blogcounter.de": 6,
		"blogfoster.com": 8,
		"bloggerads.net": 4,
		"blogher.com": 4,
		"blogherads.com": 4,
		"blogimg.jp": 9,
		"blogsmithmedia.com": 8,
		"blogblog.com": 8,
		"blogger.com": 8,
		"blogspot.com": 8,
		"brcdn.com": 4,
		"brsrvr.com": 4,
		"brtstats.com": 4,
		"offerpoint.net": 4,
		"blueserving.com": 4,
		"blueconic.net": 6,
		"bluecore.com": 4,
		"triggeredmail.appspot.com": 4,
		"bkrtx.com": 4,
		"bluekai.com": 4,
		"adrevolver.com": 4,
		"bluelithium.com": 4,
		"bmmetrix.com": 4,
		"japanmetrix.jp": 4,
		"bluenewsupdate.info": 11,
		"bluestreak.com": 4,
		"bluetriangletech.com": 6,
		"btttag.com": 6,
		"bodelen.com": 4,
		"tracking.bol.com": 4,
		"qb.boldapps.net": 4,
		"secure.apps.shappify.com": 4,
		"boldchat.com": 2,
		"boltdns.net": 11,
		"bom.gov.au": 9,
		"ml314.com": 6,
		"bongacams.com": 3,
		"bonial.com": 2,
		"bonialconnect.com": 2,
		"bonialserviceswidget.de": 2,
		"boo-box.com": 4,
		"booking.com": 8,
		"bstatic.com": 8,
		"boostbox.com.br": 6,
		"boostervideo.ru": 0,
		"bootstrapcdn.com": 9,
		"borrango.com": 11,
		"scan.botscanner.com": 6,
		"boudja.com": 11,
		"bounceexchange.com": 4,
		"bouncex.com": 4,
		"bouncex.net": 4,
		"j.clickdensity.com": 6,
		"boxever.com": 4,
		"brainient.com": 4,
		"brainsins.com": 4,
		"d2xkqxdy6ewr93.cloudfront.net": 4,
		"mobileapptracking.com": 101,
		"app.link": 4,
		"branch.io": 4,
		"brandaffinity.net": 4,
		"go.cpmadvisors.com": 4,
		"optorb.com": 4,
		"brandmetrics.com": 4,
		"brandreachsys.com": 4,
		"rtbidder.net": 4,
		"brandwire.tv": 4,
		"branica.com": 4,
		"appboycdn.com": 6,
		"braze.com": 6,
		"brealtime.com": 4,
		"bridgetrack.com": 4,
		"brightcove.com": 0,
		"brightcove.net": 0,
		"analytics.brightedge.com": 4,
		"munchkin.brightfunnel.com": 6,
		"brightonclick.com": 4,
		"btrll.com": 4,
		"p.brilig.com": 4,
		"brillen.de": 8,
		"broadstreetads.com": 4,
		"bm23.com": 4,
		"brow.si": 4,
		"browser-statistik.de": 6,
		"browser-update.org": 2,
		"btncdn.com": 9,
		"in.bubblestat.com": 4,
		"brighteroption.com": 7,
		"bufferapp.com": 7,
		"bugherd.com": 2,
		"bugsnag.com": 6,
		"d2wy8f7a9ursnm.cloudfront.net": 6,
		"bulkhentai.com": 3,
		"bumlam.com": 11,
		"bunchbox.co": 6,
		"bf-ad.net": 4,
		"bf-tools.net": 4,
		"bstatic.de": 4,
		"burstbeacon.com": 4,
		"burstnet.com": 4,
		"burt.io": 4,
		"d3q6px0y2suh5n.cloudfront.net": 4,
		"rich-agent.s3.amazonaws.com": 4,
		"richmetrics.com": 4,
		"stats.businessol.com": 6,
		"bttn.io": 4,
		"buysellads.com": 4,
		"servedby-buysellads.com": 4,
		"buzzadexchange.com": 4,
		"buzzador.com": 7,
		"buzzfed.com": 2,
		"bwbx.io": 9,
		"bypass.jp": 4,
		"c1exchange.com": 4,
		"c3metrics.com": 6,
		"c3tag.com": 6,
		"c8.net.ua": 4,
		"cackle.me": 3,
		"d1cerpgff739r9.cloudfront.net": 4,
		"d1qpxk1wfeh8v1.cloudfront.net": 4,
		"callpage.io": 2,
		"callbackhunter.com": 2,
		"callmeasurement.com": 2,
		"callibri.ru": 4,
		"callrail.com": 2,
		"calltracking.ru": 2,
		"caltat.com": 2,
		"cam-content.com": 3,
		"camakaroda.com": 11,
		"s.edkay.com": 6,
		"canddi.com": 6,
		"canonical.com": 8,
		"canvas.net": 2,
		"canvasnetwork.com": 2,
		"du11hjcvx0uqb.cloudfront.net": 2,
		"kdata.fr": 6,
		"captora.com": 4,
		"edge.capturemedia.network": 4,
		"cdn.capturly.com": 6,
		"route.carambo.la": 4,
		"carbonads.com": 4,
		"carbonads.net": 4,
		"fusionads.net": 4,
		"cardinalcommerce.com": 6,
		"cardlytics.com": 6,
		"cdn.carrotquest.io": 6,
		"api.cartstack.com": 2,
		"caspion.com": 6,
		"t.castle.io": 2,
		"3gl.net": 6,
		"cbox.ws": 2,
		"adlog.com.com": 0,
		"cbsinteractive.com": 0,
		"dw.com.com": 0,
		"ccmbg.com": 4,
		"admission.net": 4,
		"cdn-net.com": 11,
		"cdn13.com": 8,
		"cdn77.com": 9,
		"cdn77.org": 9,
		"cdnetworks.com": 9,
		"cdnetworks.net": 9,
		"cdnnetwok.xyz": 12,
		"cdnondemand.org": 11,
		"cdnsure.com": 11,
		"cdnvideo.com": 9,
		"cdnwidget.com": 9,
		"cedexis-radar.net": 6,
		"cedexis-test.com": 6,
		"cedexis.com": 6,
		"cedexis.fastlylb.net": 6,
		"cedexis.net": 6,
		"celebrus.com": 6,
		"celtra.com": 0,
		"cendyn.adtrack.calls.net": 4,
		"centraltag.com": 4,
		"brand-server.com": 4,
		"speed-trap.nl": 6,
		"link.ixs1.net": 4,
		"hits.e.cl": 4,
		"certona.net": 4,
		"res-x.com": 4,
		"gsn.chameleon.ad": 4,
		"chango.ca": 4,
		"chango.com": 4,
		"channelintelligence.com": 4,
		"cptrack.de": 6,
		"channeladvisor.com": 4,
		"searchmarketing.com": 4,
		"channelfinder.net": 4,
		"chaordicsystems.com": 4,
		"chartbeat.com": 6,
		"chartbeat.net": 6,
		"chartboost.com": 4,
		"chaser.ru": 2,
		"cloud.chatbeacon.io": 2,
		"chatango.com": 2,
		"call.chatra.io": 2,
		"chaturbate.com": 3,
		"chatwing.com": 2,
		"checkmystats.com.au": 4,
		"chefkoch-cdn.de": 8,
		"chefkoch.de": 8,
		"tracker.chinmedia.vn": 4,
		"chinesean.com": 4,
		"chitika.net": 4,
		"choicestream.com": 4,
		"api.getchute.com": 5,
		"media.chute.io": 5,
		"iqcontentplatform.de": 6,
		"data.circulate.com": 6,
		"p.cityspark.com": 4,
		"cityads.ru": 4,
		"gameleads.ru": 4,
		"ciuvo.com": 12,
		"widget.civey.com": 2,
		"civicscience.com": 6,
		"ciweb.ciwebgroup.com": 4,
		"clcknads.pro": 3,
		"pulseradius.com": 4,
		"clearbit.com": 6,
		"clearsale.com.br": 4,
		"tag.clrstm.com": 4,
		"api.clerk.io": 4,
		"cleverpush.com": 6,
		"wzrkt.com": 6,
		"cleversite.ru": 2,
		"script.click360.io": 6,
		"clickandchat.com": 2,
		"software.clickback.com": 4,
		"hit.clickaider.com": 4,
		"clickaine.com": 4,
		"clickbank.net": 4,
		"cbproads.com": 4,
		"adtoll.com": 4,
		"clickbooth.com": 4,
		"clickboothlnk.com": 4,
		"clickcease.com": 2,
		"clickcertain.com": 4,
		"remarketstats.com": 4,
		"clickdesk.com": 2,
		"analytics.clickdimensions.com": 4,
		"clickequations.net": 4,
		"clickexperts.net": 4,
		"doublemax.net": 4,
		"clickinc.com": 4,
		"clickintext.net": 4,
		"clickky.biz": 4,
		"9nl.be": 4,
		"9nl.com": 4,
		"9nl.eu": 4,
		"9nl.it": 4,
		"9nl.me": 4,
		"clickmeter.com": 4,
		"clickonometrics.pl": 4,
		"clickpoint.com": 4,
		"clickpoint.it": 4,
		"clickprotector.com": 6,
		"clickreport.com": 6,
		"doogleonduty.com": 6,
		"ctn.go2cloud.org": 4,
		"clicksor.com": 4,
		"hatid.com": 4,
		"lzjl.com": 4,
		"myroitracking.com": 4,
		"clicktale.com": 6,
		"clicktale.net": 6,
		"clicktale.pantherssl.com": 6,
		"clicktalecdn.sslcs.cdngc.net": 6,
		"clicktripz.com": 4,
		"clickwinks.com": 4,
		"getclicky.com": 6,
		"staticstuff.net": 6,
		"clickyab.com": 4,
		"clicmanager.fr": 4,
		"eplayer.clipsyndicate.com": 4,
		"www.is1.clixgalore.com": 4,
		"clixmetrix.com": 4,
		"clixsense.com": 4,
		"cloud-media.fr": 4,
		"cloudflare.com": 9,
		"cloudflare.net": 9,
		"cloudflare-dm-cmpimg.com": 9,
		"cloudflare-dns.com": 9,
		"cloudflare-ipfs.com": 9,
		"cloudflare-quic.com": 9,
		"cloudflare-terms-of-service-abuse.com": 9,
		"cloudflare.tv": 9,
		"cloudflareaccess.com": 9,
		"cloudflareclient.com": 9,
		"cloudflareinsights.com": 9,
		"cloudflareok.com": 9,
		"cloudflareportal.com": 9,
		"cloudflareresolve.com": 9,
		"cloudflaressl.com": 9,
		"cloudflarestatus.com": 9,
		"cloudflarestream.com": 9,
		"pacloudflare.com": 9,
		"sn-cloudflare.com": 9,
		"videodelivery.net": 9,
		"cloudimg.io": 9,
		"cloudinary.com": 9,
		"clovenetwork.com": 4,
		"clustrmaps.com": 4,
		"cnbc.com": 8,
		"cnetcontent.com": 8,
		"cnstats.ru": 6,
		"cnzz.com": 6,
		"umeng.com": 6,
		"acc-hd.de": 4,
		"client.cobrowser.net": 2,
		"codeonclick.com": 11,
		"cogocast.net": 4,
		"coin-have.com": 4,
		"appsha1.cointraffic.io": 2,
		"authedmine.com": 8,
		"coin-hive.com": 8,
		"coinhive.com": 8,
		"coinurl.com": 4,
		"coll1onf.com": 11,
		"coll2onf.com": 11,
		"service.collarity.com": 4,
		"static.clmbtech.com": 4,
		"combotag.com": 4,
		"pdk.theplatform.com": 0,
		"comm100.cn": 2,
		"comm100.com": 2,
		"cdn-cs.com": 4,
		"cdn.mercent.com": 4,
		"link.mercent.com": 4,
		"commercialvalue.org": 11,
		"afcyhf.com": 4,
		"anrdoezrs.net": 4,
		"apmebf.com": 4,
		"awltovhc.com": 4,
		"emjcd.com": 4,
		"ftjcfx.com": 4,
		"lduhtrp.net": 4,
		"qksz.net": 4,
		"tkqlhce.com": 4,
		"tqlkg.com": 4,
		"yceml.net": 4,
		"communicatorcorp.com": 4,
		"wowanalytics.co.uk": 6,
		"c-col.com": 6,
		"c.compete.com": 6,
		"complex.com": 4,
		"complexmedianetwork.com": 4,
		"comprigo.com": 12,
		"comscore.com": 6,
		"zqtk.net": 6,
		"conative.de": 4,
		"condenast.com": 8,
		"conduit-banners.com": 4,
		"conduit-data.com": 4,
		"conduit.com": 4,
		"confirmit.com": 4,
		"congstar.de": 4,
		"connatix.com": 4,
		"connected-by.connectad.io": 4,
		"cdn.connecto.io": 6,
		"connexity.net": 4,
		"cxt.ms": 4,
		"connextra.com": 4,
		"rs6.net": 4,
		"serverbid.com": 4,
		"contactatonce.com": 2,
		"adrolays.de": 4,
		"c-i.as": 4,
		"df-srv.de": 4,
		"d1uwd25yvxu96k.cloudfront.net": 4,
		"static.contactme.com": 4,
		"contaxe.com": 5,
		"content.ad": 4,
		"ingestion.contentinsights.com": 6,
		"contentexchange.me": 6,
		"ctfassets.net": 9,
		"contentpass.de": 6,
		"contentpass.net": 6,
		"contentsquare.net": 4,
		"d1aug3dv5magti.cloudfront.net": 6,
		"d39se0h2uvfakd.cloudfront.net": 6,
		"c-on-text.com": 4,
		"intext.contextad.pl": 4,
		"continum.net": 10,
		"s2.contribusourcesyndication.com": 4,
		"hits.convergetrack.com": 6,
		"fastclick.net": 4,
		"mediaplex.com": 4,
		"mplxtms.com": 4,
		"cm-commerce.com": 6,
		"media.conversio.com": 6,
		"c.conversionlogic.net": 6,
		"conversionruler.com": 4,
		"conversionsbox.com": 7,
		"conversionsondemand.com": 5,
		"ant.conversive.nl": 4,
		"convertexperiments.com": 6,
		"d3sjgucddk68ji.cloudfront.net": 2,
		"convertro.com": 4,
		"d1ivexoxmp59q7.cloudfront.net": 4,
		"conviva.com": 6,
		"cookieconsent.silktide.com": 5,
		"cookie-script.com": 5,
		"cookiebot.com": 5,
		"cookieq.com": 5,
		"lite.piclens.com": 2,
		"copacet.com": 4,
		"raasnet.com": 4,
		"coremotives.com": 4,
		"coull.com": 4,
		"cpmrocket.com": 4,
		"cpmprofit.com": 4,
		"cpmstar.com": 4,
		"captifymedia.com": 4,
		"cpx.to": 4,
		"cqcounter.com": 6,
		"cqq5id8n.com": 11,
		"cquotient.com": 6,
		"craftkeys.com": 4,
		"ads.crakmedia.com": 4,
		"craktraffic.com": 4,
		"crankyads.com": 4,
		"crashlytics.com": 101,
		"cetrk.com": 6,
		"crazyegg.com": 6,
		"dnn506yrbagrg.cloudfront.net": 6,
		"creafi-online-media.com": 4,
		"createjs.com": 9,
		"creativecommons.org": 8,
		"brandwatch.com": 6,
		"crimsonhexagon.com": 6,
		"hexagon-analytics.com": 6,
		"ctnsnet.com": 4,
		"crisp.chat": 2,
		"crisp.im": 2,
		"criteo.com": 4,
		"criteo.net": 4,
		"p.crm4d.com": 6,
		"crossengage.io": 6,
		"crosspixel.net": 4,
		"crsspxl.com": 4,
		"crosssell.info": 4,
		"crossss.com": 4,
		"widget.crowdignite.com": 4,
		"static.crowdscience.com": 4,
		"ss.crowdprocess.com": 2,
		"our.glossip.nl": 7,
		"widget.breakingburner.com": 7,
		"widget.crowdynews.com": 7,
		"searchg2.crownpeak.net": 5,
		"snippet.omm.crownpeak.com": 5,
		"cryptoloot.pro": 4,
		"ctnetwork.hu": 4,
		"adzhub.com": 4,
		"data.withcubed.com": 6,
		"cuelinks.com": 4,
		"cdn.cupinteractive.com": 4,
		"curse.com": 8,
		"cursecdn.com": 9,
		"assets.customer.io": 2,
		"widget.customerly.io": 2,
		"cxense.com": 4,
		"cxo.name": 6,
		"cyberwing.co.jp": 4,
		"cybersource.com": 6,
		"cygnus.com": 4,
		"da-ads.com": 4,
		"dailymail.co.uk": 8,
		"dailymotion.com": 8,
		"dailymotionbus.com": 8,
		"dm-event.net": 8,
		"dmcdn.net": 8,
		"dmxleo.com": 4,
		"ds1.nl": 4,
		"dantrack.net": 4,
		"dmclick.cn": 4,
		"tags.dashboardad.net": 4,
		"datacaciques.com": 6,
		"datacoral.com": 4,
		"abandonaid.com": 6,
		"datacrushers.com": 6,
		"datadome.co": 6,
		"optimahub.com": 6,
		"supert.ag": 5,
		"inextaction.net": 4,
		"nexac.com": 4,
		"datamind.ru": 4,
		"datatables.net": 2,
		"adunits.datawrkz.com": 4,
		"dataxpand.script.ag": 4,
		"tc.dataxpand.com": 4,
		"w55c.net": 4,
		"datds.net": 12,
		"pro-market.net": 4,
		"displaymarketplace.com": 4,
		"davebestdeals.com": 12,
		"dawandastatic.com": 8,
		"dc-storm.com": 4,
		"h4k5.com": 4,
		"stormcontainertag.com": 4,
		"stormiq.com": 4,
		"dcbap.com": 12,
		"dcmn.com": 4,
		"statslogger.rocket.persgroep.cloud": 4,
		"deadlinefunnel.com": 6,
		"cc2.dealer.com": 6,
		"d9lq0o81skkdj.cloudfront.net": 6,
		"esm1.net": 6,
		"static.dealer.com": 6,
		"decibelinsight.net": 6,
		"ads.dedicatedmedia.com": 4,
		"api.deep.bi": 6,
		"deepintent.com": 4,
		"defpush.com": 11,
		"deichmann.com": 4,
		"vxml4.delacon.com.au": 6,
		"tracking.percentmobile.com": 6,
		"adaction.se": 4,
		"de17a.com": 4,
		"deluxe.script.ag": 6,
		"delvenetworks.com": 7,
		"company-target.com": 4,
		"demandbase.com": 4,
		"dmd53.com": 4,
		"dmtracker.com": 4,
		"deqwas.net": 6,
		"devatics.com": 2,
		"developermedia.com": 4,
		"dapxl.com": 8,
		"deviantart.net": 8,
		"my.blueadvertise.com": 4,
		"dgm-au.com": 4,
		"s2d6.com": 4,
		"d31y97ze264gaa.cloudfront.net": 6,
		"d3von6il1wr7wo.cloudfront.net": 4,
		"dianomi.com": 4,
		"dianomioffers.co.uk": 4,
		"tag.didit.com": 4,
		"track.did-it.com": 4,
		"privacy-center.org": 5,
		"digg.com": 2,
		"digicert.com": 5,
		"phicdn.net": 5,
		"digidip.net": 4,
		"digiglitzmarketing.go2cloud.org": 6,
		"wtp101.com": 4,
		"digioh.com": 4,
		"lightboxcdn.com": 4,
		"digitalgov.gov": 6,
		"cookiereports.com": 5,
		"adtag.cc": 4,
		"adready.com": 4,
		"adreadytractions.com": 4,
		"cpxinteractive.com": 4,
		"directtrack.com": 4,
		"onenetworkdirect.net": 4,
		"track.digitalriver.com": 4,
		"dwin1.com": 4,
		"digiteka.net": 4,
		"ultimedia.com": 4,
		"digitru.st": 4,
		"widget.dihitt.com.br": 7,
		"dimml.io": 8,
		"keywordsconnect.com": 4,
		"directadvert.ru": 4,
		"directrev.com": 4,
		"discordapp.com": 2,
		"disneyplus.com": 0,
		"bamgrid.com": 0,
		"dssedge.com": 0,
		"dssott.com": 0,
		"d81mfvml8p5ml.cloudfront.net": 4,
		"disqus.com": 1,
		"disquscdn.com": 1,
		"disqusads.com": 4,
		"distiltag.com": 5,
		"districtm.ca": 4,
		"districtm.io": 4,
		"jsrdn.com": 6,
		"div.show": 12,
		"stats.vertriebsassistent.de": 6,
		"tag.divvit.com": 6,
		"d-msquared.com": 4,
		"and.co.uk": 8,
		"dmm.co.jp": 3,
		"ctret.de": 8,
		"toolbar.dockvine.com": 2,
		"awecr.com": 0,
		"fwbntw.com": 0,
		"s.dogannet.tv": 4,
		"domain.glass": 8,
		"www.domodomain.com": 6,
		"donation-tools.org": 12,
		"doofinder.com": 2,
		"embed.doorbell.io": 5,
		"dotandad.com": 4,
		"trackedlink.net": 2,
		"dotmetrics.net": 6,
		"dotomi.com": 4,
		"dtmc.com": 4,
		"dtmpub.com": 4,
		"double.net": 4,
		"2mdn.net": 4,
		"doubleclick.net": 4,
		"invitemedia.com": 4,
		"doubleclick.com": 4,
		"doublepimp.com": 3,
		"doublepimpssl.com": 3,
		"redcourtside.com": 3,
		"xeontopa.com": 3,
		"zerezas.com": 3,
		"doubleverify.com": 4,
		"wrating.com": 6,
		"adsymptotic.com": 4,
		"dreame.tech": 8,
		"dreametech.com": 8,
		"dreamlab.pl": 4,
		"drift.com": 2,
		"js.driftt.com": 2,
		"getdrip.com": 2,
		"dropbox.com": 2,
		"dropboxstatic.com": 2,
		"z5x.net": 4,
		"dsp-rambler.ru": 4,
		"m6d.com": 4,
		"media6degrees.com": 4,
		"dtscout.com": 4,
		"dd-cdn.multiscreensite.com": 4,
		"px.multiscreensite.com": 4,
		"cdn-0.d41.co": 6,
		"cn01.dwstat.cn": 6,
		"dynad.net": 4,
		"dyntrk.com": 4,
		"dyntracker.de": 8,
		"media01.eu": 8,
		"content.dl-rms.com": 4,
		"dlqm.net": 4,
		"questionmarket.com": 4,
		"dynamicyield.com": 5,
		"beacons.hottraffic.nl": 4,
		"dynatrace.com": 6,
		"dyncdn.me": 11,
		"e-planning.net": 4,
		"eadv.it": 4,
		"eanalyzer.de": 11,
		"early-birds.fr": 4,
		"cdn.earnify.com": 4,
		"earnify.com": 6,
		"easyads.bg": 4,
		"easylist.club": 11,
		"classistatic.de": 4,
		"ebay-us.com": 4,
		"ebay.com": 4,
		"ebay.de": 4,
		"ebayclassifiedsgroup.com": 4,
		"ebaycommercenetwork.com": 4,
		"ebaydesc.com": 4,
		"ebayimg.com": 4,
		"ebayrtm.com": 4,
		"ebaystatic.com": 4,
		"ad.about.co.kr": 4,
		"adcheck.about.co.kr": 4,
		"adn.ebay.com": 4,
		"beead.co.uk": 4,
		"beead.fr": 4,
		"beead.net": 4,
		"ebuzzing.com": 4,
		"ebz.io": 4,
		"echoenabled.com": 4,
		"eclick.vn": 4,
		"econda-monitor.de": 6,
		"eco-tag.jp": 4,
		"alphacdn.net": 9,
		"edg.io": 9,
		"edgecast.com": 9,
		"edgecastcdn.net": 9,
		"edgecastdns.net": 9,
		"sigmacdn.net": 9,
		"ecustomeropinions.com": 4,
		"effectivemeasure.net": 4,
		"effiliation.com": 4,
		"egain.net": 2,
		"cloud-emea.analytics-egain.com": 6,
		"ehi-siegel.de": 2,
		"ekmpinpoint.com": 6,
		"ekomi.de": 1,
		"elasticad.net": 4,
		"elasticbeanstalk.com": 6,
		"cloudcell.com": 2,
		"ea.com": 2,
		"eamobile.com": 2,
		"element.io": 7,
		"riot.im": 7,
		"elicitapp.com": 4,
		"eloqua.com": 4,
		"en25.com": 4,
		"eluxer.net": 12,
		"tracker.emailaptitude.com": 4,
		"tag.email-attitude.com": 4,
		"app.emarketeer.com": 4,
		"embed.ly": 6,
		"embedly.com": 6,
		"emediate.dk": 4,
		"emediate.eu": 4,
		"emediate.se": 4,
		"emetriq.de": 4,
		"e2ma.net": 4,
		"adinsight.co.kr": 4,
		"colbenson.es": 4,
		"emsmobile.de": 8,
		"sitecompass.com": 4,
		"enectoanalytics.com": 6,
		"trk.enecto.com": 6,
		"track.engagesciences.com": 6,
		"widget.engageya.com": 4,
		"engagio.com": 6,
		"engineseeker.com": 4,
		"enquisite.com": 4,
		"adtlgc.com": 4,
		"ats.tumri.net": 4,
		"ensighten.com": 5,
		"envolve.com": 2,
		"cdn.callbackkiller.com": 2,
		"email-reflex.com": 4,
		"epicgameads.com": 4,
		"trafficmp.com": 4,
		"adshost1.com": 4,
		"adshost2.com": 4,
		"epom.com": 4,
		"epoq.de": 2,
		"banzaiadv.it": 4,
		"eproof.com": 6,
		"equitystory.com": 6,
		"eqads.com": 4,
		"ero-advertising.com": 3,
		"eroadvertising.com": 3,
		"d15qhc0lu1ghnk.cloudfront.net": 6,
		"errorception.com": 6,
		"eshopcomp.com": 12,
		"espncdn.com": 9,
		"esprit.de": 8,
		"cybermonitor.com": 6,
		"estat.com": 6,
		"teste-s3-maycon.s3.amazonaws.com": 4,
		"etahub.com": 11,
		"etargetnet.com": 4,
		"ethn.io": 4,
		"pages.etology.com": 4,
		"sa.etp-prod.com": 6,
		"etracker.com": 6,
		"etracker.de": 6,
		"sedotracker.com": 6,
		"etrigue.com": 4,
		"etsystatic.com": 9,
		"eulerian.net": 6,
		"eultech.fnac.com": 6,
		"ew3.io": 6,
		"euroads.dk": 4,
		"euroads.fi": 4,
		"euroads.no": 4,
		"newpromo.europacash.com": 4,
		"tracker.euroweb.net": 4,
		"apptegic.com": 2,
		"evergage.com": 2,
		"listener.everstring.com": 6,
		"waterfrontmedia.com": 7,
		"betrad.com": 5,
		"evidon.com": 5,
		"evisitanalyst.com": 4,
		"evisitcs.com": 4,
		"websiteperform.com": 4,
		"ads.exactdrive.com": 4,
		"exactag.com": 6,
		"exelator.com": 4,
		"dynamicoxygen.com": 4,
		"exitjunction.com": 4,
		"exdynsrv.com": 3,
		"exoclick.com": 3,
		"exosrv.com": 3,
		"exoticads.com": 3,
		"expedia.com": 8,
		"trvl-px.com": 8,
		"eccmp.com": 8,
		"audienceiq.com": 4,
		"techlightenment.com": 4,
		"expo-max.com": 4,
		"server.exposebox.com": 4,
		"sf.exposebox.com": 2,
		"express.co.uk": 8,
		"d1lp05q4sghme9.cloudfront.net": 2,
		"extreme-dm.com": 6,
		"eyenewton.ru": 2,
		"eyeota.net": 4,
		"eyereturn.com": 4,
		"eyeviewads.com": 4,
		"ezakus.net": 4,
		"f11-ads.com": 4,
		"facebook.com": 4,
		"facebook.net": 4,
		"graph.facebook.com": 4,
		"fbcdn.net": 9,
		"fbsbx.com": 9,
		"facetz.net": 4,
		"adsfac.eu": 4,
		"adsfac.net": 4,
		"adsfac.sg": 4,
		"adsfac.us": 4,
		"faktor.io": 6,
		"thefancy.com": 7,
		"d1q7pknmpq2wkm.cloudfront.net": 4,
		"fap.to": 8,
		"farlightgames.com": 8,
		"fastly-insights.com": 6,
		"fastly.net": 9,
		"fastlylb.net": 9,
		"fastly-edge.com": 9,
		"fastly-masque.net": 9,
		"fastpic.ru": 10,
		"fmpub.net": 4,
		"fby.s3.amazonaws.com": 2,
		"feedbackify.com": 2,
		"feedburner.com": 4,
		"feedify.de": 7,
		"feedjit.com": 4,
		"log.feedjit.com": 4,
		"tracking.feedperfect.com": 4,
		"feedsportal.com": 4,
		"feefo.com": 2,
		"fidelity-media.com": 4,
		"fiksu.com": 4,
		"filamentapp.s3.amazonaws.com": 4,
		"fileserve.xyz": 10,
		"tools.financeads.net": 4,
		"tracker.financialcontent.com": 4,
		"findizer.fr": 8,
		"findologic.com": 2,
		"app-measurement.com": 101,
		"fcm.googleapis.com": 101,
		"firebase.com": 101,
		"firebase.google.com": 101,
		"firebase.googleapis.com": 101,
		"firebaseapp.com": 101,
		"firebaseappcheck.googleapis.com": 101,
		"firebasedynamiclinks-ipv4.googleapis.com": 101,
		"firebasedynamiclinks-ipv6.googleapis.com": 101,
		"firebasedynamiclinks.googleapis.com": 101,
		"firebaseinappmessaging.googleapis.com": 101,
		"firebaseinstallations.googleapis.com": 101,
		"firebaselogging-pa.googleapis.com": 101,
		"firebaselogging.googleapis.com": 101,
		"firebaseperusertopics-pa.googleapis.com": 101,
		"firebaseremoteconfig.googleapis.com": 101,
		"firebaseio.com": 8,
		"firstimpression.io": 4,
		"fitanalytics.com": 6,
		"fivetran.com": 6,
		"flagads.net": 4,
		"flagcounter.com": 4,
		"flashnews.com.au": 0,
		"flashtalking.com": 4,
		"flattr.com": 7,
		"flexlinks.com": 4,
		"linkoffers.net": 4,
		"flickr.com": 7,
		"staticflickr.com": 7,
		"lflipboard.com": 6,
		"flipboard.com": 6,
		"flite.com": 4,
		"flixcdn.com": 9,
		"flix360.com": 8,
		"flixcar.com": 8,
		"flocktory.com": 6,
		"flowplayer.org": 4,
		"adingo.jp": 4,
		"clicken.us": 4,
		"strcst.net": 4,
		"fluidads.co": 4,
		"fluidsurveys.com": 2,
		"cdn.flurry.com": 101,
		"data.flurry.com": 101,
		"flurry.com": 101,
		"flx1.com": 4,
		"flxpxl.com": 4,
		"api.flyertown.ca": 6,
		"adservinghost.com": 4,
		"adservinginternational.com": 4,
		"special.matchtv.ru": 6,
		"kavijaseuranta.fi": 2,
		"fontawesome.com": 9,
		"foodieblogroll.com": 7,
		"footprintlive.com": 4,
		"footprintdns.com": 11,
		"forcetrac.com": 2,
		"fqsecure.com": 4,
		"fqtag.com": 4,
		"securepaths.com": 4,
		"4seeresults.com": 5,
		"foresee.com": 5,
		"cdn-static.formisimo.com": 4,
		"forter.com": 4,
		"fortlachanhecksof.info": 11,
		"platform.foursquare.com": 4,
		"fout.jp": 4,
		"fimserve.com": 4,
		"foxsports.com.au": 0,
		"fncstatic.com": 9,
		"cdn.foxpush.net": 4,
		"foxpush.com": 4,
		"foxtel.com.au": 0,
		"foxydeal.com": 12,
		"yabidos.com": 4,
		"besucherstatistiken.com": 6,
		"compteurdevisite.com": 6,
		"contadorvisitasgratis.com": 6,
		"contatoreaccessi.com": 6,
		"freecounterstat.com": 6,
		"statcounterfree.com": 6,
		"webcontadores.com": 6,
		"fastonlineusers.com": 6,
		"fastwebcounter.com": 6,
		"freeonlineusers.com": 6,
		"atoomic.com": 6,
		"free-pagerank.com": 6,
		"freedom.com": 6,
		"freegeoip.net": 6,
		"freenet.de": 4,
		"freent.de": 4,
		"freeview.com": 0,
		"freeview.com.au": 0,
		"freeviewaustralia.tv": 0,
		"fwmrm.net": 4,
		"heimdall.fresh8.co": 6,
		"d36mpcpuzc4ztk.cloudfront.net": 2,
		"freshdesk.com": 2,
		"freshplum.com": 4,
		"friendbuy.com": 6,
		"friendfeed.com": 7,
		"adultfriendfinder.com": 3,
		"amigos.com": 3,
		"board-books.com": 3,
		"cams.com": 3,
		"facebookofsex.com": 3,
		"getiton.com": 3,
		"nostringsattached.com": 3,
		"pop6.com": 3,
		"streamray.com": 3,
		"inpref.com": 4,
		"inpref.s3-external-3.amazonaws.com": 4,
		"inpref.s3.amazonaws.com": 4,
		"adflan.com": 4,
		"fruitflan.com": 4,
		"fstrk.net": 6,
		"cookie.fuel451.com": 4,
		"fullstory.com": 6,
		"track.funnelytics.io": 6,
		"angsrvr.com": 4,
		"fyber.com": 4,
		"game-advertising-online.com": 4,
		"gameanalytics.com": 101,
		"gamedistribution.com": 8,
		"gamerdna.com": 7,
		"gannett-cdn.com": 0,
		"gaug.es": 6,
		"gpm-digital.com": 0,
		"js.gb-world.net": 7,
		"gdeslon.ru": 4,
		"gdmdigital.com": 4,
		"gntm.geeen.co.jp": 6,
		"lpomax.net": 6,
		"gemius.pl": 4,
		"generaltracking.de": 11,
		"genesismedia.com": 4,
		"gssprt.jp": 4,
		"rsvpgenius.com": 6,
		"genoo.com": 4,
		"js.geoads.com": 4,
		"geolify.com": 4,
		"geoplugin.net": 6,
		"geotrust.com": 5,
		"geovisite.com": 6,
		"gestionpub.com": 4,
		"app.getresponse.com": 2,
		"getsitecontrol.com": 4,
		"getconversion.net": 2,
		"widgets.getglue.com": 0,
		"adhigh.net": 4,
		"static.getkudos.me": 1,
		"yottos.com": 4,
		"gsfn.us": 1,
		"gettyimages.com": 8,
		"sensic.net": 4,
		"gfycat.com": 7,
		"a.giantrealm.com": 4,
		"videostat.com": 4,
		"gigaonclick.com": 4,
		"analytics.gigyahosting1.com": 6,
		"gigcount.com": 6,
		"gigya.com": 6,
		"service.giosg.com": 6,
		"giphy.com": 7,
		"giraff.io": 4,
		"github.com": 2,
		"githubassets.com": 2,
		"githubusercontent.com": 2,
		"ghcr.io": 2,
		"github.blog": 2,
		"github.dev": 2,
		"octocaptcha.com": 2,
		"githubapp.com": 2,
		"github.io": 10,
		"aff3.gittigidiyor.com": 4,
		"gittip.com": 2,
		"sitest.jp": 6,
		"glganltcs.space": 12,
		"globalwebindex.net": 6,
		"globalnotifier.com": 11,
		"globalsign.com": 8,
		"ad.globaltakeoff.net": 4,
		"glomex.cloud": 0,
		"glomex.com": 0,
		"glotgrx.com": 11,
		"a.gmdelivery.com": 4,
		"gmail.com": 13,
		"ad.atown.jp": 4,
		"gmx.net": 8,
		"gmxpro.net": 8,
		"go.com": 8,
		"affiliate.godaddy.com": 4,
		"trafficfacts.com": 6,
		"seal.godaddy.com": 5,
		"tracking.godatafeed.com": 6,
		"counter.goingup.com": 6,
		"axf8.net": 6,
		"goodadvert.ru": 4,
		"google.at": 4,
		"google.be": 4,
		"google.ca": 4,
		"google.ch": 4,
		"google.co.id": 4,
		"google.co.in": 4,
		"google.co.jp": 4,
		"google.co.ma": 4,
		"google.co.th": 4,
		"google.co.uk": 4,
		"google.com": 4,
		"google.com.ar": 4,
		"google.com.au": 4,
		"google.com.br": 4,
		"google.com.mx": 4,
		"google.com.tr": 4,
		"google.com.tw": 4,
		"google.com.ua": 4,
		"google.cz": 4,
		"google.de": 4,
		"google.dk": 4,
		"google.dz": 4,
		"google.es": 4,
		"google.fi": 4,
		"google.fr": 4,
		"google.gr": 4,
		"google.hu": 4,
		"google.ie": 4,
		"google.it": 4,
		"google.nl": 4,
		"google.no": 4,
		"google.pl": 4,
		"google.pt": 4,
		"google.ro": 4,
		"google.rs": 4,
		"google.ru": 4,
		"google.se": 4,
		"google.tn": 4,
		"1e100.net": 4,
		"agnss.goog": 4,
		"channel.status.request.url": 4,
		"g.cn": 4,
		"g.co": 4,
		"google.ad": 4,
		"google.ae": 4,
		"google.al": 4,
		"google.am": 4,
		"google.as": 4,
		"google.az": 4,
		"google.ba": 4,
		"google.bf": 4,
		"google.bg": 4,
		"google.bi": 4,
		"google.bj": 4,
		"google.bs": 4,
		"google.bt": 4,
		"google.by": 4,
		"google.cat": 4,
		"google.cd": 4,
		"google.cf": 4,
		"google.cg": 4,
		"google.ci": 4,
		"google.cl": 4,
		"google.cm": 4,
		"google.cn": 4,
		"google.co.ao": 4,
		"google.co.bw": 4,
		"google.co.ck": 4,
		"google.co.cr": 4,
		"google.co.il": 4,
		"google.co.ke": 4,
		"google.co.kr": 4,
		"google.co.ls": 4,
		"google.co.mz": 4,
		"google.co.nz": 4,
		"google.co.tz": 4,
		"google.co.ug": 4,
		"google.co.uz": 4,
		"google.co.ve": 4,
		"google.co.vi": 4,
		"google.co.za": 4,
		"google.co.zm": 4,
		"google.co.zw": 4,
		"google.com.af": 4,
		"google.com.ag": 4,
		"google.com.ai": 4,
		"google.com.bd": 4,
		"google.com.bh": 4,
		"google.com.bn": 4,
		"google.com.bo": 4,
		"google.com.bz": 4,
		"google.com.co": 4,
		"google.com.cu": 4,
		"google.com.cy": 4,
		"google.com.ec": 4,
		"google.com.eg": 4,
		"google.com.et": 4,
		"google.com.fj": 4,
		"google.com.gh": 4,
		"google.com.gi": 4,
		"google.com.gt": 4,
		"google.com.hk": 4,
		"google.com.jm": 4,
		"google.com.kh": 4,
		"google.com.kw": 4,
		"google.com.lb": 4,
		"google.com.my": 4,
		"google.com.na": 4,
		"google.com.nf": 4,
		"google.com.ng": 4,
		"google.com.ni": 4,
		"google.com.np": 4,
		"google.com.om": 4,
		"google.com.pa": 4,
		"google.com.pe": 4,
		"google.com.pg": 4,
		"google.com.ph": 4,
		"google.com.pk": 4,
		"google.com.pr": 4,
		"google.com.py": 4,
		"google.com.qa": 4,
		"google.com.sa": 4,
		"google.com.sb": 4,
		"google.com.sg": 4,
		"google.com.sl": 4,
		"google.com.sv": 4,
		"google.com.tj": 4,
		"google.com.uy": 4,
		"google.com.vc": 4,
		"google.com.vn": 4,
		"google.cv": 4,
		"google.dj": 4,
		"google.dm": 4,
		"google.ee": 4,
		"google.fm": 4,
		"google.ga": 4,
		"google.ge": 4,
		"google.gg": 4,
		"google.gl": 4,
		"google.gm": 4,
		"google.gp": 4,
		"google.gy": 4,
		"google.hn": 4,
		"google.hr": 4,
		"google.ht": 4,
		"google.im": 4,
		"google.in": 4,
		"google.iq": 4,
		"google.is": 4,
		"google.je": 4,
		"google.jo": 4,
		"google.kg": 4,
		"google.ki": 4,
		"google.kz": 4,
		"google.la": 4,
		"google.li": 4,
		"google.lk": 4,
		"google.lt": 4,
		"google.lu": 4,
		"google.lv": 4,
		"google.md": 4,
		"google.me": 4,
		"google.mg": 4,
		"google.mk": 4,
		"google.ml": 4,
		"google.mn": 4,
		"google.ms": 4,
		"google.mu": 4,
		"google.mv": 4,
		"google.mw": 4,
		"google.ne": 4,
		"google.net": 4,
		"google.nr": 4,
		"google.nu": 4,
		"google.org": 4,
		"google.pn": 4,
		"google.ps": 4,
		"google.rw": 4,
		"google.sc": 4,
		"google.sh": 4,
		"google.si": 4,
		"google.sk": 4,
		"google.sm": 4,
		"google.sn": 4,
		"google.so": 4,
		"google.sr": 4,
		"google.st": 4,
		"google.td": 4,
		"google.tg": 4,
		"google.tk": 4,
		"google.tl": 4,
		"google.tm": 4,
		"google.to": 4,
		"google.tt": 4,
		"google.us": 4,
		"google.vg": 4,
		"google.vu": 4,
		"google.ws": 4,
		"googleapis.cn": 4,
		"googlecode.com": 4,
		"googledownloads.cn": 4,
		"googleoptimize.com": 4,
		"googleweblight.in": 4,
		"googlezip.net": 4,
		"gstatic.cn": 4,
		"news.google.com": 4,
		"oo.gl": 4,
		"withgoogle.com": 4,
		"googleadservices.com": 4,
		"google-analytics.com": 6,
		"app-analytics-services.com": 6,
		"ssl-google-analytics.l.google.com": 6,
		"www-googletagmanager.l.google.com": 6,
		"appspot.com": 10,
		"googlehosted.com": 10,
		"accounts.google.com": 2,
		"myaccount.google.com": 2,
		"oauth2.googleapis.com": 2,
		"ogs.google.com": 2,
		"securetoken.googleapis.com": 2,
		"beacons-google.com": 6,
		"alt1-mtalk.google.com": 7,
		"alt2-mtalk.google.com": 7,
		"alt3-mtalk.google.com": 7,
		"alt4-mtalk.google.com": 7,
		"alt5-mtalk.google.com": 7,
		"alt6-mtalk.google.com": 7,
		"alt7-mtalk.google.com": 7,
		"alt8-mtalk.google.com": 7,
		"chat.google.com": 7,
		"mobile-gtalk.l.google.com": 7,
		"mobile-gtalk4.l.google.com": 7,
		"mtalk.google.com": 7,
		"mtalk4.google.com": 7,
		"talk.google.com": 7,
		"talk.l.google.com": 7,
		"talkx.l.google.com": 7,
		"cloud.google.com": 10,
		"gcp.gvt2.com": 10,
		"storage.googleapis.com": 10,
		"adsensecustomsearchads.com": 4,
		"dns.google": 10,
		"dns.google.com": 10,
		"google-public-dns-a.google.com": 10,
		"google-public-dns-b.google.com": 10,
		"domains.google": 10,
		"googledomains.com": 10,
		"nic.google": 10,
		"registry.google": 10,
		"edge.google.com": 9,
		"mail-ads.google.com": 13,
		"fonts.googleapis.com": 9,
		"cloudfunctions.net": 10,
		"ghs.googlehosted.com": 10,
		"ghs4.googlehosted.com": 10,
		"ghs46.googlehosted.com": 10,
		"ghs6.googlehosted.com": 10,
		"googlehosted.l.googleusercontent.com": 10,
		"run.app": 10,
		"supl.google.com": 8,
		"earth.app.goo.gl": 2,
		"geo0.ggpht.com": 2,
		"geo1.ggpht.com": 2,
		"geo2.ggpht.com": 2,
		"geo3.ggpht.com": 2,
		"kh.google.com": 2,
		"maps.app.goo.gl": 2,
		"maps.google.ca": 2,
		"maps.google.ch": 2,
		"maps.google.co.jp": 2,
		"maps.google.co.uk": 2,
		"maps.google.com": 2,
		"maps.google.com.mx": 2,
		"maps.google.es": 2,
		"maps.google.se": 2,
		"maps.gstatic.com": 2,
		"adsense.google.com": 6,
		"adservice.google.ca": 6,
		"adservice.google.co.in": 6,
		"adservice.google.co.kr": 6,
		"adservice.google.co.uk": 6,
		"adservice.google.co.za": 6,
		"adservice.google.com": 6,
		"adservice.google.com.ar": 6,
		"adservice.google.com.au": 6,
		"adservice.google.com.br": 6,
		"adservice.google.com.co": 6,
		"adservice.google.com.gt": 6,
		"adservice.google.com.mx": 6,
		"adservice.google.com.pe": 6,
		"adservice.google.com.ph": 6,
		"adservice.google.com.pk": 6,
		"adservice.google.com.tr": 6,
		"adservice.google.com.tw": 6,
		"adservice.google.com.vn": 6,
		"adservice.google.de": 6,
		"adservice.google.dk": 6,
		"adservice.google.es": 6,
		"adservice.google.fr": 6,
		"adservice.google.nl": 6,
		"adservice.google.no": 6,
		"adservice.google.pl": 6,
		"adservice.google.ru": 6,
		"adservice.google.vg": 6,
		"dai.google.com": 6,
		"doubleclickbygoogle.com": 6,
		"googlesyndication-cn.com": 6,
		"duo.google.com": 2,
		"hangouts.clients6.google.com": 2,
		"hangouts.google.com": 2,
		"hangouts.googleapis.com": 2,
		"meet.google.com": 2,
		"meetings.googleapis.com": 2,
		"stun.l.google.com": 2,
		"stun1.l.google.com": 2,
		"ggpht.com": 9,
		"play-fe.googleapis.com": 8,
		"play-lh.googleusercontent.com": 8,
		"play.google.com": 8,
		"play.googleapis.com": 8,
		"1e100cdn.net": 8,
		"gvt1.com": 8,
		"gvt2.com": 8,
		"gvt3.com": 8,
		"googlesyndication.com": 4,
		"googletagmanager.com": 5,
		"googletagservices.com": 5,
		"translate.google.com": 2,
		"googletraveladservices.com": 4,
		"pki.goog": 5,
		"googlecommerce.com": 6,
		"googleusercontent.com": 9,
		"telephony.goog": 2,
		"voice.google.com": 2,
		"gmodules.com": 2,
		"calendar.google.com": 2,
		"contacts.google.com": 2,
		"currents.google.com": 2,
		"docs.google.com": 2,
		"drive.google.com": 2,
		"forms.google.com": 2,
		"gsuite.google.com": 2,
		"jamboard.google.com": 2,
		"keep.google.com": 2,
		"plus.google.com": 2,
		"sheets.google.com": 2,
		"slides.google.com": 2,
		"spreadsheets.google.com": 2,
		"googleapis.com": 9,
		"gooal.herokuapp.com": 6,
		"gooo.al": 6,
		"cdn.triggertag.gorillanation.com": 4,
		"evolvemediametrics.com": 4,
		"d1l6p2sc9645hc.cloudfront.net": 6,
		"gosquared.com": 6,
		"gostats.com": 6,
		"govmetric.com": 6,
		"servmetric.com": 6,
		"b.grabo.bg": 4,
		"trw12.com": 4,
		"tuberewards.com": 4,
		"d2bw638ufki166.cloudfront.net": 6,
		"granify.com": 6,
		"grapeshot.co.uk": 4,
		"gscontxt.net": 4,
		"graphcomment.com": 5,
		"gravatar.com": 7,
		"cdn.gravitec.net": 6,
		"gravity.com": 6,
		"grvcdn.com": 6,
		"greatviews.de": 4,
		"gandrad.org": 4,
		"green-red.com": 4,
		"co2stats.com": 2,
		"greenstory.ca": 6,
		"greentube.com": 7,
		"gt-cdn.net": 7,
		"greystripe.com": 4,
		"groovehq.com": 2,
		"groovinads.com": 4,
		"bidagent.xad.com": 4,
		"gmads.net": 4,
		"grmtech.net": 4,
		"media.gsimedia.net": 4,
		"gstatic.com": 9,
		"fx.gtop.ro": 6,
		"fx.gtopstats.com": 6,
		"gubagootracking.com": 4,
		"guj.de": 4,
		"emsservice.de": 4,
		"gumgum.com": 4,
		"gumroad.com": 7,
		"gunggo.com": 4,
		"h12-media.com": 4,
		"h12-media.net": 4,
		"hnbutton.appspot.com": 7,
		"haendlerbund.de": 2,
		"halogennetwork.com": 7,
		"d1l7z5ofrj6ab8.cloudfront.net": 2,
		"ad.harrenmedianetwork.com": 4,
		"ads.networkhm.com": 4,
		"app.hatchbuck.com": 6,
		"hhcdn.ru": 6,
		"healte.de": 11,
		"d36lvucg9kzous.cloudfront.net": 6,
		"heapanalytics.com": 6,
		"heatmap.it": 6,
		"weltsport.net": 8,
		"hellobar.com": 7,
		"hellosociety.com": 6,
		"here.com": 8,
		"herokuapp.com": 10,
		"heureka.cz": 4,
		"heybubble.com": 2,
		"heyos.com": 4,
		"adlink.net": 4,
		"comclick.com": 4,
		"hi-mediaserver.com": 4,
		"himediads.com": 4,
		"himediadx.com": 4,
		"hiconversion.com": 4,
		"highwebmedia.com": 3,
		"hwcdn.net": 6,
		"hiiir.com": 4,
		"hiro.tv": 4,
		"histats.com": 4,
		"hit-parade.com": 4,
		"hit.ua": 4,
		"hitslink.com": 4,
		"hitsprocessor.com": 4,
		"hitsniffer.com": 4,
		"hittail.com": 4,
		"hivedx.com": 4,
		"ads.thehiveworks.com": 4,
		"hockeyapp.net": 101,
		"hoholikik.club": 12,
		"h-cdn.com": 0,
		"homeaway.com": 8,
		"honeybadger.io": 6,
		"hlserve.com": 4,
		"apiae.hopscore.com": 4,
		"hotdogsandads.com": 11,
		"hotjar.com": 6,
		"hotkeys.com": 4,
		"hotlog.ru": 4,
		"hotwords.com": 4,
		"hotwords.es": 4,
		"howtank.com": 7,
		"hqentertainmentnetwork.com": 4,
		"justservingfiles.net": 4,
		"hsoub.com": 4,
		"hstrck.com": 8,
		"httpool.com": 4,
		"toboads.com": 4,
		"hubrus.com": 4,
		"hs-analytics.net": 6,
		"hs-scripts.com": 6,
		"hsleadflows.net": 6,
		"hubapi.com": 6,
		"hubspot.com": 6,
		"forms.hubspot.com": 2,
		"hubvisor.io": 4,
		"files.hucksterbot.com": 4,
		"hupso.com": 7,
		"hurra.com": 4,
		"hybrid.ai": 4,
		"targetix.net": 4,
		"hypeads.org": 4,
		"hypercomments.com": 1,
		"hyves.nl": 4,
		"hyvyd.com": 8,
		"ib-ibi.com": 4,
		"i-mobile.co.jp": 4,
		"r.i.ua": 4,
		"i10c.net": 11,
		"i2i.jp": 6,
		"i2idata.com": 6,
		"consensu.org": 5,
		"iadvize.com": 2,
		"cmcore.com": 6,
		"coremetrics.com": 6,
		"coremetrics.eu": 6,
		"tracker.icerocket.com": 7,
		"nsimg.net": 2,
		"optimix.asia": 4,
		"ic-live.com": 4,
		"icstats.nl": 6,
		"icuazeczpeoohx.com": 11,
		"id-news.net": 4,
		"idcdn.de": 4,
		"cdn.id.services": 6,
		"e-generator.com": 4,
		"idealo.com": 4,
		"identrust.com": 5,
		"ideoclick.com": 4,
		"s.idio.co": 4,
		"ie8eamus.com": 11,
		"600z.com": 4,
		"api.iflychat.com": 2,
		"ignitionone.com": 6,
		"knotice.net": 6,
		"igodigital.com": 2,
		"ad.wsod.com": 6,
		"collserve.com": 6,
		"ihvmcqojoj.com": 11,
		"iias.eu": 3,
		"ijento.com": 6,
		"adv.imadrep.co.kr": 4,
		"worthathousandwords.com": 4,
		"picadmedia.com": 4,
		"imgix.net": 9,
		"imgur.com": 8,
		"vidigital.ru": 4,
		"immanalytics.com": 2,
		"immobilienscout24.de": 8,
		"static-immobilienscout24.de": 8,
		"imonomy.com": 6,
		"7eer.net": 5,
		"d3cxv97fi8q177.cloudfront.net": 5,
		"evyy.net": 5,
		"impactradius-event.com": 5,
		"impactradius-tag.com": 5,
		"impactradius.com": 5,
		"ojrq.net": 5,
		"r7ls.net": 5,
		"impresionesweb.com": 4,
		"360yield.com": 4,
		"iljmp.com": 6,
		"inbenta.com": 6,
		"inboxsdk.com": 8,
		"indeed.com": 4,
		"casalemedia.com": 4,
		"indexww.com": 4,
		"indieclick.com": 4,
		"industrybrains.com": 4,
		"impdesk.com": 4,
		"impressiondesk.com": 4,
		"zachysprod.infiniteanalytics.com": 6,
		"infinity-tracking.net": 6,
		"engine.influads.com": 4,
		"infolinks.com": 4,
		"intextscript.com": 4,
		"ioam.de": 6,
		"iocnt.net": 6,
		"ivwbox.de": 6,
		"informer.com": 6,
		"infusionsoft.com": 4,
		"keap.com": 4,
		"innity.com": 4,
		"innity.net": 4,
		"innogames.com": 8,
		"innogames.de": 8,
		"innogamescdn.com": 8,
		"innovid.com": 4,
		"inside-graph.com": 7,
		"useinsider.com": 6,
		"insightexpressai.com": 6,
		"inskinad.com": 4,
		"inskinmedia.com": 4,
		"inspectlet.com": 6,
		"inspsearchapi.com": 4,
		"cdninstagram.com": 8,
		"instagram.com": 8,
		"tcgtrkr.com": 2,
		"sdad.guru": 4,
		"insticator.com": 4,
		"load.instinctiveads.com": 4,
		"intango.com": 4,
		"adsafeprotected.com": 4,
		"iasds01.com": 4,
		"integral-marketing.com": 4,
		"intelliad.com": 6,
		"intelliad.de": 6,
		"saas.intelligencefocus.com": 6,
		"ist-track.com": 4,
		"intensedebate.com": 2,
		"intentiq.com": 4,
		"intentmedia.net": 4,
		"intercom.com": 2,
		"intercom.io": 2,
		"intercomassets.com": 2,
		"intercomcdn.com": 2,
		"interedy.info": 11,
		"ads.intergi.com": 4,
		"intermarkets.net": 4,
		"intermundomedia.com": 4,
		"bbelements.com": 4,
		"goadservices.com": 4,
		"ibillboard.com": 4,
		"mediainter.net": 4,
		"voice2page.com": 0,
		"ibpxl.com": 7,
		"ibsrv.net": 7,
		"interpolls.com": 4,
		"ps7894.com": 4,
		"intilery-analytics.com": 6,
		"im-apps.net": 6,
		"investingchannel.com": 8,
		"inviziads.com": 4,
		"js12.invoca.net": 4,
		"ringrevenue.com": 4,
		"invodo.com": 6,
		"ionicframework.com": 8,
		"dsp.io": 4,
		"iesnare.com": 5,
		"iovation.com": 5,
		"ip-label.net": 6,
		"eltoro.com": 6,
		"iptargeting.com": 6,
		"ip-tracker.org": 6,
		"iptrack.io": 6,
		"iperceptions.com": 2,
		"dust.ipfingerprint.com": 6,
		"mbww.com": 4,
		"ipify.org": 8,
		"ipinfo.io": 2,
		"iplogger.ru": 6,
		"centraliprom.com": 4,
		"iprom.net": 4,
		"ipromote.com": 4,
		"clickmanage.com": 4,
		"iq.com": 0,
		"iqiyi.com": 0,
		"qy.net": 0,
		"addelive.com": 4,
		"afdads.com": 4,
		"delivery47.com": 4,
		"ironsrc.com": 4,
		"ironsrc.net": 4,
		"is.com": 4,
		"soom.la": 4,
		"supersonicads.com": 4,
		"tapjoy.com": 4,
		"adsbyisocket.com": 4,
		"isocket.com": 4,
		"isolarcloud.com": 6,
		"isolarcloud.com.a.lahuashanbx.com": 6,
		"isolarcloud.com.w.cdngslb.com": 6,
		"isolarcloud.com.w.kunlunsl.com": 6,
		"ispot.tv": 4,
		"itineraire.info": 2,
		"autolinkmaker.itunes.apple.com": 4,
		"ity.im": 4,
		"iubenda.com": 5,
		"ivcbrasil.org.br": 6,
		"ivitrack.com": 4,
		"iwiw.hu": 2,
		"ixiaa.com": 4,
		"ixquick.com": 8,
		"cdn.izooto.com": 6,
		"jlist.com": 4,
		"getjaco.com": 6,
		"janrainbackplane.com": 6,
		"rpxnow.com": 6,
		"jeeng.com": 4,
		"api.jeeng.com": 4,
		"phone-analytics.com": 6,
		"jetlore.com": 6,
		"pixel.wp.com": 6,
		"stats.wp.com": 6,
		"jetpackdigital.com": 6,
		"jimcdn.com": 10,
		"jimdo.com": 10,
		"jimstatic.com": 10,
		"ads.jinkads.com": 4,
		"jirafe.com": 6,
		"jivosite.com": 2,
		"jivox.com": 4,
		"jobs2careers.com": 4,
		"joinhoney.com": 8,
		"create.leadid.com": 6,
		"d1tprjo2w7krrh.cloudfront.net": 6,
		"cdnjquery.com": 9,
		"jquery.com": 9,
		"cjmooter.xcache.kinxcdn.com": 4,
		"jsdelivr.net": 9,
		"jsecoin.com": 4,
		"jsuol.com.br": 4,
		"contentabc.com": 3,
		"mofos.com": 3,
		"juiceadv.com": 4,
		"juicyads.com": 3,
		"cdn.jumplead.com": 6,
		"jumpstarttaggingsolutions.com": 6,
		"jumptap.com": 4,
		"jump-time.net": 6,
		"jumptime.com": 6,
		"components.justanswer.com": 2,
		"justpremium.com": 4,
		"justpremium.nl": 4,
		"justrelevant.com": 4,
		"jvc.gg": 9,
		"d21rhj7n383afu.cloudfront.net": 0,
		"jwpcdn.com": 0,
		"jwplatform.com": 0,
		"jwplayer.com": 0,
		"jwpltx.com": 0,
		"jwpsrv.com": 0,
		"ltassrv.com": 4,
		"kaeufersiegel.de": 2,
		"kairion.de": 4,
		"kctag.net": 4,
		"kaloo.ga": 4,
		"kaltura.com": 0,
		"kameleoon.com": 6,
		"kameleoon.eu": 6,
		"kampyle.com": 2,
		"kanoodle.com": 4,
		"kmi-us.com": 4,
		"tnsinternet.be": 4,
		"karambasecurity.com": 8,
		"kargo.com": 4,
		"kaspersky-labs.com": 12,
		"kataweb.it": 4,
		"cen.katchup.fr": 4,
		"kau.li": 4,
		"kavanga.ru": 4,
		"kayosports.com.au": 0,
		"dc8na2hxrj29i.cloudfront.net": 6,
		"keen.io": 6,
		"widget.kelkoo.com": 4,
		"xg4ken.com": 6,
		"keymetric.net": 6,
		"lb.keytiles.com": 6,
		"keywee.co": 6,
		"keywordmax.com": 4,
		"massrelevance.com": 7,
		"tweetriver.com": 7,
		"khzbeucrltin.com": 11,
		"ping.kickfactory.com": 4,
		"sa-as.com": 4,
		"sniff.visistat.com": 4,
		"stats.visistat.com": 4,
		"apikik.com": 7,
		"kik-gateway-use1.meetme.com": 7,
		"kik-live.com": 7,
		"kik-stream.meetme.com": 7,
		"kik.com": 7,
		"king.com": 4,
		"midasplayer.com": 8,
		"kinja-img.com": 6,
		"kinja-static.com": 6,
		"kinja.com": 6,
		"kiosked.com": 4,
		"doug1izaerwt3.cloudfront.net": 6,
		"kissmetrics.com": 6,
		"ad.103092804.com": 4,
		"kmdisplay.com": 4,
		"kixer.com": 4,
		"klarna.com": 2,
		"a.klaviyo.com": 6,
		"klaviyo.com": 6,
		"klikki.com": 4,
		"scr.kliksaya.com": 4,
		"mediapeo2.com": 4,
		"knoopstat.nl": 6,
		"knotch.it": 2,
		"komoona.com": 4,
		"kona.kontera.com": 4,
		"ktxtr.com": 4,
		"kontextua.com": 4,
		"cleanrm.net": 4,
		"korrelate.net": 4,
		"trackit.ktxlytics.io": 6,
		"kaptcha.com": 6,
		"krxd.net": 4,
		"d31bfnnwekbny6.cloudfront.net": 4,
		"kpcustomer.de": 4,
		"q-sis.de": 4,
		"kxcdn.com": 9,
		"cdn.kyto.com": 6,
		"cd-ladsp-com.s3.amazonaws.com": 4,
		"ladmp.com": 4,
		"ladsp.com": 4,
		"lanistaads.com": 4,
		"latimes.com": 8,
		"events.launchdarkly.com": 5,
		"launchdarkly.com": 5,
		"launchbit.com": 4,
		"launchpad.net": 8,
		"launchpadcontent.net": 8,
		"layer-ad.org": 4,
		"ph-live.slatic.net": 4,
		"slatic.net": 4,
		"lcxdigital.com": 4,
		"lemde.fr": 8,
		"t1.llanalytics.com": 6,
		"leadback.ru": 6,
		"leaddyno.com": 4,
		"123-tracker.com": 4,
		"55-trk-srv.com": 4,
		"business-path-55.com": 4,
		"click-to-trace.com": 4,
		"cloud-exploration.com": 4,
		"cloud-journey.com": 4,
		"cloud-trail.com": 4,
		"cloudpath82.com": 4,
		"cloudtracer101.com": 4,
		"discover-path.com": 4,
		"discovertrail.net": 4,
		"domainanalytics.net": 4,
		"dthvdr9.com": 4,
		"explore-123.com": 4,
		"finger-info.net": 4,
		"forensics1000.com": 4,
		"ip-route.net": 4,
		"ipadd-path.com": 4,
		"iproute66.com": 4,
		"lead-123.com": 4,
		"lead-analytics-1000.com": 4,
		"lead-watcher.com": 4,
		"leadforensics.com": 4,
		"ledradn.com": 4,
		"letterbox-path.com": 4,
		"letterboxtrail.com": 4,
		"network-handle.com": 4,
		"path-follower.com": 4,
		"path-trail.com": 4,
		"scan-trail.com": 4,
		"site-research.net": 4,
		"srv1010elan.com": 4,
		"the-lead-tracker.com": 4,
		"trace-2000.com": 4,
		"track-web.net": 4,
		"trackdiscovery.net": 4,
		"trackercloud.net": 4,
		"trackinvestigate.net": 4,
		"trail-viewer.com": 4,
		"trail-web.com": 4,
		"trailbox.net": 4,
		"trailinvestigator.com": 4,
		"web-path.com": 4,
		"webforensics.co.uk": 4,
		"websiteexploration.com": 4,
		"www-path.com": 4,
		"gate.leadgenic.com": 4,
		"leadhit.ru": 2,
		"js.leadin.com": 6,
		"io.leadingreports.de": 4,
		"js.leadinspector.de": 6,
		"formalyzer.com": 6,
		"trackalyzer.com": 6,
		"analytics.leadlifesolutions.net": 2,
		"my.leadpages.net": 6,
		"leadplace.fr": 6,
		"scorecard.wspisp.net": 4,
		"www.leadscoreapp.dk": 2,
		"tracker.leadsius.com": 4,
		"leady.com": 4,
		"leady.cz": 4,
		"leiki.com": 4,
		"lengow.com": 4,
		"lenmit.com": 11,
		"lentainform.com": 8,
		"lenua.de": 4,
		"letreach.com": 2,
		"lencr.org": 5,
		"letsencrypt.org": 5,
		"js.letvcdn.com": 6,
		"footprint.net": 8,
		"alphonso.tv": 4,
		"lgads.tv": 4,
		"lg.com": 8,
		"lge.com": 8,
		"lgsmartad.com": 8,
		"lgtvcommon.com": 8,
		"lgtvsdp.com": 8,
		"licensebuttons.net": 9,
		"lfstmedia.com": 4,
		"content-recommendation.net": 4,
		"ligadx.com": 4,
		"ligatus.com": 4,
		"ligatus.de": 4,
		"veeseo.com": 4,
		"limk.com": 4,
		"line-apps.com": 6,
		"line-scdn.net": 6,
		"line.me": 6,
		"tongji.linezing.com": 4,
		"linkbucks.com": 4,
		"linkconnector.com": 4,
		"bizo.com": 8,
		"licdn.com": 8,
		"linkedin.com": 8,
		"lynda.com": 8,
		"ads.linkedin.com": 4,
		"snap.licdn.com": 6,
		"bizographics.com": 4,
		"platform.linkedin.com": 7,
		"linker.hr": 4,
		"linkprice.com": 4,
		"lp4.io": 6,
		"linksalpha.com": 7,
		"erovinmo.com": 4,
		"linksmart.com": 4,
		"linkstorm.net": 2,
		"linksynergy.com": 4,
		"linkup.com": 6,
		"linkwi.se": 4,
		"linkwithin.com": 7,
		"lqm.io": 4,
		"lqmcdn.com": 4,
		"liqwid.net": 4,
		"list.ru": 7,
		"listrakbi.com": 2,
		"live2support.com": 2,
		"live800.com": 2,
		"ladesk.com": 2,
		"livehelpnow.net": 2,
		"liadm.com": 6,
		"l-stat.livejournal.net": 6,
		"liveadexchanger.com": 11,
		"livechat.s3.amazonaws.com": 2,
		"livechatinc.com": 2,
		"livechatinc.net": 2,
		"livechatnow.com": 2,
		"livechatnow.net": 2,
		"liveclicker.net": 2,
		"livecounter.dk": 6,
		"fyre.co": 1,
		"livefyre.com": 1,
		"yadro.ru": 1,
		"liveperson.net": 2,
		"lpsnmedia.net": 2,
		"pippio.com": 4,
		"rapleaf.com": 4,
		"rlcdn.com": 4,
		"livere.co.kr": 7,
		"livere.co.kr.cizion.ixcloud.net": 7,
		"livesportmedia.eu": 8,
		"analytics.livestream.com": 0,
		"livetex.ru": 2,
		"lkqd.net": 4,
		"loadbee.com": 4,
		"loadercdn.com": 11,
		"loadsource.org": 11,
		"web.localytics.com": 101,
		"localytics.com": 101,
		"cdn2.lockerdome.com": 7,
		"addtoany.com": 7,
		"pixel.loganmedia.mobi": 6,
		"ping.answerbook.com": 4,
		"loggly.com": 6,
		"logly.co.jp": 6,
		"logsss.com": 11,
		"lomadee.com": 4,
		"assets.loomia.com": 4,
		"loop11.com": 6,
		"lfov.net": 4,
		"crwdcntrl.net": 4,
		"vidcpm.com": 11,
		"tracker.samplicio.us": 4,
		"lucidmedia.com": 4,
		"lead.adsender.us": 4,
		"livestatserver.com": 6,
		"luckyorange.com": 6,
		"luckyorange.net": 6,
		"luckypushh.com": 11,
		"adelixir.com": 4,
		"lypn.com": 4,
		"lypn.net": 4,
		"lytics.io": 6,
		"lyuoaxruaqdo.com": 11,
		"m-pathy.com": 4,
		"mpnrs.com": 4,
		"m4n.nl": 4,
		"madadsmedia.com": 4,
		"madeleine.de": 4,
		"dinclinx.com": 4,
		"madisonlogic.com": 4,
		"madnet.ru": 4,
		"eu2.madsone.com": 4,
		"magna.ru": 4,
		"d3ezl4ajpp2zy8.cloudfront.net": 4,
		"domdex.com": 4,
		"domdex.net": 4,
		"magnetisemedia.com": 4,
		"magnify360.com": 6,
		"magnuum.com": 11,
		"ad.mail.ru": 4,
		"imgsmail.ru": 7,
		"mail.ru": 7,
		"mradx.net": 7,
		"odnoklassniki.ru": 7,
		"ok.ru": 7,
		"chimpstatic.com": 4,
		"list-manage.com": 4,
		"mailchimp.com": 4,
		"mailerlite.com": 10,
		"mailtrack.io": 4,
		"mainadv.com": 4,
		"makazi.com": 4,
		"makeappdev.xyz": 12,
		"makesource.cool": 11,
		"widgets.mango-office.ru": 4,
		"manycontacts.com": 4,
		"mapandroute.de": 2,
		"mapbox.com": 2,
		"www.maploco.com": 4,
		"px.marchex.io": 4,
		"voicestar.com": 4,
		"mmadsgadget.com": 4,
		"qadabra.com": 4,
		"qadserve.com": 4,
		"qadservice.com": 4,
		"marinsm.com": 4,
		"markandmini.com": 4,
		"ak-cdn.placelocal.com": 4,
		"dt00.net": 4,
		"dt07.net": 4,
		"marketgid.com": 4,
		"mgid.com": 4,
		"marketingautomation.si": 4,
		"marketo.com": 4,
		"marketo.net": 4,
		"mktoresp.com": 4,
		"caanalytics.com": 4,
		"mmstat.com": 4,
		"markmonitor.com": 4,
		"netscope.data.marktest.pt": 4,
		"marshadow.io": 4,
		"martiniadnetwork.com": 4,
		"edigitalsurvey.com": 2,
		"marvellousmachine.net": 6,
		"mbn.com.ua": 4,
		"mastertarget.ru": 4,
		"rns.matelso.de": 6,
		"matheranalytics.com": 6,
		"mathjax.org": 9,
		"nzaza.com": 6,
		"matomo.cloud": 6,
		"matomo.org": 6,
		"piwik.org": 6,
		"adsmarket.com": 4,
		"m2pub.com": 4,
		"matrix.org": 5,
		"mb01.com": 5,
		"maxcdn.com": 9,
		"netdna-cdn.com": 9,
		"netdna-ssl.com": 9,
		"maxlab.ru": 4,
		"maxmind.com": 4,
		"maxonclick.com": 11,
		"mxptint.net": 4,
		"maxymiser.hs.llnwd.net": 4,
		"maxymiser.net": 4,
		"m6r.eu": 4,
		"pixel.adbuyer.com": 4,
		"mcabi.mcloudglobal.com": 4,
		"scanalert.com": 5,
		"ywxi.net": 5,
		"mconet.biz": 4,
		"mdotlabs.com": 4,
		"media-clic.com": 4,
		"media-imdb.com": 9,
		"media.net": 4,
		"mediaimpact.de": 4,
		"mookie1.com": 4,
		"idntfy.ru": 4,
		"s1.mediaad.org": 4,
		"mlnadvertising.com": 4,
		"fhserve.com": 4,
		"media-lab.ai": 8,
		"medialab.la": 8,
		"adnet.ru": 4,
		"medialand.ru": 4,
		"medialead.de": 4,
		"mathads.com": 4,
		"mathtag.com": 4,
		"mediametrics.ru": 7,
		"audit.median.hu": 4,
		"mediapass.com": 4,
		"mt.mediapostcommunication.net": 6,
		"mediarithmics.com": 4,
		"tns-counter.ru": 6,
		"ad.media-servers.net": 4,
		"adsvc1107131.net": 4,
		"mediator.media": 6,
		"mediav.com": 4,
		"adnetinteractive.com": 4,
		"adnetinteractive.net": 4,
		"mediego.com": 4,
		"medleyads.com": 4,
		"adnet.com.tr": 4,
		"e-kolay.net": 4,
		"medyanetads.com": 4,
		"cim.meebo.com": 7,
		"meetrics.net": 4,
		"mxcdn.net": 4,
		"research.de.com": 4,
		"counter.megaindex.ru": 4,
		"mega.co.nz": 8,
		"mega.io": 8,
		"mega.nz": 8,
		"mein-bmi.com": 12,
		"webvisitor.melissadata.net": 6,
		"meltdsp.com": 4,
		"mlt01.com": 4,
		"mentad.com": 4,
		"mercadoclics.com": 4,
		"mercadolivre.com.br": 4,
		"mlstatic.com": 4,
		"merchantadvantage.com": 4,
		"merchenta.com": 4,
		"roia.biz": 4,
		"cdn.merklesearch.com": 6,
		"rkdms.com": 6,
		"messenger.com": 7,
		"ad.metanetwork.com": 7,
		"metaffiliation.com": 4,
		"netaffiliation.com": 4,
		"metalyzer.com": 4,
		"mlsat02.de": 4,
		"metrigo.com": 4,
		"metriweb.be": 4,
		"miaozhen.com": 4,
		"microad.co.jp": 4,
		"microad.jp": 4,
		"microad.net": 4,
		"microadinc.com": 4,
		"azurewebsites.net": 8,
		"cloudapp.net": 8,
		"gfx.ms": 8,
		"microsoft.com": 8,
		"microsoftonline-p.com": 8,
		"microsoftonline.com": 8,
		"microsofttranslator.com": 8,
		"msecnd.net": 8,
		"msedge.net": 8,
		"msocdn.com": 8,
		"onestore.ms": 8,
		"s-microsoft.com": 8,
		"trouter.io": 8,
		"windows.net": 8,
		"aka.ms": 8,
		"microsoftazuread-sso.com": 8,
		"bingapis.com": 8,
		"msauth.net": 8,
		"msauthimages.net": 8,
		"msftauth.net": 8,
		"msftstatic.com": 8,
		"msidentity.com": 8,
		"nelreports.net": 8,
		"windowscentral.com": 8,
		"analytics.live.com": 4,
		"a.clarity.ms": 6,
		"b.clarity.ms": 6,
		"c.clarity.ms": 6,
		"d.clarity.ms": 6,
		"e.clarity.ms": 6,
		"f.clarity.ms": 6,
		"g.clarity.ms": 6,
		"h.clarity.ms": 6,
		"i.clarity.ms": 6,
		"j.clarity.ms": 6,
		"log.clarity.ms": 6,
		"www.clarity.ms": 6,
		"mmismm.com": 4,
		"imgfarm.com": 6,
		"mindspark.com": 6,
		"staticimgfarm.com": 6,
		"mvtracker.com": 4,
		"minewhat.com": 4,
		"mintsapp.io": 2,
		"snackly.co": 0,
		"snippet.minute.ly": 0,
		"apv.configuration.minute.ly": 0,
		"get.mirando.de": 4,
		"mirtesen.ru": 7,
		"misterbell.com": 4,
		"mixi.jp": 7,
		"mixpanel.com": 6,
		"mxpnl.com": 6,
		"mxpnl.net": 6,
		"swf.mixpo.com": 4,
		"app.mluvii.com": 2,
		"mncdn.com": 9,
		"moatads.com": 4,
		"moatpixel.com": 4,
		"mobicow.com": 4,
		"a.mobify.com": 4,
		"mobtrks.com": 11,
		"ads.mocean.mobi": 4,
		"ads.moceanads.com": 4,
		"chat.mochapp.com": 2,
		"intelligentpixel.modernimpact.com": 4,
		"teljari.is": 6,
		"modulepush.com": 4,
		"mogointeractive.com": 4,
		"mokonocdn.com": 4,
		"devappgrant.space": 8,
		"monetate.net": 6,
		"monetize-me.com": 4,
		"ads.themoneytizer.com": 4,
		"mongoosemetrics.com": 4,
		"track.monitis.com": 6,
		"monitus.net": 6,
		"fonts.net": 9,
		"fonts.com": 2,
		"cdn.monsido.com": 6,
		"monster.com": 4,
		"mooxar.com": 4,
		"mopinion.com": 2,
		"mopub.com": 4,
		"ad.ad-arata.com": 4,
		"moras.jp": 4,
		"nedstatbasic.net": 7,
		"webstats.motigo.com": 7,
		"analytics.convertlanguage.com": 6,
		"mouseflow.com": 6,
		"mousestats.com": 4,
		"s.mousetrace.com": 6,
		"movad.de": 8,
		"movad.net": 8,
		"micpn.com": 2,
		"mvb.me": 4,
		"moz.com": 8,
		"firefox.com": 8,
		"mozaws.net": 8,
		"mozgcp.net": 8,
		"mozilla.com": 8,
		"mozilla.net": 8,
		"mozilla.org": 8,
		"storage.mozoo.com": 4,
		"tracker.mrpfd.com": 4,
		"mrpdata.com": 6,
		"mrpdata.net": 6,
		"mrskincash.com": 3,
		"a-msedge.net": 8,
		"b-msedge.net": 8,
		"e-msedge.net": 8,
		"k-msedge.net": 8,
		"l-msedge.net": 8,
		"s-msedge.net": 8,
		"spo-msedge.net": 8,
		"t-msedge.net": 8,
		"wac-msedge.net": 8,
		"msn.com": 8,
		"s-msn.com": 8,
		"musculahq.appspot.com": 4,
		"litix.io": 0,
		"mybloglog.com": 7,
		"t.p.mybuys.com": 4,
		"mycdn.me": 9,
		"mycliplister.com": 2,
		"mycounter.com.ua": 6,
		"mycounter.ua": 6,
		"myfonts.net": 6,
		"mypagerank.net": 6,
		"stat.mystat.hu": 7,
		"mythings.com": 4,
		"mystat-in.net": 7,
		"nab.com": 8,
		"nab.com.au": 8,
		"nab.net": 8,
		"nabgroup.com": 8,
		"national.com.au": 8,
		"nationalaustraliabank.com.au": 8,
		"nationalbank.com.au": 8,
		"nakanohito.jp": 4,
		"namogoo.coom": 4,
		"nanigans.com": 4,
		"audiencemanager.de": 4,
		"nanorep.com": 2,
		"narando.com": 0,
		"static.bam-x.com": 4,
		"narrative.io": 6,
		"p1.ntvk1.ru": 4,
		"nativeads.com": 4,
		"cdn01.nativeroll.tv": 0,
		"ntv.io": 4,
		"postrelease.com": 4,
		"navdmp.com": 6,
		"naver.com": 4,
		"naver.net": 4,
		"s-nbcnews.com": 8,
		"richmedia247.com": 4,
		"needle.com": 2,
		"nekudo.com": 2,
		"neodatagroup.com": 4,
		"ad-srv.net": 4,
		"contentspread.net": 4,
		"neory-tm.com": 4,
		"simptrack.com": 4,
		"nerfherdersolo.com": 8,
		"wemfbox.ch": 6,
		"cdnma.com": 4,
		"nr7.us": 4,
		"netavenir.com": 4,
		"netcommunities.com": 4,
		"visibility-stats.com": 4,
		"netbiscuits.net": 6,
		"bbtrack.net": 4,
		"netbooster.com": 4,
		"netflix.com": 0,
		"nflxext.com": 0,
		"nflximg.net": 0,
		"nflxso.net": 0,
		"nflxvideo.net": 0,
		"flxvpn.net": 0,
		"netflix.ca": 0,
		"netflix.com.au": 0,
		"netflix.net": 0,
		"netflixdnstest1.com": 0,
		"netflixdnstest10.com": 0,
		"netflixdnstest2.com": 0,
		"netflixdnstest3.com": 0,
		"netflixdnstest4.com": 0,
		"netflixdnstest5.com": 0,
		"netflixdnstest6.com": 0,
		"netflixdnstest7.com": 0,
		"netflixdnstest8.com": 0,
		"netflixdnstest9.com": 0,
		"netflixinvestor.com": 0,
		"netflixstudios.com": 0,
		"netflixtechblog.com": 0,
		"nflximg.com": 0,
		"netify.ai": 8,
		"netzathleten-media.de": 4,
		"netminers.dk": 6,
		"netmining.com": 4,
		"netmng.com": 4,
		"stat.netmonitor.fi": 6,
		"glanceguide.com": 4,
		"imrworldwide.com": 4,
		"vizu.com": 4,
		"netrk.net": 6,
		"netseer.com": 4,
		"netshelter.net": 4,
		"nsaudience.pl": 6,
		"nwidget.networkedblogs.com": 7,
		"adadvisor.net": 4,
		"d1ros97qkrwjf5.cloudfront.net": 6,
		"newrelic.com": 6,
		"nr-data.net": 6,
		"codestream.com": 6,
		"newscgp.com": 4,
		"nmcdn.us": 4,
		"newstogram.com": 4,
		"newsupdatedir.info": 11,
		"newsupdatewe.info": 12,
		"ads.newtention.net": 4,
		"ads.newtentionassets.net": 4,
		"nexage.com": 4,
		"nexeps.com": 4,
		"nxtck.com": 4,
		"track.nextuser.com": 4,
		"imgsrv.nextag.com": 4,
		"nextclick.pl": 4,
		"nextstat.com": 6,
		"d1d8vn0fpluuz7.cloudfront.net": 6,
		"ads.ngageinc.com": 6,
		"nice264.com": 0,
		"nimblecommerce.com": 4,
		"nineanalytics.io": 4,
		"cho-chin.com": 6,
		"donburako.com": 6,
		"hishaku.com": 6,
		"shinobi.jp": 6,
		"static.nirror.com": 6,
		"nitropay.com": 4,
		"nk.pl": 4,
		"noaa.gov": 8,
		"track.noddus.com": 4,
		"contextbar.ru": 4,
		"nonli.com": 4,
		"non.li": 4,
		"trkme.net": 4,
		"noop.style": 11,
		"nosto.com": 6,
		"adleadevent.com": 4,
		"notifyfox.com": 6,
		"notion.so": 8,
		"nowinteract.com": 6,
		"npario-inc.net": 6,
		"nplexmedia.com": 4,
		"nrelate.com": 2,
		"ns8.com": 4,
		"nt.vc": 8,
		"featurelink.com": 4,
		"ntp.org": 5,
		"ntppool.org": 5,
		"tracer.jp": 6,
		"nuffnang.com": 4,
		"nuggad.net": 4,
		"rotator.adjuggler.com": 4,
		"numbers.md": 6,
		"channeliq.com": 5,
		"nyacampwk.com": 11,
		"nyetm2mkch.com": 11,
		"nyt.com": 8,
		"nytimes.com": 8,
		"o12zs3u2n.com": 11,
		"o2.pl": 8,
		"o2online.de": 8,
		"oath.com": 8,
		"observerapp.com": 4,
		"ocioso.com.br": 7,
		"oclasrv.com": 11,
		"octapi.net": 11,
		"service.octavius.rocks": 4,
		"office.com": 8,
		"office.net": 8,
		"office365.com": 8,
		"oghub.io": 11,
		"ohmystats.com": 6,
		"adohana.com": 4,
		"photorank.me": 4,
		"olark.com": 2,
		"olx-st.com": 8,
		"onap.io": 8,
		"omarsys.com": 4,
		"ometria.com": 4,
		"omgpm.com": 7,
		"omniconvert.com": 4,
		"omnidsp.com": 4,
		"oms.eu": 4,
		"omsnative.de": 4,
		"onaudience.com": 4,
		"btc-echode.api.oneall.com": 7,
		"tracking.onefeed.co.uk": 6,
		"onesignal.com": 5,
		"os.tc": 5,
		"stat.onestat.com": 6,
		"ocdn.eu": 8,
		"onet.pl": 8,
		"onetag.com": 4,
		"s-onetag.com": 4,
		"onetrust.com": 5,
		"fogl1onf.com": 4,
		"onfocus.io": 4,
		"onlinewebstat.com": 6,
		"onlinewebstats.com": 6,
		"onswipe.com": 4,
		"onthe.io": 6,
		"moon-ray.com": 4,
		"moonraymarketing.com": 4,
		"ooyala.com": 0,
		"openadex.dk": 4,
		"247realmedia.com": 4,
		"oaserve.com": 4,
		"realmedia.com": 4,
		"realmediadigital.com": 4,
		"opensharecount.com": 4,
		"chatgpt.com": 8,
		"oaistatic.com": 8,
		"oaiusercontent.com": 8,
		"openai.com": 8,
		"oloadcdn.net": 9,
		"openload.co": 9,
		"openstat.net": 6,
		"spylog.com": 6,
		"spylog.ru": 6,
		"opentracker.net": 6,
		"openwebanalytics.com": 6,
		"odnxs.net": 4,
		"openx.net": 4,
		"openx.org": 4,
		"openxenterprise.com": 4,
		"servedbyopenx.com": 4,
		"adsummos.net": 4,
		"opinary.com": 2,
		"opinionbar.com": 2,
		"emagazines.com": 6,
		"allawnos.com": 101,
		"allawntech.com": 101,
		"heytapdl.com": 101,
		"heytapmobi.com": 101,
		"heytapmobile.com": 101,
		"oppomobile.com": 101,
		"opta.net": 6,
		"optaim.com": 4,
		"cookielaw.org": 5,
		"service.optify.net": 4,
		"optimatic.com": 0,
		"optmd.com": 4,
		"optimicdn.com": 9,
		"optimizely.com": 6,
		"episerver.net": 6,
		"optimonk.com": 6,
		"mstrlytcs.com": 2,
		"optmnstr.com": 2,
		"optmstr.com": 2,
		"optnmstr.com": 2,
		"optincollect.com": 4,
		"volvelle.tech": 4,
		"ora.tv": 4,
		"oracleinfinity.io": 6,
		"instantservice.com": 2,
		"ts.istrack.com": 2,
		"rightnowtech.com": 8,
		"rnengage.com": 8,
		"orange.fr": 4,
		"orangeads.fr": 4,
		"ads.orange142.com": 4,
		"wanadoo.fr": 8,
		"otracking.com": 4,
		"emxdgt.com": 4,
		"static.ordergroove.com": 4,
		"orelsite.ru": 2,
		"otclick-adv.ru": 4,
		"othersearch.info": 8,
		"otm-r.com": 4,
		"otto.de": 8,
		"ottogroup.media": 8,
		"outbrain.com": 4,
		"outbrainimg.com": 4,
		"live.com": 13,
		"cloud.microsoft": 13,
		"hotmail.com": 13,
		"outlook.com": 13,
		"svc.ms": 13,
		"overheat.it": 6,
		"oewabox.at": 6,
		"owneriq.net": 4,
		"ownpage.fr": 2,
		"owox.com": 6,
		"adconnexa.com": 2,
		"adsbwm.com": 2,
		"oxomi.com": 4,
		"oztam.com.au": 8,
		"pageanalytics.space": 11,
		"blockmetrics.com": 2,
		"pagefair.com": 2,
		"pagefair.net": 2,
		"ghmedia.com": 4,
		"777seo.com": 4,
		"paid-to-promote.net": 4,
		"ptp22.com": 4,
		"ptp33.com": 4,
		"paperg.com": 4,
		"pardot.com": 6,
		"d1z2jf7jlzjs58.cloudfront.net": 6,
		"parsely.com": 6,
		"partner-ads.com": 4,
		"passionfruitads.com": 4,
		"pathful.com": 6,
		"pay-hit.com": 4,
		"payclick.it": 4,
		"app.paykickstart.com": 6,
		"paypal.com": 2,
		"paypalobjects.com": 2,
		"pcvark.com": 11,
		"peer39.com": 4,
		"peer39.net": 4,
		"peer5.com": 9,
		"peerius.com": 2,
		"pendo.io": 6,
		"pepper.com": 4,
		"gopjn.com": 4,
		"pjatr.com": 4,
		"pjtra.com": 4,
		"pntra.com": 4,
		"pntrac.com": 4,
		"pntrs.com": 4,
		"player.pepsia.com": 6,
		"perfdrive.com": 11,
		"perfectaudience.com": 4,
		"prfct.co": 4,
		"perfectmarket.com": 4,
		"perfops.io": 6,
		"performgroup.com": 5,
		"analytics.performable.com": 6,
		"performancing.com": 6,
		"performax.cz": 4,
		"perimeterx.net": 6,
		"permutive.com": 4,
		"persgroep.net": 4,
		"persianstat.com": 6,
		"code.pers.io": 4,
		"counter.personyze.com": 2,
		"petametrics.com": 2,
		"ads.pheedo.com": 4,
		"app.phonalytics.com": 2,
		"d2bgg7rjywcwsy.cloudfront.net": 4,
		"piguiqproxy.com": 11,
		"trgt.eu": 6,
		"pingdom.net": 6,
		"pinimg.com": 7,
		"pinterest.com": 7,
		"app.pipz.io": 4,
		"disabled.invalid": 6,
		"piwik.pro": 6,
		"adrta.com": 4,
		"app.pixelpop.co": 4,
		"pixfuture.net": 4,
		"vast1.pixfuture.com": 4,
		"piximedia.com": 4,
		"pizzaandads.com": 11,
		"ads.placester.net": 4,
		"d3uemyw1e5n0jw.cloudfront.net": 4,
		"pladform.com": 4,
		"tag.bi.serviceplan.com": 6,
		"pfrm.co": 4,
		"impact-ad.jp": 4,
		"loveadvert.ru": 4,
		"playbuzz.com": 2,
		"pof.com": 6,
		"plex.bz": 0,
		"plex.direct": 0,
		"plex.tv": 0,
		"analytics.plex.tv": 6,
		"metrics.plex.tv": 6,
		"plista.com": 4,
		"plugrush.com": 4,
		"pluso.ru": 7,
		"plutusads.com": 4,
		"pmddby.com": 12,
		"pnamic.com": 12,
		"po.st": 7,
		"widgets.getpocket.com": 6,
		"pocketcents.com": 4,
		"pointificsecure.com": 6,
		"pointroll.com": 4,
		"poirreleast.club": 11,
		"mediavoice.com": 4,
		"polar.me": 4,
		"polarmobile.com": 4,
		"polldaddy.com": 2,
		"polyad.net": 4,
		"polyfill.io": 8,
		"popads.net": 4,
		"popadscdn.net": 4,
		"popcash.net": 4,
		"popcashjs.b-cdn.net": 4,
		"desv383oqqc0.cloudfront.net": 6,
		"popin.cc": 7,
		"cdn.popmyads.com": 4,
		"poponclick.com": 4,
		"populis.com": 4,
		"populisengage.com": 4,
		"phncdn.com": 3,
		"pornhub.com": 3,
		"prscripts.com": 3,
		"prstatics.com": 3,
		"prwidgets.com": 3,
		"barra.brasil.gov.br": 4,
		"postaffiliatepro.com": 4,
		"powerlinks.com": 4,
		"powerreviews.com": 2,
		"powr.io": 6,
		"api.pozvonim.com": 4,
		"prebid.org": 4,
		"precisionclick.com": 4,
		"adserver.com.br": 4,
		"predicta.net": 4,
		"prnx.net": 4,
		"ppjol.com": 4,
		"ppjol.net": 4,
		"api.pressly.com": 4,
		"pricegrabber.com": 4,
		"cdn.pricespider.com": 4,
		"pmdrecrute.com": 4,
		"prismamediadigital.com": 4,
		"privy.com": 2,
		"pswec.com": 4,
		"prodperfect.com": 6,
		"lib.productsup.io": 4,
		"proadsnet.com": 6,
		"profitshare.ro": 6,
		"tracking.proformics.com": 6,
		"programattik.com": 4,
		"projectwonderful.com": 4,
		"propelmarketing.com": 4,
		"oclaserver.com": 4,
		"onclasrv.com": 4,
		"onclickads.net": 4,
		"onclkds.com": 4,
		"propellerads.com": 4,
		"propellerpops.com": 4,
		"proper.io": 4,
		"st-a.props.id": 4,
		"propvideo.net": 11,
		"tr.prospecteye.com": 4,
		"prosperent.com": 4,
		"prostor-lite.ru": 4,
		"providesupport.com": 2,
		"proximic.com": 4,
		"proxistore.com": 4,
		"pscp.tv": 7,
		"pstatic.net": 9,
		"psyma.com": 4,
		"ptengine.jp": 6,
		"pub-fit.com": 4,
		"pub.network": 4,
		"learnpipe.com": 2,
		"pubble.co": 2,
		"pubdirecte.com": 4,
		"pubgears.com": 4,
		"publicidees.com": 4,
		"publicidad.net": 4,
		"intgr.net": 4,
		"pubmatic.com": 4,
		"pubnub.com": 8,
		"puboclic.com": 4,
		"pulpix.com": 4,
		"tentaculos.net": 4,
		"pulse360.com": 4,
		"pulseinsights.com": 6,
		"contextweb.com": 4,
		"pulsepoint.com": 4,
		"punchtab.com": 4,
		"purch.com": 4,
		"servebom.com": 4,
		"purechat.com": 2,
		"cdn.pprl.io": 6,
		"oopt.fr": 4,
		"puserving.com": 11,
		"push.world": 2,
		"pushengage.com": 2,
		"pushame.com": 11,
		"zebra.pushbullet.com": 2,
		"pushcrew.com": 2,
		"pusher.com": 6,
		"pusherapp.com": 6,
		"pushnative.com": 11,
		"cdn.pushnews.eu": 4,
		"pushno.com": 11,
		"pushwhy.com": 11,
		"pushwoosh.com": 2,
		"pvclouds.com": 11,
		"ads.q1media.com": 4,
		"q1mediahydraplatform.com": 4,
		"q-divisioncdn.de": 4,
		"qbaka.net": 6,
		"track.qcri.org": 6,
		"collect.qeado.com": 6,
		"s.lianmeng.360.cn": 6,
		"qq.com": 2,
		"qrius.me": 7,
		"qualaroo.com": 6,
		"qualcomm.com": 8,
		"gpsonextra.net": 15,
		"izatcloud.net": 15,
		"xtracloud.net": 15,
		"bluecava.com": 4,
		"qualtrics.com": 6,
		"quantcast.com": 4,
		"quantserve.com": 4,
		"quantcount.com": 6,
		"quantummetric.com": 6,
		"quartic.pl": 6,
		"quarticon.com": 6,
		"d3c3cq33003psk.cloudfront.net": 6,
		"qubit.com": 6,
		"easyresearch.se": 2,
		"queue-it.net": 6,
		"quick-counter.net": 6,
		"adsonar.com": 4,
		"qnsr.com": 4,
		"quinstreet.com": 4,
		"thecounter.com": 4,
		"quintelligence.com": 6,
		"qservz.com": 4,
		"quisma.com": 4,
		"quora.com": 7,
		"ads-digitalkeys.com": 4,
		"rackcdn.com": 9,
		"radarurl.com": 6,
		"dsa.csdata1.com": 4,
		"gwallet.com": 4,
		"r1-cdn.net": 4,
		"widget.raisenow.com": 6,
		"mediaforge.com": 4,
		"rmtag.com": 4,
		"rakuten.co.jp": 4,
		"trafficgate.net": 4,
		"mtwidget04.affiliate.rakuten.co.jp": 4,
		"xml.affilliate.rakuten.co.jp": 4,
		"rambler.ru": 6,
		"top100.ru": 6,
		"rapidspike.com": 6,
		"ravelin.com": 6,
		"rawgit.com": 9,
		"raygun.io": 4,
		"count.rbc.ru": 6,
		"rcs.it": 4,
		"rcsmediagroup.it": 4,
		"d335luupugsy2.cloudfront.net": 6,
		"rea-group.com": 4,
		"reagroupdata.com.au": 4,
		"reastatic.net": 4,
		"d12ulf131zb0yj.cloudfront.net": 6,
		"reachforce.com": 6,
		"reachjunction.com": 4,
		"cdn.rlets.com": 4,
		"reachlocal.com": 4,
		"reachlocallivechat.com": 4,
		"rlcdn.net": 4,
		"plugin.reactful.com": 4,
		"reactivpub.fr": 6,
		"skinected.com": 4,
		"readrboard.com": 7,
		"readme.com": 6,
		"readme.io": 6,
		"readspeaker.com": 2,
		"realclick.co.kr": 4,
		"realestate.com.au": 4,
		"realperson.de": 2,
		"powermarketing.com": 2,
		"realtime.co": 2,
		"webspectator.com": 2,
		"dcniko1cv0rz.cloudfront.net": 6,
		"realytics.io": 6,
		"static.rbl.ms": 6,
		"recaptcha.net": 8,
		"recettes.net": 8,
		"static.recopick.com": 4,
		"recreativ.ru": 4,
		"analytics.recruitics.com": 6,
		"analytics.cohesionapps.com": 6,
		"cdn.cohesionapps.com": 6,
		"redblue.de": 6,
		"atendesoftware.pl": 9,
		"redd.it": 7,
		"reddit-image.s3.amazonaws.com": 7,
		"reddit.com": 7,
		"redditmedia.com": 7,
		"redditstatic.com": 7,
		"redhelper.ru": 2,
		"pixelinteractivemedia.com": 4,
		"triggit.com": 4,
		"grt01.com": 4,
		"grt02.com": 4,
		"redtram.com": 4,
		"rdtcdn.com": 9,
		"redtube.com": 9,
		"reduxmedia.com": 4,
		"reduxmediagroup.com": 4,
		"reedbusiness.net": 6,
		"reembed.com": 0,
		"reevoo.com": 4,
		"refericon.pl": 4,
		"ads.referlocal.com": 4,
		"refersion.com": 4,
		"refinedads.com": 4,
		"product.reflektion.com": 4,
		"reformal.ru": 2,
		"reinvigorate.net": 6,
		"convertglobal.com": 4,
		"convertglobal.s3.amazonaws.com": 4,
		"dnhgz729v27ca.cloudfront.net": 4,
		"reklamstore.com": 4,
		"ad.reklamport.com": 4,
		"delivery.reklamz.com": 4,
		"adimg.rekmob.com": 4,
		"relap.io": 4,
		"svtrd.com": 5,
		"synovite-scripts.com": 5,
		"tdn.r42tag.com": 5,
		"relestar.com": 6,
		"relevant4.com": 8,
		"remintrex.com": 4,
		"remove.video": 12,
		"rp-api.com": 4,
		"republer.com": 4,
		"resmeter.respublica.al": 6,
		"researchnow.com": 4,
		"reson8.com": 4,
		"respondhq.com": 4,
		"adinsight.com": 4,
		"adinsight.eu": 4,
		"responsetap.com": 4,
		"data.resultlinks.com": 4,
		"sli-system.com": 6,
		"retailrocket.net": 4,
		"retailrocket.ru": 4,
		"shopify.retargetapp.com": 4,
		"retargeter.com": 4,
		"retargeting.cl": 4,
		"d1stxfv94hrhia.cloudfront.net": 4,
		"waves.retentionscience.com": 4,
		"reutersmedia.net": 9,
		"revcontent.com": 4,
		"socialtwist.com": 4,
		"revenue.com": 4,
		"clkads.com": 4,
		"clkmon.com": 4,
		"clkrev.com": 4,
		"clksite.com": 4,
		"eclkspbn.com": 4,
		"imageshack.host": 4,
		"revenuemantra.com": 4,
		"revive-adserver.com": 4,
		"revolvermaps.com": 6,
		"cts.tradepub.com": 4,
		"revresponse.com": 4,
		"incontext.pl": 4,
		"pl-engine.intextad.net": 4,
		"addesktop.com": 4,
		"1rx.io": 4,
		"ria.ru": 8,
		"rmbn.ru": 4,
		"ics0.com": 2,
		"richrelevance.com": 2,
		"ringier.ch": 6,
		"meteorsolutions.com": 7,
		"riskified.com": 2,
		"rncdn3.com": 9,
		"ro2.biz": 4,
		"rbxcdn.com": 8,
		"getrockerbox.com": 6,
		"rocket.la": 4,
		"trk.sodoit.com": 4,
		"collector.roistat.com": 6,
		"rollad.ru": 4,
		"d37gvrvc0wt4s1.cloudfront.net": 6,
		"get.roost.me": 6,
		"getrooster.com": 6,
		"rqtrk.eu": 4,
		"rotaban.ru": 4,
		"routenplaner-karten.com": 2,
		"rovion.com": 4,
		"rsspump.com": 2,
		"creativecdn.com": 4,
		"rvty.net": 4,
		"rtbsuperhub.com": 4,
		"rtl.de": 8,
		"static-fra.de": 8,
		"technical-service.net": 8,
		"rtmark.net": 4,
		"dpclk.com": 4,
		"mobsmith.com": 4,
		"nearbyad.com": 4,
		"rubiconproject.com": 4,
		"tracker.ruhrgebiet-onlineservices.de": 4,
		"click.rummycircle.com": 4,
		"runadtag.com": 4,
		"rundsp.com": 4,
		"un-syndicate.com": 4,
		"cdn.secretrune.com": 6,
		"runmewivel.com": 10,
		"rhythmxchange.com": 0,
		"s24.com": 4,
		"s3xified.com": 11,
		"camp.sabavision.com": 4,
		"sageanalyst.net": 4,
		"sail-horizon.com": 4,
		"sail-personalize.com": 4,
		"sailthru.com": 4,
		"d16fk4ms6rqz1v.cloudfront.net": 4,
		"salecycle.com": 4,
		"api.salesfeed.com": 4,
		"salesmanago.com": 6,
		"salesmanago.pl": 6,
		"force.com": 4,
		"salesforce.com": 4,
		"liveagentforsalesforce.com": 2,
		"salesforceliveagent.com": 2,
		"msgapp.com": 4,
		"salespidermedia.com": 4,
		"salesviewer.com": 6,
		"samba.tv": 4,
		"game-mode.net": 8,
		"gos-gsp.io": 8,
		"lldns.net": 8,
		"pavv.co.kr": 8,
		"remotesamsung.com": 8,
		"samsung-gamelauncher.com": 8,
		"samsung.co.kr": 8,
		"samsung.com": 8,
		"samsung.com.cn": 8,
		"samsungcloud.com": 8,
		"samsungcloudcdn.com": 8,
		"samsungcloudprint.com": 8,
		"samsungcloudsolution.com": 8,
		"samsungcloudsolution.net": 8,
		"samsungelectronics.com": 8,
		"samsunghealth.com": 8,
		"samsungiotcloud.com": 8,
		"samsungknox.com": 8,
		"samsungnyc.com": 8,
		"samsungosp.com": 8,
		"samsungotn.net": 8,
		"samsungpositioning.com": 8,
		"samsungqbe.com": 8,
		"samsungrm.net": 8,
		"samsungrs.com": 8,
		"samsungsemi.com": 8,
		"samsungsetup.com": 8,
		"samsungusa.com": 8,
		"secb2b.com": 8,
		"smartthings.com": 8,
		"adgear.com": 4,
		"adgrx.com": 4,
		"samsungacr.com": 4,
		"samsungadhub.com": 4,
		"samsungads.com": 4,
		"samsungtifa.com": 4,
		"aibixby.com": 101,
		"findmymobile.samsung.com": 101,
		"samsapps.cust.lldns.net": 101,
		"samsung-omc.com": 101,
		"samsungapps.com": 101,
		"samsungdiroute.net": 101,
		"samsungdive.com": 101,
		"samsungdm.com": 101,
		"samsungdmroute.com": 101,
		"samsungmdec.com": 101,
		"samsungvisioncloud.com": 101,
		"sbixby.com": 101,
		"ospserver.net": 101,
		"samsungdms.net": 101,
		"samsungmax.com": 101,
		"samsungmobile.com": 101,
		"secmobilesvc.com": 101,
		"push.samsungosp.com": 8,
		"pushmessage.samsung.com": 8,
		"scs.samsungqbe.com": 8,
		"ssp.samsung.com": 8,
		"samsungsds.com": 10,
		"internetat.tv": 15,
		"samsungcloud.tv": 15,
		"tizenservice.com": 15,
		"ilsemedia.nl": 4,
		"sanoma.fi": 4,
		"d13im3ek7neeqp.cloudfront.net": 6,
		"d28ethi6slcjbm.cloudfront.net": 6,
		"d2uevgmgh16uk4.cloudfront.net": 6,
		"d3m83gvgzupli.cloudfront.net": 6,
		"saas.seewhy.com": 6,
		"leadforce1.com": 2,
		"vlog.leadformix.com": 2,
		"sap-xm.org": 4,
		"sape.ru": 6,
		"js.sl.pt": 4,
		"aimatch.com": 6,
		"sas.com": 6,
		"say.ac": 4,
		"ads.saymedia.com": 4,
		"srv.sayyac.net": 6,
		"scarabresearch.com": 4,
		"schibsted.com": 8,
		"schibsted.io": 8,
		"schneevonmorgen.com": 0,
		"svonm.com": 0,
		"rockabox.co": 4,
		"scorecardresearch.com": 6,
		"scoreresearch.com": 6,
		"scrsrch.com": 6,
		"securestudies.com": 6,
		"scout.scoutanalytics.net": 4,
		"scribblelive.com": 8,
		"scribol.com": 4,
		"analytics.snidigital.com": 6,
		"scroll.com": 5,
		"scupio.com": 4,
		"search123.uk.com": 4,
		"searchforce.net": 4,
		"searchignite.com": 4,
		"srtk.net": 4,
		"tacticalrepublic.com": 4,
		"sectigo.com": 5,
		"securedtouch.com": 6,
		"securedvisit.com": 4,
		"bacontent.de": 4,
		"nativendo.de": 4,
		"seedtag.com": 4,
		"svlu.net": 6,
		"d2dq2ahtl5zl1z.cloudfront.net": 6,
		"d47xnnr8b1rki.cloudfront.net": 6,
		"segment.com": 6,
		"segment.io": 6,
		"rutarget.ru": 4,
		"segmint.net": 6,
		"sekindo.com": 4,
		"sellpoint.net": 4,
		"sellpoints.com": 4,
		"semantiqo.com": 4,
		"semasio.net": 4,
		"semilo.com": 4,
		"semknox.com": 5,
		"sibautomation.com": 4,
		"sendpulse.com": 3,
		"sendsay.ru": 2,
		"track.sensedigital.in": 6,
		"static.sensorsdata.cn": 6,
		"sentifi.com": 6,
		"d3nslu0hdya83q.cloudfront.net": 6,
		"getsentry.com": 6,
		"ravenjs.com": 6,
		"sentry.io": 6,
		"sepyra.com": 4,
		"d2oh4tlt9mrke9.cloudfront.net": 6,
		"sessioncam.com": 6,
		"sessionly.io": 2,
		"71i.de": 4,
		"sexad.net": 3,
		"ads.sexinyourcity.com": 3,
		"sextracker.com": 3,
		"sexypartners.net": 3,
		"im.cz": 6,
		"imedia.cz": 6,
		"szn.cz": 6,
		"dtym7iokkjlif.cloudfront.net": 6,
		"shareaholic.com": 6,
		"shareasale.com": 4,
		"quintrics.nl": 2,
		"sharecompany.nl": 2,
		"sharepointonline.com": 8,
		"onmicrosoft.com": 8,
		"sharepoint.com": 8,
		"sharethis.com": 4,
		"shareth.ru": 4,
		"sharethrough.com": 4,
		"marketingautomation.services": 6,
		"sharpspring.com": 6,
		"sheego.de": 8,
		"services.sheerid.com": 4,
		"shinystat.com": 6,
		"shinystat.it": 6,
		"app.shoptarget.com.br": 4,
		"retargeter.com.br": 4,
		"shopauskunft.de": 2,
		"shopgate.com": 2,
		"shopify.com": 2,
		"shopifycdn.com": 2,
		"cdn.shopify.com": 2,
		"myshopify.com": 2,
		"shop.app": 2,
		"shopify.co.za": 2,
		"shopify.com.au": 2,
		"shopify.com.mx": 2,
		"shopify.dev": 2,
		"shopifyapps.com": 2,
		"shopifycdn.net": 2,
		"shopifynetwork.com": 2,
		"shopifypreview.com": 2,
		"shopifysvc.com": 6,
		"stats.shopify.com": 6,
		"v.shopify.com": 6,
		"shopifycloud.com": 2,
		"shopperapproved.com": 2,
		"shoppingshadow.com": 4,
		"tracking.shopping-flux.com": 6,
		"shoprunner.com": 2,
		"shopsocially.com": 2,
		"shopzilla.com": 4,
		"shortnews.de": 8,
		"showrss.info": 8,
		"shink.in": 2,
		"shutterstock.com": 8,
		"siblesectiveal.club": 11,
		"d3v27wwd40f0xu.cloudfront.net": 6,
		"getsidecar.com": 6,
		"dtlilztwypawv.cloudfront.net": 6,
		"siftscience.com": 6,
		"btstatic.com": 5,
		"signal.co": 5,
		"thebrighttag.com": 5,
		"cdn-scripts.signifyd.com": 6,
		"signifyd.com": 6,
		"gw-services.vtrenz.net": 2,
		"mkt51.net": 2,
		"mkt912.com": 2,
		"mkt922.com": 2,
		"mkt941.com": 2,
		"pages01.net": 2,
		"pages02.net": 2,
		"pages04.net": 2,
		"pages05.net": 2,
		"similardeals.net": 8,
		"similarweb.com": 6,
		"similarweb.io": 6,
		"d8rk54i4mohrb.cloudfront.net": 6,
		"simplereach.com": 6,
		"simpli.fi": 4,
		"sina.com.cn": 6,
		"sinaimg.cn": 9,
		"reporting.singlefeed.com": 4,
		"sddan.com": 6,
		"site24x7rum.com": 6,
		"site24x7rum.eu": 6,
		"sitebooster-fjfmworld-production.azureedge.net": 7,
		"a5.ogt.jp": 4,
		"siteapps.com": 2,
		"sitebro.com": 6,
		"sitebro.com.tw": 6,
		"sitebro.net": 6,
		"sitebro.tw": 6,
		"siteheart.com": 2,
		"siteimprove.com": 6,
		"siteimproveanalytics.com": 6,
		"sitelabweb.com": 11,
		"sitemeter.com": 6,
		"pixel.ad": 4,
		"sitescout.com": 4,
		"ad.sitemaji.com": 2,
		"sitetag.us": 2,
		"analytics.sitewit.com": 4,
		"ads.sixapart.com": 4,
		"sixt-neuwagen.de": 8,
		"skadtec.com": 6,
		"redirectingat.com": 4,
		"skimlinks.com": 4,
		"skimresources.com": 4,
		"analytics.skroutz.gr": 6,
		"skyglue.com": 6,
		"skype.com": 2,
		"skypeassets.com": 2,
		"skysa.com": 2,
		"skyscnr.com": 9,
		"slack-edge.com": 8,
		"slack-imgs.com": 8,
		"slack.com": 8,
		"slackb.com": 8,
		"slashdot.org": 2,
		"sleeknotestaticcontent.sleeknote.com": 2,
		"resultspage.com": 2,
		"builder.extensionfactory.com": 2,
		"freeskreen.com": 6,
		"slingpic.com": 4,
		"smaato.net": 4,
		"smart4ads.com": 4,
		"sascdn.com": 4,
		"smartadserver.com": 4,
		"styria-digital.com": 4,
		"yoc-adserver.com": 4,
		"smartcall.kz": 2,
		"getsmartcontent.com": 4,
		"smartdevicemedia.com": 4,
		"x.cnt.my": 4,
		"tracking.smartselling.cz": 2,
		"bepolite.eu": 4,
		"smartbn.ru": 4,
		"smartclick.net": 4,
		"smartclip.net": 4,
		"smartcontext.pl": 4,
		"d1n00d49gkbray.cloudfront.net": 4,
		"dhxtx5wtu812h.cloudfront.net": 4,
		"smartertravel.com": 4,
		"travelsmarter.net": 4,
		"smct.co": 4,
		"smartertrack.com": 4,
		"smartlink.cool": 11,
		"getsmartlook.com": 2,
		"smartlook.com": 2,
		"smartstream.tv": 4,
		"smartsuppchat.com": 2,
		"smi2.net": 6,
		"smi2.ru": 6,
		"stat.media": 6,
		"cdn.smooch.io": 2,
		"smowtion.com": 4,
		"smxindia.in": 6,
		"smyte.com": 6,
		"snacktv.de": 6,
		"snap.com": 2,
		"addlive.io": 2,
		"feelinsonice.com": 2,
		"sc-cdn.net": 2,
		"sc-corp.net": 2,
		"sc-gw.com": 2,
		"sc-jpl.com": 2,
		"sc-prod.net": 2,
		"snap-dev.net": 2,
		"snapads.com": 2,
		"snapkit.com": 2,
		"snapengage.com": 2,
		"sc-static.net": 4,
		"snapchat.com": 4,
		"snapcraft.io": 8,
		"snapcraftcontent.com": 8,
		"h-bid.com": 4,
		"eu2.snoobi.eu": 6,
		"snoobi.com": 6,
		"d346whrrklhco7.cloudfront.net": 6,
		"d78fikflryjgj.cloudfront.net": 6,
		"dc8xl0ndzn2cb.cloudfront.net": 6,
		"playwire.com": 6,
		"snplow.net": 6,
		"go-mpulse.net": 6,
		"mpstat.us": 6,
		"tiaa-cref.org": 6,
		"sociablelabs.com": 4,
		"socialamp.com": 4,
		"socialannex.com": 4,
		"soclminer.com.br": 7,
		"duu8lzqdm8tsz.cloudfront.net": 4,
		"ratevoice.com": 7,
		"sociaplus.com": 6,
		"sociomantic.com": 4,
		"images.sohu.com": 7,
		"sojern.com": 4,
		"sokrati.com": 4,
		"solads.media": 4,
		"solaredge.com": 8,
		"solidopinion.com": 2,
		"pixel.solvemedia.com": 4,
		"soma2.de": 4,
		"mobileadtrading.com": 4,
		"sonobi.com": 4,
		"sonos.com": 8,
		"sophus3.com": 4,
		"deployads.com": 4,
		"sndcdn.com": 0,
		"soundcloud.com": 0,
		"provenpixel.com": 4,
		"decenthat.com": 4,
		"summerhamster.com": 4,
		"d3pkae9owd2lcf.cloudfront.net": 4,
		"lijit.com": 4,
		"onscroll.com": 4,
		"rts.sparkstudios.com": 0,
		"sparkasse.de": 8,
		"speakpipe.com": 2,
		"adviva.net": 4,
		"specificclick.net": 4,
		"specificmedia.com": 4,
		"spectate.com": 6,
		"speedshiftmedia.com": 4,
		"speedcurve.com": 6,
		"admarket.entireweb.com": 4,
		"affiliate.entireweb.com": 4,
		"sa.entireweb.com": 4,
		"speee-ad.akamaized.net": 4,
		"sphere.com": 4,
		"surphace.com": 4,
		"api.spheremall.com": 6,
		"zdwidget3-bs.sphereup.com": 2,
		"static.sspicy.ru": 4,
		"spider.ad": 4,
		"metrics.spiderads.eu": 4,
		"spn.ee": 6,
		"embed.spokenlayer.com": 0,
		"spongecell.com": 4,
		"sponsorads.de": 4,
		"sportsbetaffiliates.com.au": 4,
		"spot.im": 7,
		"spoteffects.net": 6,
		"scdn.co": 0,
		"spotify.com": 0,
		"pscdn.co": 0,
		"spotifycdn.com": 0,
		"spotifycdn.net": 0,
		"spotilocal.com": 0,
		"embed.spotify.com": 0,
		"spotscenered.info": 11,
		"spotx.tv": 4,
		"spotxcdn.com": 4,
		"spotxchange.com": 4,
		"spoutable.com": 4,
		"cdn.springboardplatform.com": 4,
		"springserve.com": 4,
		"pixel.sprinklr.com": 4,
		"stat.sputnik.ru": 6,
		"email-match.com": 4,
		"squarespace.com": 6,
		"srvtrck.com": 12,
		"srvvtrk.com": 11,
		"sstatic.net": 9,
		"hatena.ne.jp": 7,
		"st-hatena.com": 7,
		"stackadapt.com": 4,
		"stackpathdns.com": 9,
		"stailamedia.com": 4,
		"stalluva.pro": 11,
		"startappservice.com": 4,
		"hit.stat24.com": 6,
		"adstat.4u.pl": 6,
		"stat.4u.pl": 6,
		"statcounter.com": 6,
		"stathat.com": 6,
		"statisfy.net": 6,
		"statsy.net": 11,
		"statuscake.com": 6,
		"statuspage.io": 2,
		"stspg-customer.com": 2,
		"stayfriends.de": 8,
		"steelhousemedia.com": 4,
		"steepto.com": 4,
		"stepstone.com": 8,
		"4stats.de": 6,
		"stetic.com": 6,
		"stickyadstv.com": 4,
		"stocktwits.com": 2,
		"storify.com": 4,
		"storygize.net": 4,
		"bizsolutions.strands.com": 4,
		"strava.com": 6,
		"mailfoogae.appspot.com": 2,
		"streamotion.com.au": 0,
		"streamrail.com": 4,
		"streamrail.net": 4,
		"stridespark.com": 6,
		"stripcdn.com": 3,
		"stripchat.com": 3,
		"stripe.com": 2,
		"stripe.network": 2,
		"stripst.com": 3,
		"interactivemedia.net": 4,
		"stroeerdigitalgroup.de": 4,
		"stroeerdigitalmedia.de": 4,
		"stroeerdp.de": 4,
		"stroeermediabrands.de": 4,
		"spklw.com": 4,
		"sprinklecontent.com": 4,
		"strossle.it": 4,
		"struq.com": 4,
		"stumble-upon.com": 7,
		"stumbleupon.com": 7,
		"su.pr": 7,
		"sub2tech.com": 4,
		"ayads.co": 4,
		"suggest.io": 4,
		"sumologic.com": 6,
		"sumo.com": 6,
		"sumome.com": 6,
		"sundaysky.com": 4,
		"supercell.com": 2,
		"supercellsupport.com": 2,
		"supercounters.com": 6,
		"superfastcdn.com": 11,
		"socdm.com": 4,
		"supplyframe.com": 4,
		"surfingbird.ru": 2,
		"px.surveywall-api.survata.com": 4,
		"cdn.sweettooth.io": 2,
		"swiftypecdn.com": 9,
		"swisscom.ch": 8,
		"myswitchads.com": 4,
		"switchadhub.com": 4,
		"switchads.com": 4,
		"switchafrica.com": 4,
		"switch.tv": 8,
		"shopximity.com": 4,
		"swoop.com": 4,
		"analytics-cdn.sykescottages.co.uk": 6,
		"norton.com": 5,
		"seal.verisign.com": 5,
		"symantec.com": 5,
		"d.hodes.com": 2,
		"technorati.com": 4,
		"technoratimedia.com": 4,
		"cn.clickable.net": 4,
		"synergy-e.com": 4,
		"sdp-campaign.de": 8,
		"t-online.de": 8,
		"telekom-dienste.de": 8,
		"telekom.com": 8,
		"telekom.de": 8,
		"toi.de": 8,
		"t8cdn.com": 11,
		"tableteducation.com": 11,
		"basebanner.com": 4,
		"taboola.com": 4,
		"taboolasyndication.com": 4,
		"tacoda.net": 4,
		"commander1.com": 5,
		"tagcommander.com": 5,
		"tags.tagcade.com": 4,
		"taggify.net": 4,
		"taggyad.jp": 4,
		"levexis.com": 5,
		"tailtarget.com": 6,
		"tailsweep.com": 4,
		"tamedia.ch": 4,
		"tanx.com": 4,
		"alipcsec.com": 4,
		"taobao.com": 4,
		"tapad.com": 4,
		"theblogfrog.com": 4,
		"tarafdari.com": 4,
		"target2sell.com": 4,
		"trackmytarget.com": 6,
		"cdn.targetfuel.com": 6,
		"tawk.to": 2,
		"tbn.ru": 4,
		"tchibo-content.de": 8,
		"tchibo.de": 8,
		"tdsrmbl.net": 8,
		"teads.tv": 4,
		"tealeaf.ibmcloud.com": 6,
		"tealium.com": 5,
		"tealium.hs.llnwd.net": 5,
		"tealiumiq.com": 5,
		"tiqcdn.com": 5,
		"teaser.cc": 4,
		"emailretargeting.com": 4,
		"tracking.dsmmadvantage.com": 4,
		"telstra.com": 8,
		"telstra.com.au": 8,
		"tenderapp.com": 2,
		"tensitionschoo.club": 11,
		"watch.teroti.com": 4,
		"webterren.com": 4,
		"teufel.de": 8,
		"theadex.com": 4,
		"connect.decknetwork.net": 4,
		"gu-web.net": 8,
		"guardianapps.co.uk": 8,
		"guim.co.uk": 8,
		"deepthought.online": 4,
		"reachgroup.com": 4,
		"redintelligence.net": 4,
		"thesearchagency.net": 4,
		"thesun.co.uk": 8,
		"w-x.co": 4,
		"weather.com": 4,
		"wfxtriggers.com": 4,
		"tmdb.org": 8,
		"thinglink.com": 4,
		"online-metrix.net": 6,
		"tidbit.co.in": 2,
		"code.tidio.co": 2,
		"widget-v4.tidiochat.com": 2,
		"analytics.tiktok.com": 6,
		"optimized.by.tiller.co": 4,
		"vip.timezonedb.com": 4,
		"npttech.com": 5,
		"tinypass.com": 5,
		"tisoomi-services.com": 4,
		"ad.tlvmedia.com": 4,
		"ads.tlvmedia.com": 4,
		"tag.tlvmedia.com": 4,
		"research-int.se": 6,
		"sesamestats.com": 6,
		"spring-tns.net": 6,
		"statistik-gallup.net": 6,
		"tns-cs.net": 6,
		"tns-gallup.dk": 6,
		"tomnewsupdate.info": 12,
		"tfag.de": 4,
		"srv.clickfuse.com": 4,
		"toplist.cz": 11,
		"toponclick.com": 11,
		"topsy.com": 4,
		"insight.torbit.com": 6,
		"toro-tags.com": 4,
		"toroadvertising.com": 4,
		"toroadvertisingmedia.com": 4,
		"tororango.com": 11,
		"i.total-media.net": 4,
		"inq.com": 2,
		"tovarro.com": 4,
		"rialpay.com": 4,
		"tp-cdn.com": 4,
		"kiwe.io": 6,
		"tracc.it": 6,
		"ipnoid.com": 4,
		"tracemyip.org": 4,
		"d2gfdmu30u15x7.cloudfront.net": 6,
		"tracelytics.com": 6,
		"cdn.trackduck.com": 6,
		"d2zah9y47r7bi2.cloudfront.net": 6,
		"dl1d2m8ri9v3j.cloudfront.net": 6,
		"trackjs.com": 6,
		"conversionlab.trackset.com": 4,
		"trackuity.com": 2,
		"adsrvr.org": 4,
		"tradedoubler.com": 4,
		"tradelab.fr": 4,
		"tradetracker.net": 4,
		"cdntrf.com": 4,
		"traffective.com": 4,
		"my.trafficfuel.com": 4,
		"trafficrevenue.net": 4,
		"trafficstars.com": 3,
		"tsyndicate.com": 3,
		"trafficbroker.com": 4,
		"trafficfabrik.com": 3,
		"trafficfactory.biz": 4,
		"trafficforce.com": 4,
		"traffichaus.com": 3,
		"trafficjunky.net": 3,
		"traffiliate.com": 4,
		"storage.trafic.ro": 6,
		"trafmag.com": 4,
		"api.transcend.io": 14,
		"cdn.transcend.io": 14,
		"sync-transcend-cdn.com": 14,
		"transcend-cdn.com": 14,
		"transcend.io": 14,
		"telemetry.transcend.io": 6,
		"backoffice.transmatico.com": 6,
		"travelaudience.com": 6,
		"trbo.com": 4,
		"treasuredata.com": 6,
		"scanscout.com": 0,
		"tremorhub.com": 0,
		"tremormedia.com": 0,
		"tremorvideo.com": 0,
		"videohub.tv": 0,
		"s.tcimg.com": 6,
		"tcimg.com": 6,
		"trendemon.com": 6,
		"exponential.com": 4,
		"tribalfusion.com": 4,
		"tribl.io": 6,
		"api.temails.com": 4,
		"t.myvisitors.se": 2,
		"jscache.com": 8,
		"tacdn.com": 8,
		"tamgrt.com": 8,
		"tripadvisor.co.uk": 8,
		"tripadvisor.com": 8,
		"tripadvisor.de": 8,
		"3lift.com": 4,
		"d3iwjrnl4m67rd.cloudfront.net": 4,
		"triplelift.com": 4,
		"static.triptease.io": 2,
		"andomedia.com": 0,
		"tritondigital.com": 0,
		"revelations.trovus.co.uk": 4,
		"trsv3.com": 11,
		"truefitcorp.com": 4,
		"tru.am": 4,
		"adlegend.com": 4,
		"addoer.com": 6,
		"truehits.in.th": 6,
		"truehits.net": 6,
		"trumba.com": 4,
		"truoptik.com": 6,
		"trustarc.com": 5,
		"truste.com": 5,
		"consent.truste.com": 5,
		"choices-or.truste.com": 5,
		"choices.truste.com": 5,
		"privacy-policy.truste.com": 5,
		"trustedshops.com": 5,
		"trustev.com": 6,
		"secure.comodo.net": 5,
		"trustlogo.com": 5,
		"usertrust.com": 5,
		"trustpilot.com": 2,
		"trustwave.com": 8,
		"tubecorporate.com": 3,
		"tubecup.org": 3,
		"tubemogul.com": 4,
		"sre-perim.com": 6,
		"txmblr.com": 6,
		"platform.tumblr.com": 7,
		"lib.tunein.com": 0,
		"adagio.turboadv.com": 4,
		"turn.com": 4,
		"ngtv.io": 6,
		"turner.com": 6,
		"warnermedia.com": 6,
		"turnsocial.com": 7,
		"turnto.com": 2,
		"tvsquared.com": 4,
		"tweetboard.com": 7,
		"tweetmeme.com": 7,
		"c4tw.net": 4,
		"twiago.com": 4,
		"twinedigital.go2cloud.org": 6,
		"ext-twitch.tv": 0,
		"twitch.tv": 0,
		"jtvnw.net": 0,
		"ttvnw.net": 0,
		"twitchcdn.net": 0,
		"twitchsvc.net": 0,
		"t.co": 7,
		"twimg.com": 7,
		"twitter.com": 7,
		"twttr.com": 7,
		"x.com": 7,
		"ads-twitter.com": 4,
		"analytics.twitter.com": 6,
		"tellapart.com": 4,
		"syndication.twitter.com": 7,
		"twittercounter.com": 6,
		"twyn.com": 4,
		"txxx.com": 8,
		"tynt.com": 4,
		"typeform.com": 2,
		"typepad.com": 6,
		"typography.com": 9,
		"tyroodirect.com": 7,
		"tyroodr.com": 7,
		"tzetze.it": 2,
		"ubersetzung-app.com": 12,
		"ubuntu.com": 8,
		"ubuntucompanyservices.co.za": 8,
		"aralego.net": 4,
		"ucfunnel.com": 4,
		"at.ua": 6,
		"do.am": 6,
		"ucoz.net": 6,
		"ad-api-v01.uliza.jp": 4,
		"api.umbel.com": 6,
		"umebiggestern.club": 11,
		"unanimis.co.uk": 4,
		"d3pkntwtp2ukl5.cloudfront.net": 6,
		"t.unbounce.com": 6,
		"d21gpk1vhmjuf5.cloudfront.net": 6,
		"tracker.unbxdapi.com": 6,
		"under-box.com": 12,
		"undercomputer.com": 11,
		"udmserve.net": 4,
		"undertone.com": 4,
		"roitesting.com": 2,
		"unica.com": 2,
		"unister-adservices.com": 6,
		"unister-gmbh.de": 6,
		"uadx.com": 4,
		"nonstoppartner.net": 4,
		"tifbs.net": 4,
		"ui-portal.de": 4,
		"uimserv.net": 4,
		"unity.com": 8,
		"unity3d.com": 8,
		"unity3dusercontent.com": 8,
		"unityads.unity3d.com": 4,
		"univide.com": 4,
		"unpkg.com": 9,
		"unrulymedia.com": 4,
		"src.kitcode.net": 6,
		"s.clickability.com": 4,
		"uppr.de": 4,
		"upravel.com": 11,
		"upsellit.com": 2,
		"kontagent.net": 6,
		"app.uptain.de": 6,
		"uptolike.com": 7,
		"uptrends.com": 6,
		"urban-media.com": 4,
		"urbanairship.com": 6,
		"mobile.usabilitytools.com": 6,
		"usabilla.com": 2,
		"usemax.de": 4,
		"usemaxserver.de": 4,
		"usemessages.com": 11,
		"api.usercycle.com": 6,
		"userdive.com": 6,
		"userecho.com": 2,
		"dq4irj27fs462.cloudfront.net": 2,
		"userlike-cdn-widgets.s3-eu-west-1.amazonaws.com": 2,
		"userlike.com": 2,
		"contactusplus.com": 2,
		"user-pulse.appspot.com": 2,
		"userpulse.com": 2,
		"userreplay.net": 6,
		"sdsbucket.s3.amazonaws.com": 2,
		"userreport.com": 2,
		"dtkm4pd19nw6z.cloudfront.net": 2,
		"api.usersnap.com": 2,
		"d3mvnvhjmkxpjz.cloudfront.net": 2,
		"uservoice.com": 2,
		"userzoom.com": 2,
		"usocial.pro": 7,
		"utarget.ru": 4,
		"uuidksinc.net": 11,
		"v12group.com": 6,
		"vacaneedasap.com": 11,
		"ads.brand.net": 4,
		"vdrn.redplum.com": 4,
		"api.searchlinks.com": 4,
		"js.searchlinks.com": 4,
		"vinsight.de": 4,
		"valueclick.net": 4,
		"valuecommerce.com": 4,
		"valuedopinions.co.uk": 4,
		"buzzparadise.com": 4,
		"vmmpxl.com": 4,
		"vcita.com": 6,
		"tracking.vcommission.com": 4,
		"vdopia.com": 4,
		"veinteractive.com": 4,
		"vee24.com": 0,
		"velocecdn.com": 11,
		"mdcn.mobi": 4,
		"velti.com": 4,
		"vendemore.com": 1,
		"venturead.com": 11,
		"api.venyoo.ru": 2,
		"veoxa.com": 4,
		"vergic.com": 1,
		"d3qxef4rp70elm.cloudfront.net": 4,
		"getvero.com": 4,
		"verticalacuity.com": 4,
		"roi.vertical-leap.co.uk": 4,
		"cts.vresp.com": 4,
		"verticalscope.com": 4,
		"ads.vertoz.com": 4,
		"banner.vrtzads.com": 4,
		"veruta.com": 4,
		"vrvm.com": 4,
		"vgwort.de": 6,
		"digitaltarget.ru": 4,
		"btg.mtvnservices.com": 4,
		"viafoura.com": 4,
		"viafoura.net": 4,
		"intellitxt.com": 4,
		"vicomi.com": 6,
		"vidazoo.com": 4,
		"module-videodesk.com": 0,
		"vidtok.ru": 0,
		"videoadex.com": 4,
		"tidaltv.com": 4,
		"videonow.ru": 4,
		"videoplayerhub.com": 11,
		"videoplaza.tv": 4,
		"kweb.videostep.com": 4,
		"content.vidgyor.com": 0,
		"vidible.tv": 4,
		"assets.vidora.com": 0,
		"vietad.vn": 4,
		"viglink.com": 4,
		"vigo.one": 6,
		"vigo.ru": 6,
		"vimeo.com": 0,
		"vimeocdn.com": 0,
		"vindicosuite.com": 4,
		"vinted.net": 8,
		"viraladnetwork.net": 4,
		"app.viral-loops.com": 2,
		"viralgains.com": 4,
		"viralmint.com": 7,
		"virgul.com": 4,
		"ssp.virool.com": 4,
		"virtusize.com": 5,
		"viewablemedia.net": 4,
		"visiblemeasures.com": 4,
		"visioncriticalpanels.com": 6,
		"visitstreamer.com": 6,
		"visitortracklog.com": 4,
		"visitorville.com": 6,
		"d2hkbi3gan6yg6.cloudfront.net": 4,
		"myvisualiq.net": 6,
		"visualrevenue.com": 6,
		"d5phz18u4wuww.cloudfront.net": 6,
		"visualwebsiteoptimizer.com": 6,
		"wingify.com": 6,
		"vdna-assets.com": 4,
		"visualdna.com": 4,
		"visualstudio.com": 8,
		"id-visitors.com": 6,
		"vi-tag.net": 4,
		"vivistats.com": 6,
		"vizury.com": 4,
		"vizzit.se": 4,
		"cdn-vk.com": 7,
		"vk-analytics.com": 7,
		"vkuservideo.net": 7,
		"userapi.com": 7,
		"vk.com": 7,
		"vkontakte.ru": 7,
		"vntsm.com": 4,
		"vodafone.de": 8,
		"voicefive.com": 6,
		"volusion.com": 2,
		"cwkuki.com": 4,
		"volumtrk.com": 4,
		"voluumtrk3.com": 4,
		"vooxe.com": 8,
		"vorwerk.de": 8,
		"vox-cdn.com": 2,
		"embed.voxus.tv": 4,
		"voxus-targeting-voxusmidia.netdna-ssl.com": 4,
		"c-dsp.vpadn.com": 4,
		"tools.vpscash.nl": 4,
		"vsassets.io": 8,
		"exp-tas.com": 8,
		"v0cdn.net": 8,
		"vscode-cdn.net": 8,
		"vscode-unpkg.net": 8,
		"vtracy.de": 11,
		"liftoff.io": 4,
		"vungle.com": 4,
		"vuukle.com": 6,
		"view.vzaar.com": 0,
		"w3counter.com": 6,
		"w3roi.com": 6,
		"contentwidgets.net": 2,
		"wahoha.com": 2,
		"walkme.com": 2,
		"wsod.com": 4,
		"walmart.com": 8,
		"wamcash.com": 3,
		"cdn-saveit.wanelo.com": 2,
		"static.warp.ly": 6,
		"way2traffic.com": 4,
		"wayfair.com": 8,
		"wdr.de": 8,
		"web-stat.com": 6,
		"web.de": 8,
		"webde.de": 8,
		"webstat.net": 6,
		"ssl.webserviceaward.com": 6,
		"webtraxs.com": 6,
		"wipe.de": 6,
		"webads.nl": 4,
		"tr.webantenna.info": 6,
		"webclicks24.com": 11,
		"webclose.net": 12,
		"webcollage.net": 2,
		"goutee.top": 4,
		"mediaathay.org.uk": 4,
		"wbdx.fr": 4,
		"webeffective.keynote.com": 6,
		"widgets.webengage.com": 2,
		"webgains.com": 8,
		"webgozar.com": 6,
		"webgozar.ir": 6,
		"webhelpje.be": 2,
		"webhelpje.nl": 2,
		"webleads-tracker.com": 6,
		"automation.webmecanik.com": 6,
		"adrcdn.com": 4,
		"adrcntr.com": 4,
		"weborama.com": 4,
		"weborama.fr": 4,
		"webprospector.de": 6,
		"webstat.com": 6,
		"webstat.se": 6,
		"stat.webtrack.biz": 6,
		"webtraffic.no": 6,
		"webtraffic.se": 6,
		"d1r27qvpjiaqj3.cloudfront.net": 6,
		"mateti.net": 6,
		"wbtrk.net": 6,
		"wcfbc.net": 6,
		"webtrekk-asia.net": 6,
		"webtrekk.com": 6,
		"webtrekk.de": 6,
		"webtrekk.net": 6,
		"wt-eu02.net": 6,
		"wt-safetag.com": 6,
		"webtrends.com": 6,
		"webtrendslive.com": 6,
		"rd.clickshift.com": 4,
		"web-visor.com": 6,
		"weebly.com": 4,
		"widget.weibo.com": 4,
		"westlotto.com": 8,
		"wetter.com": 8,
		"wettercomassets.com": 8,
		"whatsbroadcast.com": 2,
		"whatsapp.com": 8,
		"whatsapp.net": 8,
		"whisper.onelink.me": 7,
		"whisper.sh": 7,
		"amung.us": 6,
		"whoson.com": 6,
		"api.wibbitz.com": 0,
		"cdn4.wibbitz.com": 0,
		"cdn.wibiya.com": 7,
		"predictad.com": 2,
		"widerplanet.com": 4,
		"widespace.com": 4,
		"widgetserver.com": 2,
		"3c45d848d99.se": 4,
		"wigetmedia.com": 4,
		"tracker.wigzopush.com": 4,
		"wikia-services.com": 8,
		"wikia-beacon.com": 6,
		"nocookie.net": 9,
		"wikimedia.org": 9,
		"wikipedia.org": 9,
		"wikiquote.org": 9,
		"tracking.winaffiliates.com": 6,
		"maps.windows.com": 8,
		"client.wns.windows.com": 8,
		"time.windows.com": 8,
		"windowsupdate.com": 9,
		"api.wipmania.com": 6,
		"col1.wiqhit.com": 6,
		"wirecard.com": 2,
		"wirecard.de": 2,
		"leadlab.click": 6,
		"wiredminds.com": 6,
		"wiredminds.de": 6,
		"adtotal.pl": 4,
		"wisepops.com": 4,
		"cdn.wishpond.net": 2,
		"wistia.com": 6,
		"wistia.net": 6,
		"parastorage.com": 8,
		"wix.com": 8,
		"public.wixab-cloud.com": 6,
		"wixmp.com": 9,
		"wnzmauurgol.com": 11,
		"wonderpush.com": 2,
		"woopic.com": 8,
		"woopra.com": 6,
		"pubmine.com": 4,
		"w.org": 6,
		"wordpress.com": 6,
		"wp.com": 6,
		"tracker.wordstream.com": 6,
		"worldnaturenet.xyz": 12,
		"wp.pl": 4,
		"wpimg.pl": 4,
		"wpengine.com": 5,
		"clickanalyzer.jp": 6,
		"wurfl.io": 6,
		"wwwpromoter.com": 4,
		"imgwykop.pl": 7,
		"wykop.pl": 7,
		"wysistat.com": 6,
		"wysistat.net": 6,
		"wywy.com": 4,
		"wywyuserservice.com": 4,
		"cdn.x-lift.jp": 4,
		"xapads.com": 4,
		"xen-media.com": 11,
		"xfreeservice.com": 11,
		"xhamster.com": 3,
		"xhamsterlive.com": 3,
		"xhamsterpremium.com": 3,
		"xhcdn.com": 3,
		"huami.com": 8,
		"mi-img.com": 8,
		"mi.com": 8,
		"miui.com": 8,
		"xiaomi.com": 8,
		"xiaomi.net": 8,
		"xiaomiyoupin.com": 8,
		"xing-share.com": 6,
		"xing.com": 6,
		"xmediaclicks.com": 3,
		"xnxx-cdn.com": 9,
		"xplosion.de": 4,
		"xtendmedia.com": 4,
		"xvideos-cdn.com": 8,
		"xvideos.com": 8,
		"xxxlshop.de": 8,
		"xxxlutz.de": 8,
		"adx.com.ru": 4,
		"yabbi.me": 4,
		"yabuka.com": 4,
		"tumblr.com": 6,
		"yahoo.com": 6,
		"yahooapis.com": 6,
		"yimg.com": 6,
		"oath.cloud": 6,
		"yahoo.net": 6,
		"yahooinc.com": 6,
		"yahoodns.net": 6,
		"yads.yahoo.com": 4,
		"yieldmanager.com": 4,
		"pr-bh.ybp.yahoo.com": 4,
		"ads.yahoo.com": 4,
		"adtech.yahooinc.com": 4,
		"analytics.yahoo.com": 6,
		"np.lexity.com": 4,
		"storage-yahoo.jp": 4,
		"yahoo.co.jp": 4,
		"yahooapis.jp": 4,
		"yimg.jp": 4,
		"yjtag.jp": 4,
		"ov.yahoo.co.jp": 4,
		"overture.com": 4,
		"search.yahooinc.com": 4,
		"luminate.com": 4,
		"pixazza.com": 4,
		"awaps.yandex.ru": 4,
		"d31j93rd8oukbv.cloudfront.net": 4,
		"webvisor.org": 4,
		"yandex.net": 4,
		"yandex.ru": 4,
		"yastatic.net": 4,
		"ya.ru": 4,
		"yandex.by": 4,
		"yandex.com": 4,
		"yandex.com.tr": 4,
		"yandex.fr": 4,
		"yandex.kz": 4,
		"yandex.st": 2,
		"yandexadexchange.net": 4,
		"metabar.ru": 12,
		"appmetrica.yandex.com": 101,
		"an.webvisor.org": 6,
		"an.yandex.ru": 6,
		"bs.yandex.ru": 6,
		"mc.yandex.ru": 6,
		"passport.yandex.ru": 2,
		"yapfiles.ru": 8,
		"yashi.com": 4,
		"ad.adserverplus.com": 4,
		"player.sambaads.com": 0,
		"cdn.yektanet.com": 4,
		"fetch.yektanet.com": 4,
		"yengo.com": 4,
		"yengointernational.com": 4,
		"link.p0.com": 4,
		"adsrevenue.net": 4,
		"infinityads.com": 4,
		"momentsharing.com": 4,
		"multipops.com": 4,
		"onlineadultadvertising.com": 4,
		"paypopup.com": 4,
		"popupxxx.com": 4,
		"xtargeting.com": 4,
		"xxxwebtraffic.com": 4,
		"app.yesware.com": 2,
		"yldbt.com": 6,
		"yieldify.com": 4,
		"yieldlab.net": 4,
		"yieldlove-ad-serving.net": 4,
		"yieldlove.com": 4,
		"yieldmo.com": 4,
		"254a.com": 4,
		"collect.yldr.io": 6,
		"yieldsquare.com": 4,
		"analytics-sdk.yle.fi": 6,
		"yllix.com": 4,
		"ymetrica1.com": 11,
		"ymzrrizntbhde.com": 11,
		"yoapp.s3.amazonaws.com": 2,
		"natpal.com": 4,
		"analytics.yola.net": 6,
		"pixel.yola.net": 6,
		"delivery.yomedia.vn": 4,
		"yoochoose.net": 4,
		"yotpo.com": 1,
		"yottaa.net": 6,
		"yottlyscript.com": 4,
		"api.youcanbook.me": 2,
		"youcanbook.me": 2,
		"player.youku.com": 0,
		"youporn.com": 3,
		"ypncdn.com": 3,
		"googlevideo.com": 0,
		"youtube-nocookie.com": 0,
		"youtube.com": 0,
		"ytimg.com": 0,
		"c.ypcdn.com": 4,
		"i1.ypcdn.com": 4,
		"yellowpages.com": 4,
		"prod-js.aws.y-track.com": 4,
		"y-track.com": 4,
		"yume.com": 4,
		"yumenetworks.com": 4,
		"gravityrd-services.com": 6,
		"api.zadarma.com": 2,
		"zalan.do": 8,
		"zalando.de": 8,
		"ztat.net": 8,
		"zaloapp.com": 2,
		"zanox-affiliate.de": 4,
		"zanox.com": 4,
		"zanox.ws": 4,
		"zaparena.com": 4,
		"zapunited.com": 4,
		"track.zappos.com": 4,
		"zdassets.com": 8,
		"zebestof.com": 4,
		"zedo.com": 4,
		"zemanta.com": 2,
		"zencdn.net": 0,
		"zendesk.com": 2,
		"zergnet.com": 2,
		"zero.kz": 6,
		"app.insightgrit.com": 2,
		"app.ubertags.com": 2,
		"cdn.boomtrain.com": 2,
		"events.api.boomtrain.com": 2,
		"rfihub.com": 2,
		"rfihub.net": 2,
		"ru4.com": 2,
		"xplusone.com": 2,
		"zeusclicks.com": 4,
		"webtest.net": 4,
		"zdbb.net": 4,
		"ziffdavis.com": 4,
		"ziffdavisinternational.com": 4,
		"ziffprod.com": 4,
		"ziffstatic.com": 4,
		"analytics.ziftsolutions.com": 6,
		"zimbio.com": 8,
		"api.zippyshare.com": 2,
		"zmags.com": 6,
		"zmctrack.net": 11,
		"zog.link": 11,
		"js.zohostatic.eu": 6,
		"zononi.com": 3,
		"zopim.com": 2,
		"zukxd6fkxqn.com": 11,
		"zwaar.net": 4,
		"zwaar.org": 4,
		"extend.tv": 4
	}
};




/***/ }),

/***/ 63596:
/***/ (function(module) {

!function(e,t){ true?module.exports=t():0}(this,(function(){return function(e){var t={};function r(n){if(t[n])return t[n].exports;var i=t[n]={i:n,l:!1,exports:{}};return e[n].call(i.exports,i,i.exports,r),i.l=!0,i.exports}return r.m=e,r.c=t,r.d=function(e,t,n){r.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:n})},r.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},r.t=function(e,t){if(1&t&&(e=r(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var n=Object.create(null);if(r.r(n),Object.defineProperty(n,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var i in e)r.d(n,i,function(t){return e[t]}.bind(null,i));return n},r.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return r.d(t,"a",t),t},r.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},r.p="",r(r.s=90)}({17:function(e,t,r){"use strict";t.__esModule=!0,t.default=void 0;var n=r(18),i=function(){function e(){}return e.getFirstMatch=function(e,t){var r=t.match(e);return r&&r.length>0&&r[1]||""},e.getSecondMatch=function(e,t){var r=t.match(e);return r&&r.length>1&&r[2]||""},e.matchAndReturnConst=function(e,t,r){if(e.test(t))return r},e.getWindowsVersionName=function(e){switch(e){case"NT":return"NT";case"XP":return"XP";case"NT 5.0":return"2000";case"NT 5.1":return"XP";case"NT 5.2":return"2003";case"NT 6.0":return"Vista";case"NT 6.1":return"7";case"NT 6.2":return"8";case"NT 6.3":return"8.1";case"NT 10.0":return"10";default:return}},e.getMacOSVersionName=function(e){var t=e.split(".").splice(0,2).map((function(e){return parseInt(e,10)||0}));if(t.push(0),10===t[0])switch(t[1]){case 5:return"Leopard";case 6:return"Snow Leopard";case 7:return"Lion";case 8:return"Mountain Lion";case 9:return"Mavericks";case 10:return"Yosemite";case 11:return"El Capitan";case 12:return"Sierra";case 13:return"High Sierra";case 14:return"Mojave";case 15:return"Catalina";default:return}},e.getAndroidVersionName=function(e){var t=e.split(".").splice(0,2).map((function(e){return parseInt(e,10)||0}));if(t.push(0),!(1===t[0]&&t[1]<5))return 1===t[0]&&t[1]<6?"Cupcake":1===t[0]&&t[1]>=6?"Donut":2===t[0]&&t[1]<2?"Eclair":2===t[0]&&2===t[1]?"Froyo":2===t[0]&&t[1]>2?"Gingerbread":3===t[0]?"Honeycomb":4===t[0]&&t[1]<1?"Ice Cream Sandwich":4===t[0]&&t[1]<4?"Jelly Bean":4===t[0]&&t[1]>=4?"KitKat":5===t[0]?"Lollipop":6===t[0]?"Marshmallow":7===t[0]?"Nougat":8===t[0]?"Oreo":9===t[0]?"Pie":void 0},e.getVersionPrecision=function(e){return e.split(".").length},e.compareVersions=function(t,r,n){void 0===n&&(n=!1);var i=e.getVersionPrecision(t),s=e.getVersionPrecision(r),a=Math.max(i,s),o=0,u=e.map([t,r],(function(t){var r=a-e.getVersionPrecision(t),n=t+new Array(r+1).join(".0");return e.map(n.split("."),(function(e){return new Array(20-e.length).join("0")+e})).reverse()}));for(n&&(o=a-Math.min(i,s)),a-=1;a>=o;){if(u[0][a]>u[1][a])return 1;if(u[0][a]===u[1][a]){if(a===o)return 0;a-=1}else if(u[0][a]<u[1][a])return-1}},e.map=function(e,t){var r,n=[];if(Array.prototype.map)return Array.prototype.map.call(e,t);for(r=0;r<e.length;r+=1)n.push(t(e[r]));return n},e.find=function(e,t){var r,n;if(Array.prototype.find)return Array.prototype.find.call(e,t);for(r=0,n=e.length;r<n;r+=1){var i=e[r];if(t(i,r))return i}},e.assign=function(e){for(var t,r,n=e,i=arguments.length,s=new Array(i>1?i-1:0),a=1;a<i;a++)s[a-1]=arguments[a];if(Object.assign)return Object.assign.apply(Object,[e].concat(s));var o=function(){var e=s[t];"object"==typeof e&&null!==e&&Object.keys(e).forEach((function(t){n[t]=e[t]}))};for(t=0,r=s.length;t<r;t+=1)o();return e},e.getBrowserAlias=function(e){return n.BROWSER_ALIASES_MAP[e]},e.getBrowserTypeByAlias=function(e){return n.BROWSER_MAP[e]||""},e}();t.default=i,e.exports=t.default},18:function(e,t,r){"use strict";t.__esModule=!0,t.ENGINE_MAP=t.OS_MAP=t.PLATFORMS_MAP=t.BROWSER_MAP=t.BROWSER_ALIASES_MAP=void 0;t.BROWSER_ALIASES_MAP={"Amazon Silk":"amazon_silk","Android Browser":"android",Bada:"bada",BlackBerry:"blackberry",Chrome:"chrome",Chromium:"chromium",Electron:"electron",Epiphany:"epiphany",Firefox:"firefox",Focus:"focus",Generic:"generic","Google Search":"google_search",Googlebot:"googlebot","Internet Explorer":"ie","K-Meleon":"k_meleon",Maxthon:"maxthon","Microsoft Edge":"edge","MZ Browser":"mz","NAVER Whale Browser":"naver",Opera:"opera","Opera Coast":"opera_coast",PhantomJS:"phantomjs",Puffin:"puffin",QupZilla:"qupzilla",QQ:"qq",QQLite:"qqlite",Safari:"safari",Sailfish:"sailfish","Samsung Internet for Android":"samsung_internet",SeaMonkey:"seamonkey",Sleipnir:"sleipnir",Swing:"swing",Tizen:"tizen","UC Browser":"uc",Vivaldi:"vivaldi","WebOS Browser":"webos",WeChat:"wechat","Yandex Browser":"yandex",Roku:"roku"};t.BROWSER_MAP={amazon_silk:"Amazon Silk",android:"Android Browser",bada:"Bada",blackberry:"BlackBerry",chrome:"Chrome",chromium:"Chromium",electron:"Electron",epiphany:"Epiphany",firefox:"Firefox",focus:"Focus",generic:"Generic",googlebot:"Googlebot",google_search:"Google Search",ie:"Internet Explorer",k_meleon:"K-Meleon",maxthon:"Maxthon",edge:"Microsoft Edge",mz:"MZ Browser",naver:"NAVER Whale Browser",opera:"Opera",opera_coast:"Opera Coast",phantomjs:"PhantomJS",puffin:"Puffin",qupzilla:"QupZilla",qq:"QQ Browser",qqlite:"QQ Browser Lite",safari:"Safari",sailfish:"Sailfish",samsung_internet:"Samsung Internet for Android",seamonkey:"SeaMonkey",sleipnir:"Sleipnir",swing:"Swing",tizen:"Tizen",uc:"UC Browser",vivaldi:"Vivaldi",webos:"WebOS Browser",wechat:"WeChat",yandex:"Yandex Browser"};t.PLATFORMS_MAP={tablet:"tablet",mobile:"mobile",desktop:"desktop",tv:"tv"};t.OS_MAP={WindowsPhone:"Windows Phone",Windows:"Windows",MacOS:"macOS",iOS:"iOS",Android:"Android",WebOS:"WebOS",BlackBerry:"BlackBerry",Bada:"Bada",Tizen:"Tizen",Linux:"Linux",ChromeOS:"Chrome OS",PlayStation4:"PlayStation 4",Roku:"Roku"};t.ENGINE_MAP={EdgeHTML:"EdgeHTML",Blink:"Blink",Trident:"Trident",Presto:"Presto",Gecko:"Gecko",WebKit:"WebKit"}},90:function(e,t,r){"use strict";t.__esModule=!0,t.default=void 0;var n,i=(n=r(91))&&n.__esModule?n:{default:n},s=r(18);function a(e,t){for(var r=0;r<t.length;r++){var n=t[r];n.enumerable=n.enumerable||!1,n.configurable=!0,"value"in n&&(n.writable=!0),Object.defineProperty(e,n.key,n)}}var o=function(){function e(){}var t,r,n;return e.getParser=function(e,t){if(void 0===t&&(t=!1),"string"!=typeof e)throw new Error("UserAgent should be a string");return new i.default(e,t)},e.parse=function(e){return new i.default(e).getResult()},t=e,n=[{key:"BROWSER_MAP",get:function(){return s.BROWSER_MAP}},{key:"ENGINE_MAP",get:function(){return s.ENGINE_MAP}},{key:"OS_MAP",get:function(){return s.OS_MAP}},{key:"PLATFORMS_MAP",get:function(){return s.PLATFORMS_MAP}}],(r=null)&&a(t.prototype,r),n&&a(t,n),e}();t.default=o,e.exports=t.default},91:function(e,t,r){"use strict";t.__esModule=!0,t.default=void 0;var n=u(r(92)),i=u(r(93)),s=u(r(94)),a=u(r(95)),o=u(r(17));function u(e){return e&&e.__esModule?e:{default:e}}var d=function(){function e(e,t){if(void 0===t&&(t=!1),null==e||""===e)throw new Error("UserAgent parameter can't be empty");this._ua=e,this.parsedResult={},!0!==t&&this.parse()}var t=e.prototype;return t.getUA=function(){return this._ua},t.test=function(e){return e.test(this._ua)},t.parseBrowser=function(){var e=this;this.parsedResult.browser={};var t=o.default.find(n.default,(function(t){if("function"==typeof t.test)return t.test(e);if(t.test instanceof Array)return t.test.some((function(t){return e.test(t)}));throw new Error("Browser's test function is not valid")}));return t&&(this.parsedResult.browser=t.describe(this.getUA())),this.parsedResult.browser},t.getBrowser=function(){return this.parsedResult.browser?this.parsedResult.browser:this.parseBrowser()},t.getBrowserName=function(e){return e?String(this.getBrowser().name).toLowerCase()||"":this.getBrowser().name||""},t.getBrowserVersion=function(){return this.getBrowser().version},t.getOS=function(){return this.parsedResult.os?this.parsedResult.os:this.parseOS()},t.parseOS=function(){var e=this;this.parsedResult.os={};var t=o.default.find(i.default,(function(t){if("function"==typeof t.test)return t.test(e);if(t.test instanceof Array)return t.test.some((function(t){return e.test(t)}));throw new Error("Browser's test function is not valid")}));return t&&(this.parsedResult.os=t.describe(this.getUA())),this.parsedResult.os},t.getOSName=function(e){var t=this.getOS().name;return e?String(t).toLowerCase()||"":t||""},t.getOSVersion=function(){return this.getOS().version},t.getPlatform=function(){return this.parsedResult.platform?this.parsedResult.platform:this.parsePlatform()},t.getPlatformType=function(e){void 0===e&&(e=!1);var t=this.getPlatform().type;return e?String(t).toLowerCase()||"":t||""},t.parsePlatform=function(){var e=this;this.parsedResult.platform={};var t=o.default.find(s.default,(function(t){if("function"==typeof t.test)return t.test(e);if(t.test instanceof Array)return t.test.some((function(t){return e.test(t)}));throw new Error("Browser's test function is not valid")}));return t&&(this.parsedResult.platform=t.describe(this.getUA())),this.parsedResult.platform},t.getEngine=function(){return this.parsedResult.engine?this.parsedResult.engine:this.parseEngine()},t.getEngineName=function(e){return e?String(this.getEngine().name).toLowerCase()||"":this.getEngine().name||""},t.parseEngine=function(){var e=this;this.parsedResult.engine={};var t=o.default.find(a.default,(function(t){if("function"==typeof t.test)return t.test(e);if(t.test instanceof Array)return t.test.some((function(t){return e.test(t)}));throw new Error("Browser's test function is not valid")}));return t&&(this.parsedResult.engine=t.describe(this.getUA())),this.parsedResult.engine},t.parse=function(){return this.parseBrowser(),this.parseOS(),this.parsePlatform(),this.parseEngine(),this},t.getResult=function(){return o.default.assign({},this.parsedResult)},t.satisfies=function(e){var t=this,r={},n=0,i={},s=0;if(Object.keys(e).forEach((function(t){var a=e[t];"string"==typeof a?(i[t]=a,s+=1):"object"==typeof a&&(r[t]=a,n+=1)})),n>0){var a=Object.keys(r),u=o.default.find(a,(function(e){return t.isOS(e)}));if(u){var d=this.satisfies(r[u]);if(void 0!==d)return d}var c=o.default.find(a,(function(e){return t.isPlatform(e)}));if(c){var f=this.satisfies(r[c]);if(void 0!==f)return f}}if(s>0){var l=Object.keys(i),h=o.default.find(l,(function(e){return t.isBrowser(e,!0)}));if(void 0!==h)return this.compareVersion(i[h])}},t.isBrowser=function(e,t){void 0===t&&(t=!1);var r=this.getBrowserName().toLowerCase(),n=e.toLowerCase(),i=o.default.getBrowserTypeByAlias(n);return t&&i&&(n=i.toLowerCase()),n===r},t.compareVersion=function(e){var t=[0],r=e,n=!1,i=this.getBrowserVersion();if("string"==typeof i)return">"===e[0]||"<"===e[0]?(r=e.substr(1),"="===e[1]?(n=!0,r=e.substr(2)):t=[],">"===e[0]?t.push(1):t.push(-1)):"="===e[0]?r=e.substr(1):"~"===e[0]&&(n=!0,r=e.substr(1)),t.indexOf(o.default.compareVersions(i,r,n))>-1},t.isOS=function(e){return this.getOSName(!0)===String(e).toLowerCase()},t.isPlatform=function(e){return this.getPlatformType(!0)===String(e).toLowerCase()},t.isEngine=function(e){return this.getEngineName(!0)===String(e).toLowerCase()},t.is=function(e,t){return void 0===t&&(t=!1),this.isBrowser(e,t)||this.isOS(e)||this.isPlatform(e)},t.some=function(e){var t=this;return void 0===e&&(e=[]),e.some((function(e){return t.is(e)}))},e}();t.default=d,e.exports=t.default},92:function(e,t,r){"use strict";t.__esModule=!0,t.default=void 0;var n,i=(n=r(17))&&n.__esModule?n:{default:n};var s=/version\/(\d+(\.?_?\d+)+)/i,a=[{test:[/googlebot/i],describe:function(e){var t={name:"Googlebot"},r=i.default.getFirstMatch(/googlebot\/(\d+(\.\d+))/i,e)||i.default.getFirstMatch(s,e);return r&&(t.version=r),t}},{test:[/opera/i],describe:function(e){var t={name:"Opera"},r=i.default.getFirstMatch(s,e)||i.default.getFirstMatch(/(?:opera)[\s/](\d+(\.?_?\d+)+)/i,e);return r&&(t.version=r),t}},{test:[/opr\/|opios/i],describe:function(e){var t={name:"Opera"},r=i.default.getFirstMatch(/(?:opr|opios)[\s/](\S+)/i,e)||i.default.getFirstMatch(s,e);return r&&(t.version=r),t}},{test:[/SamsungBrowser/i],describe:function(e){var t={name:"Samsung Internet for Android"},r=i.default.getFirstMatch(s,e)||i.default.getFirstMatch(/(?:SamsungBrowser)[\s/](\d+(\.?_?\d+)+)/i,e);return r&&(t.version=r),t}},{test:[/Whale/i],describe:function(e){var t={name:"NAVER Whale Browser"},r=i.default.getFirstMatch(s,e)||i.default.getFirstMatch(/(?:whale)[\s/](\d+(?:\.\d+)+)/i,e);return r&&(t.version=r),t}},{test:[/MZBrowser/i],describe:function(e){var t={name:"MZ Browser"},r=i.default.getFirstMatch(/(?:MZBrowser)[\s/](\d+(?:\.\d+)+)/i,e)||i.default.getFirstMatch(s,e);return r&&(t.version=r),t}},{test:[/focus/i],describe:function(e){var t={name:"Focus"},r=i.default.getFirstMatch(/(?:focus)[\s/](\d+(?:\.\d+)+)/i,e)||i.default.getFirstMatch(s,e);return r&&(t.version=r),t}},{test:[/swing/i],describe:function(e){var t={name:"Swing"},r=i.default.getFirstMatch(/(?:swing)[\s/](\d+(?:\.\d+)+)/i,e)||i.default.getFirstMatch(s,e);return r&&(t.version=r),t}},{test:[/coast/i],describe:function(e){var t={name:"Opera Coast"},r=i.default.getFirstMatch(s,e)||i.default.getFirstMatch(/(?:coast)[\s/](\d+(\.?_?\d+)+)/i,e);return r&&(t.version=r),t}},{test:[/opt\/\d+(?:.?_?\d+)+/i],describe:function(e){var t={name:"Opera Touch"},r=i.default.getFirstMatch(/(?:opt)[\s/](\d+(\.?_?\d+)+)/i,e)||i.default.getFirstMatch(s,e);return r&&(t.version=r),t}},{test:[/yabrowser/i],describe:function(e){var t={name:"Yandex Browser"},r=i.default.getFirstMatch(/(?:yabrowser)[\s/](\d+(\.?_?\d+)+)/i,e)||i.default.getFirstMatch(s,e);return r&&(t.version=r),t}},{test:[/ucbrowser/i],describe:function(e){var t={name:"UC Browser"},r=i.default.getFirstMatch(s,e)||i.default.getFirstMatch(/(?:ucbrowser)[\s/](\d+(\.?_?\d+)+)/i,e);return r&&(t.version=r),t}},{test:[/Maxthon|mxios/i],describe:function(e){var t={name:"Maxthon"},r=i.default.getFirstMatch(s,e)||i.default.getFirstMatch(/(?:Maxthon|mxios)[\s/](\d+(\.?_?\d+)+)/i,e);return r&&(t.version=r),t}},{test:[/epiphany/i],describe:function(e){var t={name:"Epiphany"},r=i.default.getFirstMatch(s,e)||i.default.getFirstMatch(/(?:epiphany)[\s/](\d+(\.?_?\d+)+)/i,e);return r&&(t.version=r),t}},{test:[/puffin/i],describe:function(e){var t={name:"Puffin"},r=i.default.getFirstMatch(s,e)||i.default.getFirstMatch(/(?:puffin)[\s/](\d+(\.?_?\d+)+)/i,e);return r&&(t.version=r),t}},{test:[/sleipnir/i],describe:function(e){var t={name:"Sleipnir"},r=i.default.getFirstMatch(s,e)||i.default.getFirstMatch(/(?:sleipnir)[\s/](\d+(\.?_?\d+)+)/i,e);return r&&(t.version=r),t}},{test:[/k-meleon/i],describe:function(e){var t={name:"K-Meleon"},r=i.default.getFirstMatch(s,e)||i.default.getFirstMatch(/(?:k-meleon)[\s/](\d+(\.?_?\d+)+)/i,e);return r&&(t.version=r),t}},{test:[/micromessenger/i],describe:function(e){var t={name:"WeChat"},r=i.default.getFirstMatch(/(?:micromessenger)[\s/](\d+(\.?_?\d+)+)/i,e)||i.default.getFirstMatch(s,e);return r&&(t.version=r),t}},{test:[/qqbrowser/i],describe:function(e){var t={name:/qqbrowserlite/i.test(e)?"QQ Browser Lite":"QQ Browser"},r=i.default.getFirstMatch(/(?:qqbrowserlite|qqbrowser)[/](\d+(\.?_?\d+)+)/i,e)||i.default.getFirstMatch(s,e);return r&&(t.version=r),t}},{test:[/msie|trident/i],describe:function(e){var t={name:"Internet Explorer"},r=i.default.getFirstMatch(/(?:msie |rv:)(\d+(\.?_?\d+)+)/i,e);return r&&(t.version=r),t}},{test:[/\sedg\//i],describe:function(e){var t={name:"Microsoft Edge"},r=i.default.getFirstMatch(/\sedg\/(\d+(\.?_?\d+)+)/i,e);return r&&(t.version=r),t}},{test:[/edg([ea]|ios)/i],describe:function(e){var t={name:"Microsoft Edge"},r=i.default.getSecondMatch(/edg([ea]|ios)\/(\d+(\.?_?\d+)+)/i,e);return r&&(t.version=r),t}},{test:[/vivaldi/i],describe:function(e){var t={name:"Vivaldi"},r=i.default.getFirstMatch(/vivaldi\/(\d+(\.?_?\d+)+)/i,e);return r&&(t.version=r),t}},{test:[/seamonkey/i],describe:function(e){var t={name:"SeaMonkey"},r=i.default.getFirstMatch(/seamonkey\/(\d+(\.?_?\d+)+)/i,e);return r&&(t.version=r),t}},{test:[/sailfish/i],describe:function(e){var t={name:"Sailfish"},r=i.default.getFirstMatch(/sailfish\s?browser\/(\d+(\.\d+)?)/i,e);return r&&(t.version=r),t}},{test:[/silk/i],describe:function(e){var t={name:"Amazon Silk"},r=i.default.getFirstMatch(/silk\/(\d+(\.?_?\d+)+)/i,e);return r&&(t.version=r),t}},{test:[/phantom/i],describe:function(e){var t={name:"PhantomJS"},r=i.default.getFirstMatch(/phantomjs\/(\d+(\.?_?\d+)+)/i,e);return r&&(t.version=r),t}},{test:[/slimerjs/i],describe:function(e){var t={name:"SlimerJS"},r=i.default.getFirstMatch(/slimerjs\/(\d+(\.?_?\d+)+)/i,e);return r&&(t.version=r),t}},{test:[/blackberry|\bbb\d+/i,/rim\stablet/i],describe:function(e){var t={name:"BlackBerry"},r=i.default.getFirstMatch(s,e)||i.default.getFirstMatch(/blackberry[\d]+\/(\d+(\.?_?\d+)+)/i,e);return r&&(t.version=r),t}},{test:[/(web|hpw)[o0]s/i],describe:function(e){var t={name:"WebOS Browser"},r=i.default.getFirstMatch(s,e)||i.default.getFirstMatch(/w(?:eb)?[o0]sbrowser\/(\d+(\.?_?\d+)+)/i,e);return r&&(t.version=r),t}},{test:[/bada/i],describe:function(e){var t={name:"Bada"},r=i.default.getFirstMatch(/dolfin\/(\d+(\.?_?\d+)+)/i,e);return r&&(t.version=r),t}},{test:[/tizen/i],describe:function(e){var t={name:"Tizen"},r=i.default.getFirstMatch(/(?:tizen\s?)?browser\/(\d+(\.?_?\d+)+)/i,e)||i.default.getFirstMatch(s,e);return r&&(t.version=r),t}},{test:[/qupzilla/i],describe:function(e){var t={name:"QupZilla"},r=i.default.getFirstMatch(/(?:qupzilla)[\s/](\d+(\.?_?\d+)+)/i,e)||i.default.getFirstMatch(s,e);return r&&(t.version=r),t}},{test:[/firefox|iceweasel|fxios/i],describe:function(e){var t={name:"Firefox"},r=i.default.getFirstMatch(/(?:firefox|iceweasel|fxios)[\s/](\d+(\.?_?\d+)+)/i,e);return r&&(t.version=r),t}},{test:[/electron/i],describe:function(e){var t={name:"Electron"},r=i.default.getFirstMatch(/(?:electron)\/(\d+(\.?_?\d+)+)/i,e);return r&&(t.version=r),t}},{test:[/MiuiBrowser/i],describe:function(e){var t={name:"Miui"},r=i.default.getFirstMatch(/(?:MiuiBrowser)[\s/](\d+(\.?_?\d+)+)/i,e);return r&&(t.version=r),t}},{test:[/chromium/i],describe:function(e){var t={name:"Chromium"},r=i.default.getFirstMatch(/(?:chromium)[\s/](\d+(\.?_?\d+)+)/i,e)||i.default.getFirstMatch(s,e);return r&&(t.version=r),t}},{test:[/chrome|crios|crmo/i],describe:function(e){var t={name:"Chrome"},r=i.default.getFirstMatch(/(?:chrome|crios|crmo)\/(\d+(\.?_?\d+)+)/i,e);return r&&(t.version=r),t}},{test:[/GSA/i],describe:function(e){var t={name:"Google Search"},r=i.default.getFirstMatch(/(?:GSA)\/(\d+(\.?_?\d+)+)/i,e);return r&&(t.version=r),t}},{test:function(e){var t=!e.test(/like android/i),r=e.test(/android/i);return t&&r},describe:function(e){var t={name:"Android Browser"},r=i.default.getFirstMatch(s,e);return r&&(t.version=r),t}},{test:[/playstation 4/i],describe:function(e){var t={name:"PlayStation 4"},r=i.default.getFirstMatch(s,e);return r&&(t.version=r),t}},{test:[/safari|applewebkit/i],describe:function(e){var t={name:"Safari"},r=i.default.getFirstMatch(s,e);return r&&(t.version=r),t}},{test:[/.*/i],describe:function(e){var t=-1!==e.search("\\(")?/^(.*)\/(.*)[ \t]\((.*)/:/^(.*)\/(.*) /;return{name:i.default.getFirstMatch(t,e),version:i.default.getSecondMatch(t,e)}}}];t.default=a,e.exports=t.default},93:function(e,t,r){"use strict";t.__esModule=!0,t.default=void 0;var n,i=(n=r(17))&&n.__esModule?n:{default:n},s=r(18);var a=[{test:[/Roku\/DVP/],describe:function(e){var t=i.default.getFirstMatch(/Roku\/DVP-(\d+\.\d+)/i,e);return{name:s.OS_MAP.Roku,version:t}}},{test:[/windows phone/i],describe:function(e){var t=i.default.getFirstMatch(/windows phone (?:os)?\s?(\d+(\.\d+)*)/i,e);return{name:s.OS_MAP.WindowsPhone,version:t}}},{test:[/windows /i],describe:function(e){var t=i.default.getFirstMatch(/Windows ((NT|XP)( \d\d?.\d)?)/i,e),r=i.default.getWindowsVersionName(t);return{name:s.OS_MAP.Windows,version:t,versionName:r}}},{test:[/Macintosh(.*?) FxiOS(.*?)\//],describe:function(e){var t={name:s.OS_MAP.iOS},r=i.default.getSecondMatch(/(Version\/)(\d[\d.]+)/,e);return r&&(t.version=r),t}},{test:[/macintosh/i],describe:function(e){var t=i.default.getFirstMatch(/mac os x (\d+(\.?_?\d+)+)/i,e).replace(/[_\s]/g,"."),r=i.default.getMacOSVersionName(t),n={name:s.OS_MAP.MacOS,version:t};return r&&(n.versionName=r),n}},{test:[/(ipod|iphone|ipad)/i],describe:function(e){var t=i.default.getFirstMatch(/os (\d+([_\s]\d+)*) like mac os x/i,e).replace(/[_\s]/g,".");return{name:s.OS_MAP.iOS,version:t}}},{test:function(e){var t=!e.test(/like android/i),r=e.test(/android/i);return t&&r},describe:function(e){var t=i.default.getFirstMatch(/android[\s/-](\d+(\.\d+)*)/i,e),r=i.default.getAndroidVersionName(t),n={name:s.OS_MAP.Android,version:t};return r&&(n.versionName=r),n}},{test:[/(web|hpw)[o0]s/i],describe:function(e){var t=i.default.getFirstMatch(/(?:web|hpw)[o0]s\/(\d+(\.\d+)*)/i,e),r={name:s.OS_MAP.WebOS};return t&&t.length&&(r.version=t),r}},{test:[/blackberry|\bbb\d+/i,/rim\stablet/i],describe:function(e){var t=i.default.getFirstMatch(/rim\stablet\sos\s(\d+(\.\d+)*)/i,e)||i.default.getFirstMatch(/blackberry\d+\/(\d+([_\s]\d+)*)/i,e)||i.default.getFirstMatch(/\bbb(\d+)/i,e);return{name:s.OS_MAP.BlackBerry,version:t}}},{test:[/bada/i],describe:function(e){var t=i.default.getFirstMatch(/bada\/(\d+(\.\d+)*)/i,e);return{name:s.OS_MAP.Bada,version:t}}},{test:[/tizen/i],describe:function(e){var t=i.default.getFirstMatch(/tizen[/\s](\d+(\.\d+)*)/i,e);return{name:s.OS_MAP.Tizen,version:t}}},{test:[/linux/i],describe:function(){return{name:s.OS_MAP.Linux}}},{test:[/CrOS/],describe:function(){return{name:s.OS_MAP.ChromeOS}}},{test:[/PlayStation 4/],describe:function(e){var t=i.default.getFirstMatch(/PlayStation 4[/\s](\d+(\.\d+)*)/i,e);return{name:s.OS_MAP.PlayStation4,version:t}}}];t.default=a,e.exports=t.default},94:function(e,t,r){"use strict";t.__esModule=!0,t.default=void 0;var n,i=(n=r(17))&&n.__esModule?n:{default:n},s=r(18);var a=[{test:[/googlebot/i],describe:function(){return{type:"bot",vendor:"Google"}}},{test:[/huawei/i],describe:function(e){var t=i.default.getFirstMatch(/(can-l01)/i,e)&&"Nova",r={type:s.PLATFORMS_MAP.mobile,vendor:"Huawei"};return t&&(r.model=t),r}},{test:[/nexus\s*(?:7|8|9|10).*/i],describe:function(){return{type:s.PLATFORMS_MAP.tablet,vendor:"Nexus"}}},{test:[/ipad/i],describe:function(){return{type:s.PLATFORMS_MAP.tablet,vendor:"Apple",model:"iPad"}}},{test:[/Macintosh(.*?) FxiOS(.*?)\//],describe:function(){return{type:s.PLATFORMS_MAP.tablet,vendor:"Apple",model:"iPad"}}},{test:[/kftt build/i],describe:function(){return{type:s.PLATFORMS_MAP.tablet,vendor:"Amazon",model:"Kindle Fire HD 7"}}},{test:[/silk/i],describe:function(){return{type:s.PLATFORMS_MAP.tablet,vendor:"Amazon"}}},{test:[/tablet(?! pc)/i],describe:function(){return{type:s.PLATFORMS_MAP.tablet}}},{test:function(e){var t=e.test(/ipod|iphone/i),r=e.test(/like (ipod|iphone)/i);return t&&!r},describe:function(e){var t=i.default.getFirstMatch(/(ipod|iphone)/i,e);return{type:s.PLATFORMS_MAP.mobile,vendor:"Apple",model:t}}},{test:[/nexus\s*[0-6].*/i,/galaxy nexus/i],describe:function(){return{type:s.PLATFORMS_MAP.mobile,vendor:"Nexus"}}},{test:[/[^-]mobi/i],describe:function(){return{type:s.PLATFORMS_MAP.mobile}}},{test:function(e){return"blackberry"===e.getBrowserName(!0)},describe:function(){return{type:s.PLATFORMS_MAP.mobile,vendor:"BlackBerry"}}},{test:function(e){return"bada"===e.getBrowserName(!0)},describe:function(){return{type:s.PLATFORMS_MAP.mobile}}},{test:function(e){return"windows phone"===e.getBrowserName()},describe:function(){return{type:s.PLATFORMS_MAP.mobile,vendor:"Microsoft"}}},{test:function(e){var t=Number(String(e.getOSVersion()).split(".")[0]);return"android"===e.getOSName(!0)&&t>=3},describe:function(){return{type:s.PLATFORMS_MAP.tablet}}},{test:function(e){return"android"===e.getOSName(!0)},describe:function(){return{type:s.PLATFORMS_MAP.mobile}}},{test:function(e){return"macos"===e.getOSName(!0)},describe:function(){return{type:s.PLATFORMS_MAP.desktop,vendor:"Apple"}}},{test:function(e){return"windows"===e.getOSName(!0)},describe:function(){return{type:s.PLATFORMS_MAP.desktop}}},{test:function(e){return"linux"===e.getOSName(!0)},describe:function(){return{type:s.PLATFORMS_MAP.desktop}}},{test:function(e){return"playstation 4"===e.getOSName(!0)},describe:function(){return{type:s.PLATFORMS_MAP.tv}}},{test:function(e){return"roku"===e.getOSName(!0)},describe:function(){return{type:s.PLATFORMS_MAP.tv}}}];t.default=a,e.exports=t.default},95:function(e,t,r){"use strict";t.__esModule=!0,t.default=void 0;var n,i=(n=r(17))&&n.__esModule?n:{default:n},s=r(18);var a=[{test:function(e){return"microsoft edge"===e.getBrowserName(!0)},describe:function(e){if(/\sedg\//i.test(e))return{name:s.ENGINE_MAP.Blink};var t=i.default.getFirstMatch(/edge\/(\d+(\.?_?\d+)+)/i,e);return{name:s.ENGINE_MAP.EdgeHTML,version:t}}},{test:[/trident/i],describe:function(e){var t={name:s.ENGINE_MAP.Trident},r=i.default.getFirstMatch(/trident\/(\d+(\.?_?\d+)+)/i,e);return r&&(t.version=r),t}},{test:function(e){return e.test(/presto/i)},describe:function(e){var t={name:s.ENGINE_MAP.Presto},r=i.default.getFirstMatch(/presto\/(\d+(\.?_?\d+)+)/i,e);return r&&(t.version=r),t}},{test:function(e){var t=e.test(/gecko/i),r=e.test(/like gecko/i);return t&&!r},describe:function(e){var t={name:s.ENGINE_MAP.Gecko},r=i.default.getFirstMatch(/gecko\/(\d+(\.?_?\d+)+)/i,e);return r&&(t.version=r),t}},{test:[/(apple)?webkit\/537\.36/i],describe:function(){return{name:s.ENGINE_MAP.Blink}}},{test:[/(apple)?webkit/i],describe:function(e){var t={name:s.ENGINE_MAP.WebKit},r=i.default.getFirstMatch(/webkit\/(\d+(\.?_?\d+)+)/i,e);return r&&(t.version=r),t}}];t.default=a,e.exports=t.default}})}));

/***/ }),

/***/ 8178:
/***/ (function(__unused_webpack_module, exports) {

!function(g,c){ true?c(exports):0}(this,function(g){const c=Symbol("newer"),e=Symbol("older");class n{constructor(a,b){typeof a!=="number"&&(b=a,a=0),this.size=0,this.limit=a,this.oldest=this.newest=void 0,this._keymap=new Map(),b&&(this.assign(b),a<1&&(this.limit=this.size))}_markEntryAsUsed(a){if(a===this.newest)return;a[c]&&(a===this.oldest&&(this.oldest=a[c]),a[c][e]=a[e]),a[e]&&(a[e][c]=a[c]),a[c]=void 0,a[e]=this.newest,this.newest&&(this.newest[c]=a),this.newest=a}assign(a){let b,d=this.limit||Number.MAX_VALUE;this._keymap.clear();let m=a[Symbol.iterator]();for(let h=m.next();!h.done;h=m.next()){let f=new l(h.value[0],h.value[1]);this._keymap.set(f.key,f),b?(b[c]=f,f[e]=b):this.oldest=f,b=f;if(d--==0)throw new Error("overflow")}this.newest=b,this.size=this._keymap.size}get(a){var b=this._keymap.get(a);return b?(this._markEntryAsUsed(b),b.value):void 0}set(a,b){var d=this._keymap.get(a);return d?(d.value=b,this._markEntryAsUsed(d),this):(this._keymap.set(a,d=new l(a,b)),this.newest?(this.newest[c]=d,d[e]=this.newest):this.oldest=d,this.newest=d,++this.size,this.size>this.limit&&this.shift(),this)}shift(){var a=this.oldest;if(a)return this.oldest[c]?(this.oldest=this.oldest[c],this.oldest[e]=void 0):(this.oldest=void 0,this.newest=void 0),a[c]=a[e]=void 0,this._keymap.delete(a.key),--this.size,[a.key,a.value]}find(a){let b=this._keymap.get(a);return b?b.value:void 0}has(a){return this._keymap.has(a)}delete(a){var b=this._keymap.get(a);return b?(this._keymap.delete(b.key),b[c]&&b[e]?(b[e][c]=b[c],b[c][e]=b[e]):b[c]?(b[c][e]=void 0,this.oldest=b[c]):b[e]?(b[e][c]=void 0,this.newest=b[e]):this.oldest=this.newest=void 0,this.size--,b.value):void 0}clear(){this.oldest=this.newest=void 0,this.size=0,this._keymap.clear()}keys(){return new j(this.oldest)}values(){return new k(this.oldest)}entries(){return this}[Symbol.iterator](){return new i(this.oldest)}forEach(a,b){typeof b!=="object"&&(b=this);let d=this.oldest;for(;d;)a.call(b,d.value,d.key,this),d=d[c]}toJSON(){for(var a=new Array(this.size),b=0,d=this.oldest;d;)a[b++]={key:d.key,value:d.value},d=d[c];return a}toString(){for(var a="",b=this.oldest;b;)a+=String(b.key)+":"+b.value,b=b[c],b&&(a+=" < ");return a}}g.LRUMap=n;function l(a,b){this.key=a,this.value=b,this[c]=void 0,this[e]=void 0}function i(a){this.entry=a}i.prototype[Symbol.iterator]=function(){return this},i.prototype.next=function(){let a=this.entry;return a?(this.entry=a[c],{done:!1,value:[a.key,a.value]}):{done:!0,value:void 0}};function j(a){this.entry=a}j.prototype[Symbol.iterator]=function(){return this},j.prototype.next=function(){let a=this.entry;return a?(this.entry=a[c],{done:!1,value:a.key}):{done:!0,value:void 0}};function k(a){this.entry=a}k.prototype[Symbol.iterator]=function(){return this},k.prototype.next=function(){let a=this.entry;return a?(this.entry=a[c],{done:!1,value:a.value}):{done:!0,value:void 0}}});


/***/ }),

/***/ 48514:
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";

// EXPORTS
__webpack_require__.d(__webpack_exports__, {
  "ge": () => (/* binding */ es6_getDomain),
  "Fo": () => (/* binding */ getHostname),
  "cH": () => (/* binding */ getPublicSuffix),
  "Qc": () => (/* binding */ parse)
});

// UNUSED EXPORTS: getDomainWithoutSuffix, getSubdomain

;// CONCATENATED MODULE: ./node_modules/.pnpm/tldts-core@6.1.61/node_modules/tldts-core/dist/es6/src/domain.js
/**
 * 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
    const publicSuffixIndex = hostname.length - publicSuffix.length - 2;
    const 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(suffix, hostname, options) {
    // Check if `hostname` ends with a member of `validHosts`.
    if (options.validHosts !== null) {
        const validHosts = options.validHosts;
        for (const vhost of validHosts) {
            if ( /*@__INLINE__*/shareSameDomainSuffix(hostname, vhost)) {
                return vhost;
            }
        }
    }
    let numberOfLeadingDots = 0;
    if (hostname.startsWith('.')) {
        while (numberOfLeadingDots < hostname.length &&
            hostname[numberOfLeadingDots] === '.') {
            numberOfLeadingDots += 1;
        }
    }
    // 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 - numberOfLeadingDots) {
        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);
}

;// CONCATENATED MODULE: ./node_modules/.pnpm/tldts-core@6.1.61/node_modules/tldts-core/dist/es6/src/domain-without-suffix.js
/**
 * 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);
}

;// CONCATENATED MODULE: ./node_modules/.pnpm/tldts-core@6.1.61/node_modules/tldts-core/dist/es6/src/extract-hostname.js
/**
 * @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) {
    let start = 0;
    let end = url.length;
    let hasUpper = false;
    // If url is not already a valid hostname, then try to extract hostname.
    if (!urlIsValidHostname) {
        // Special handling of data URLs
        if (url.startsWith('data:')) {
            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 {
            const 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.
                const protocolSize = indexOfProtocol - start;
                const c0 = url.charCodeAt(start);
                const c1 = url.charCodeAt(start + 1);
                const c2 = url.charCodeAt(start + 2);
                const c3 = url.charCodeAt(start + 3);
                const c4 = url.charCodeAt(start + 4);
                if (protocolSize === 5 &&
                    c0 === 104 /* 'h' */ &&
                    c1 === 116 /* 't' */ &&
                    c2 === 116 /* 't' */ &&
                    c3 === 112 /* 'p' */ &&
                    c4 === 115 /* 's' */) {
                    // https
                }
                else if (protocolSize === 4 &&
                    c0 === 104 /* 'h' */ &&
                    c1 === 116 /* 't' */ &&
                    c2 === 116 /* 't' */ &&
                    c3 === 112 /* 'p' */) {
                    // http
                }
                else if (protocolSize === 3 &&
                    c0 === 119 /* 'w' */ &&
                    c1 === 115 /* 's' */ &&
                    c2 === 115 /* 's' */) {
                    // wss
                }
                else if (protocolSize === 2 &&
                    c0 === 119 /* 'w' */ &&
                    c1 === 115 /* 's' */) {
                    // ws
                }
                else {
                    // Check that scheme is valid
                    for (let i = start; i < indexOfProtocol; i += 1) {
                        const lowerCaseCode = url.charCodeAt(i) | 32;
                        if (!(((lowerCaseCode >= 97 && lowerCaseCode <= 122) || // [a, z]
                            (lowerCaseCode >= 48 && lowerCaseCode <= 57) || // [0, 9]
                            lowerCaseCode === 46 || // '.'
                            lowerCaseCode === 45 || // '-'
                            lowerCaseCode === 43) // '+'
                        )) {
                            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.
        let indexOfIdentifier = -1;
        let indexOfClosingBracket = -1;
        let indexOfPort = -1;
        for (let i = start; i < end; i += 1) {
            const 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;
    }
    const hostname = start !== 0 || end !== url.length ? url.slice(start, end) : url;
    if (hasUpper) {
        return hostname.toLowerCase();
    }
    return hostname;
}

;// CONCATENATED MODULE: ./node_modules/.pnpm/tldts-core@6.1.61/node_modules/tldts-core/dist/es6/src/is-ip.js
/**
 * 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;
    }
    let numberOfDots = 0;
    for (let i = 0; i < hostname.length; i += 1) {
        const 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;
    }
    let start = hostname.startsWith('[') ? 1 : 0;
    let 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;
    }
    let hasColon = false;
    for (; start < end; start += 1) {
        const 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
        )) {
            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(hostname) {
    return isProbablyIpv6(hostname) || isProbablyIpv4(hostname);
}

;// CONCATENATED MODULE: ./node_modules/.pnpm/tldts-core@6.1.61/node_modules/tldts-core/dist/es6/src/is-valid.js
/**
 * 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.
 */
/* harmony default export */ function is_valid(hostname) {
    if (hostname.length > 255) {
        return false;
    }
    if (hostname.length === 0) {
        return false;
    }
    if (
    /*@__INLINE__*/ !isValidAscii(hostname.charCodeAt(0)) &&
        hostname.charCodeAt(0) !== 46 && // '.' (dot)
        hostname.charCodeAt(0) !== 95 // '_' (underscore)
    ) {
        return false;
    }
    // Validate hostname according to RFC
    let lastDotIndex = -1;
    let lastCharCode = -1;
    const len = hostname.length;
    for (let i = 0; i < len; i += 1) {
        const 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))) {
            // 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);
}

;// CONCATENATED MODULE: ./node_modules/.pnpm/tldts-core@6.1.61/node_modules/tldts-core/dist/es6/src/options.js
function setDefaultsImpl({ allowIcannDomains = true, allowPrivateDomains = false, detectIp = true, extractHostname = true, mixedInputs = true, validHosts = null, validateHostname = true, }) {
    return {
        allowIcannDomains,
        allowPrivateDomains,
        detectIp,
        extractHostname,
        mixedInputs,
        validHosts,
        validateHostname,
    };
}
const DEFAULT_OPTIONS = /*@__INLINE__*/ setDefaultsImpl({});
function setDefaults(options) {
    if (options === undefined) {
        return DEFAULT_OPTIONS;
    }
    return /*@__INLINE__*/ setDefaultsImpl(options);
}

;// CONCATENATED MODULE: ./node_modules/.pnpm/tldts-core@6.1.61/node_modules/tldts-core/dist/es6/src/subdomain.js
/**
 * 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);
}

;// CONCATENATED MODULE: ./node_modules/.pnpm/tldts-core@6.1.61/node_modules/tldts-core/dist/es6/src/factory.js
/**
 * 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 factory_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 factory_parseImpl(url, step, suffixLookup, partialOptions, result) {
    const 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) {
        result.hostname = url;
    }
    else if (options.mixedInputs) {
        result.hostname = extractHostname(url, is_valid(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) {
        result.isIp = isIp(result.hostname);
        if (result.isIp) {
            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 &&
        options.extractHostname &&
        !is_valid(result.hostname)) {
        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(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;
}

;// CONCATENATED MODULE: ./node_modules/.pnpm/tldts-core@6.1.61/node_modules/tldts-core/dist/es6/src/lookup/fast-path.js
/* harmony default export */ function fast_path(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 && hostname.length > 3) {
        const last = hostname.length - 1;
        const c3 = hostname.charCodeAt(last);
        const c2 = hostname.charCodeAt(last - 1);
        const c1 = hostname.charCodeAt(last - 2);
        const 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;
}

;// CONCATENATED MODULE: ./node_modules/.pnpm/tldts-core@6.1.61/node_modules/tldts-core/dist/es6/index.js




;// CONCATENATED MODULE: ./node_modules/.pnpm/tldts@6.1.61/node_modules/tldts/dist/es6/src/data/trie.js
const exceptions = (function () {
    const _0 = [1, {}], _1 = [0, { "city": _0 }];
    const exceptions = [0, { "ck": [0, { "www": _0 }], "jp": [0, { "kawasaki": _1, "kitakyushu": _1, "kobe": _1, "nagoya": _1, "sapporo": _1, "sendai": _1, "yokohama": _1 }] }];
    return exceptions;
})();
const rules = (function () {
    const _2 = [1, {}], _3 = [2, {}], _4 = [1, { "gov": _2, "com": _2, "org": _2, "net": _2, "edu": _2 }], _5 = [0, { "*": _3 }], _6 = [0, { "relay": _3 }], _7 = [2, { "id": _3 }], _8 = [1, { "blogspot": _3 }], _9 = [1, { "gov": _2 }], _10 = [0, { "notebook": _3, "studio": _3 }], _11 = [0, { "labeling": _3, "notebook": _3, "studio": _3 }], _12 = [0, { "notebook": _3 }], _13 = [0, { "labeling": _3, "notebook": _3, "notebook-fips": _3, "studio": _3 }], _14 = [0, { "notebook": _3, "notebook-fips": _3, "studio": _3, "studio-fips": _3 }], _15 = [0, { "*": _2 }], _16 = [0, { "cloud": _3 }], _17 = [1, { "co": _3 }], _18 = [0, { "objects": _3 }], _19 = [2, { "nodes": _3 }], _20 = [0, { "my": _5 }], _21 = [0, { "s3": _3, "s3-accesspoint": _3, "s3-website": _3 }], _22 = [0, { "s3": _3, "s3-accesspoint": _3 }], _23 = [0, { "direct": _3 }], _24 = [0, { "webview-assets": _3 }], _25 = [0, { "vfs": _3, "webview-assets": _3 }], _26 = [0, { "execute-api": _3, "emrappui-prod": _3, "emrnotebooks-prod": _3, "emrstudio-prod": _3, "dualstack": _21, "s3": _3, "s3-accesspoint": _3, "s3-object-lambda": _3, "s3-website": _3, "aws-cloud9": _24, "cloud9": _25 }], _27 = [0, { "execute-api": _3, "emrappui-prod": _3, "emrnotebooks-prod": _3, "emrstudio-prod": _3, "dualstack": _22, "s3": _3, "s3-accesspoint": _3, "s3-object-lambda": _3, "s3-website": _3, "aws-cloud9": _24, "cloud9": _25 }], _28 = [0, { "execute-api": _3, "emrappui-prod": _3, "emrnotebooks-prod": _3, "emrstudio-prod": _3, "dualstack": _21, "s3": _3, "s3-accesspoint": _3, "s3-object-lambda": _3, "s3-website": _3, "analytics-gateway": _3, "aws-cloud9": _24, "cloud9": _25 }], _29 = [0, { "execute-api": _3, "emrappui-prod": _3, "emrnotebooks-prod": _3, "emrstudio-prod": _3, "dualstack": _21, "s3": _3, "s3-accesspoint": _3, "s3-object-lambda": _3, "s3-website": _3 }], _30 = [0, { "s3": _3, "s3-accesspoint": _3, "s3-accesspoint-fips": _3, "s3-fips": _3, "s3-website": _3 }], _31 = [0, { "execute-api": _3, "emrappui-prod": _3, "emrnotebooks-prod": _3, "emrstudio-prod": _3, "dualstack": _30, "s3": _3, "s3-accesspoint": _3, "s3-accesspoint-fips": _3, "s3-fips": _3, "s3-object-lambda": _3, "s3-website": _3, "aws-cloud9": _24, "cloud9": _25 }], _32 = [0, { "execute-api": _3, "emrappui-prod": _3, "emrnotebooks-prod": _3, "emrstudio-prod": _3, "dualstack": _30, "s3": _3, "s3-accesspoint": _3, "s3-accesspoint-fips": _3, "s3-deprecated": _3, "s3-fips": _3, "s3-object-lambda": _3, "s3-website": _3, "analytics-gateway": _3, "aws-cloud9": _24, "cloud9": _25 }], _33 = [0, { "s3": _3, "s3-accesspoint": _3, "s3-accesspoint-fips": _3, "s3-fips": _3 }], _34 = [0, { "execute-api": _3, "emrappui-prod": _3, "emrnotebooks-prod": _3, "emrstudio-prod": _3, "dualstack": _33, "s3": _3, "s3-accesspoint": _3, "s3-accesspoint-fips": _3, "s3-fips": _3, "s3-object-lambda": _3, "s3-website": _3 }], _35 = [0, { "auth": _3 }], _36 = [0, { "auth": _3, "auth-fips": _3 }], _37 = [0, { "apps": _3 }], _38 = [0, { "paas": _3 }], _39 = [2, { "eu": _3 }], _40 = [0, { "app": _3 }], _41 = [0, { "site": _3 }], _42 = [1, { "com": _2, "edu": _2, "net": _2, "org": _2 }], _43 = [0, { "j": _3 }], _44 = [0, { "p": _3 }], _45 = [0, { "user": _3 }], _46 = [0, { "shop": _3 }], _47 = [0, { "cust": _3, "reservd": _3 }], _48 = [0, { "cust": _3 }], _49 = [1, { "gov": _2, "edu": _2, "mil": _2, "com": _2, "org": _2, "net": _2 }], _50 = [0, { "s3": _3 }], _51 = [1, { "edu": _2, "biz": _2, "net": _2, "org": _2, "gov": _2, "info": _2, "com": _2 }], _52 = [1, { "framer": _3 }], _53 = [0, { "forgot": _3 }], _54 = [0, { "cdn": _3 }], _55 = [1, { "gs": _2 }], _56 = [0, { "nes": _2 }], _57 = [1, { "k12": _2, "cc": _2, "lib": _2 }], _58 = [1, { "cc": _2, "lib": _2 }];
    const rules = [0, { "ac": [1, { "com": _2, "edu": _2, "gov": _2, "net": _2, "mil": _2, "org": _2, "drr": _3, "feedback": _3, "forms": _3 }], "ad": [1, { "nom": _2 }], "ae": [1, { "co": _2, "net": _2, "org": _2, "sch": _2, "ac": _2, "gov": _2, "mil": _2, "blogspot": _3 }], "aero": [1, { "airline": _2, "airport": _2, "accident-investigation": _2, "accident-prevention": _2, "aerobatic": _2, "aeroclub": _2, "aerodrome": _2, "agents": _2, "air-surveillance": _2, "air-traffic-control": _2, "aircraft": _2, "airtraffic": _2, "ambulance": _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, "freight": _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, "marketplace": _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, "taxi": _2, "trader": _2, "trading": _2, "trainer": _2, "union": _2, "workinggroup": _2, "works": _2 }], "af": _4, "ag": [1, { "com": _2, "org": _2, "net": _2, "co": _2, "nom": _2 }], "ai": [1, { "off": _2, "com": _2, "net": _2, "org": _2, "uwu": _3, "framer": _3 }], "al": [1, { "com": _2, "edu": _2, "gov": _2, "mil": _2, "net": _2, "org": _2, "blogspot": _3 }], "am": [1, { "co": _2, "com": _2, "commune": _2, "net": _2, "org": _2, "radio": _3, "blogspot": _3 }], "ao": [1, { "ed": _2, "edu": _2, "gov": _2, "gv": _2, "og": _2, "org": _2, "co": _2, "pb": _2, "it": _2 }], "aq": _2, "ar": [1, { "bet": _2, "com": _8, "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, { "e164": _2, "home": _2, "in-addr": _2, "ip6": _2, "iris": _2, "uri": _2, "urn": _2 }], "as": _9, "asia": [1, { "cloudns": _3, "daemon": _3, "dix": _3 }], "at": [1, { "ac": [1, { "sth": _2 }], "co": _8, "gv": _2, "or": _2, "funkfeuer": [0, { "wien": _3 }], "futurecms": [0, { "*": _3, "ex": _5, "in": _5 }], "futurehosting": _3, "futuremailing": _3, "ortsinfo": [0, { "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, { "com": [1, { "blogspot": _3, "cloudlets": [0, { "mel": _3 }], "myspreadshop": _3 }], "net": _2, "org": _2, "edu": [1, { "act": _2, "catholic": _2, "nsw": [1, { "schools": _2 }], "nt": _2, "qld": _2, "sa": _2, "tas": _2, "vic": _2, "wa": _2 }], "gov": [1, { "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, { "com": _2 }], "ax": _2, "az": [1, { "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, { "com": _2, "edu": _2, "gov": _2, "mil": _2, "net": _2, "org": _2, "blogspot": _3, "rs": _3 }], "bb": [1, { "biz": _2, "co": _2, "com": _2, "edu": _2, "gov": _2, "info": _2, "net": _2, "org": _2, "store": _2, "tv": _2 }], "bd": _15, "be": [1, { "ac": _2, "cloudns": _3, "webhosting": _3, "blogspot": _3, "interhostsolutions": _16, "kuleuven": [0, { "ezproxy": _3 }], "123website": _3, "myspreadshop": _3, "transurl": _5 }], "bf": _9, "bg": [1, { "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, { "co": _2, "com": _2, "edu": _2, "or": _2, "org": _2 }], "biz": [1, { "activetrail": _3, "cloud-ip": _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, { "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, { "com": _2, "edu": _2, "gov": _2, "net": _2, "org": _2, "co": _3 }], "bo": [1, { "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, { "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, "bet": _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, { "blogspot": _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, { "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, { "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 }], "leilao": _2, "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": _15, "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, { "com": _2, "net": _2, "org": _2, "edu": _2, "gov": _2, "we": _3 }], "bt": _4, "bv": _2, "bw": [1, { "co": _2, "org": _2 }], "by": [1, { "gov": _2, "mil": _2, "com": _8, "of": _2, "mediatech": _3 }], "bz": [1, { "co": _2, "com": _2, "net": _2, "org": _2, "edu": _2, "gov": _2, "za": _3, "mydns": _3, "gsj": _3 }], "ca": [1, { "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, "box": _3 }], "cat": _2, "cc": [1, { "cleverapps": _3, "cloudns": _3, "ftpaccess": _3, "game-server": _3, "myphotos": _3, "scrapping": _3, "twmail": _3, "csx": _3, "fantasyleague": _3, "spawn": [0, { "instances": _3 }] }], "cd": _9, "cf": _8, "cg": _2, "ch": [1, { "square7": _3, "cloudns": _3, "cloudscale": [0, { "cust": _3, "lpg": _18, "rma": _18 }], "blogspot": _3, "flow": [0, { "ae": [0, { "alp1": _3 }], "appengine": _3 }], "linkyard-cloud": _3, "gotdns": _3, "dnsking": _3, "123website": _3, "myspreadshop": _3, "firenet": [0, { "*": _3, "svc": _5 }], "12hp": _3, "2ix": _3, "4lima": _3, "lima-city": _3 }], "ci": [1, { "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, "gouv": _2, "fin": _3 }], "ck": _15, "cl": [1, { "co": _2, "gob": _2, "gov": _2, "mil": _2, "cloudns": _3, "blogspot": _3 }], "cm": [1, { "co": _2, "com": _2, "gov": _2, "net": _2 }], "cn": [1, { "ac": _2, "com": [1, { "amazonaws": [0, { "cn-north-1": [0, { "execute-api": _3, "emrappui-prod": _3, "emrnotebooks-prod": _3, "emrstudio-prod": _3, "dualstack": _21, "s3": _3, "s3-accesspoint": _3, "s3-deprecated": _3, "s3-object-lambda": _3, "s3-website": _3 }], "cn-northwest-1": [0, { "execute-api": _3, "emrappui-prod": _3, "emrnotebooks-prod": _3, "emrstudio-prod": _3, "dualstack": _22, "s3": _3, "s3-accesspoint": _3, "s3-object-lambda": _3, "s3-website": _3 }], "compute": _5, "airflow": [0, { "cn-north-1": _5, "cn-northwest-1": _5 }], "eb": [0, { "cn-north-1": _3, "cn-northwest-1": _3 }], "elb": _5 }], "sagemaker": [0, { "cn-north-1": _10, "cn-northwest-1": _10 }] }], "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": [1, { "as": _3 }], "sn": _2, "sx": _2, "tj": _2, "xj": _2, "xz": _2, "yn": _2, "zj": _2, "hk": _2, "mo": _2, "tw": _2, "canva-apps": _3, "canvasite": _20, "myqnapcloud": _3, "quickconnect": _23 }], "co": [1, { "arts": _2, "com": _8, "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, "xmit": _5, "firewalledreplit": _7, "repl": _7, "supabase": _3 }], "com": [1, { "a2hosted": _3, "cpserver": _3, "adobeaemcloud": [2, { "dev": _5 }], "africa": _3, "airkitapps": _3, "airkitapps-au": _3, "aivencloud": _3, "kasserver": _3, "amazonaws": [0, { "af-south-1": _26, "ap-east-1": _27, "ap-northeast-1": _28, "ap-northeast-2": _28, "ap-northeast-3": _26, "ap-south-1": _28, "ap-south-2": _29, "ap-southeast-1": _28, "ap-southeast-2": _28, "ap-southeast-3": _29, "ap-southeast-4": _29, "ap-southeast-5": [0, { "execute-api": _3, "dualstack": _21, "s3": _3, "s3-accesspoint": _3, "s3-deprecated": _3, "s3-object-lambda": _3, "s3-website": _3 }], "ca-central-1": _31, "ca-west-1": [0, { "execute-api": _3, "emrappui-prod": _3, "emrnotebooks-prod": _3, "emrstudio-prod": _3, "dualstack": _30, "s3": _3, "s3-accesspoint": _3, "s3-accesspoint-fips": _3, "s3-fips": _3, "s3-object-lambda": _3, "s3-website": _3 }], "eu-central-1": _28, "eu-central-2": _29, "eu-north-1": _27, "eu-south-1": _26, "eu-south-2": _29, "eu-west-1": [0, { "execute-api": _3, "emrappui-prod": _3, "emrnotebooks-prod": _3, "emrstudio-prod": _3, "dualstack": _21, "s3": _3, "s3-accesspoint": _3, "s3-deprecated": _3, "s3-object-lambda": _3, "s3-website": _3, "analytics-gateway": _3, "aws-cloud9": _24, "cloud9": _25 }], "eu-west-2": _27, "eu-west-3": _26, "il-central-1": [0, { "execute-api": _3, "emrappui-prod": _3, "emrnotebooks-prod": _3, "emrstudio-prod": _3, "dualstack": _21, "s3": _3, "s3-accesspoint": _3, "s3-object-lambda": _3, "s3-website": _3, "aws-cloud9": _24, "cloud9": [0, { "vfs": _3 }] }], "me-central-1": _29, "me-south-1": _27, "sa-east-1": _26, "us-east-1": [2, { "execute-api": _3, "emrappui-prod": _3, "emrnotebooks-prod": _3, "emrstudio-prod": _3, "dualstack": _30, "s3": _3, "s3-accesspoint": _3, "s3-accesspoint-fips": _3, "s3-deprecated": _3, "s3-fips": _3, "s3-object-lambda": _3, "s3-website": _3, "analytics-gateway": _3, "aws-cloud9": _24, "cloud9": _25 }], "us-east-2": _32, "us-gov-east-1": _34, "us-gov-west-1": _34, "us-west-1": _31, "us-west-2": _32, "compute": _5, "compute-1": _5, "airflow": [0, { "af-south-1": _5, "ap-east-1": _5, "ap-northeast-1": _5, "ap-northeast-2": _5, "ap-northeast-3": _5, "ap-south-1": _5, "ap-south-2": _5, "ap-southeast-1": _5, "ap-southeast-2": _5, "ap-southeast-3": _5, "ap-southeast-4": _5, "ca-central-1": _5, "ca-west-1": _5, "eu-central-1": _5, "eu-central-2": _5, "eu-north-1": _5, "eu-south-1": _5, "eu-south-2": _5, "eu-west-1": _5, "eu-west-2": _5, "eu-west-3": _5, "il-central-1": _5, "me-central-1": _5, "me-south-1": _5, "sa-east-1": _5, "us-east-1": _5, "us-east-2": _5, "us-west-1": _5, "us-west-2": _5 }], "s3": _3, "s3-1": _3, "s3-ap-east-1": _3, "s3-ap-northeast-1": _3, "s3-ap-northeast-2": _3, "s3-ap-northeast-3": _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-north-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-east-1": _3, "s3-fips-us-gov-west-1": _3, "s3-global": [0, { "accesspoint": [0, { "mrap": _3 }] }], "s3-me-south-1": _3, "s3-sa-east-1": _3, "s3-us-east-2": _3, "s3-us-gov-east-1": _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-gov-west-1": _3, "s3-website-us-west-1": _3, "s3-website-us-west-2": _3, "elb": _5 }], "amazoncognito": [0, { "af-south-1": _35, "ap-east-1": _35, "ap-northeast-1": _35, "ap-northeast-2": _35, "ap-northeast-3": _35, "ap-south-1": _35, "ap-south-2": _35, "ap-southeast-1": _35, "ap-southeast-2": _35, "ap-southeast-3": _35, "ap-southeast-4": _35, "ca-central-1": _35, "ca-west-1": _35, "eu-central-1": _35, "eu-central-2": _35, "eu-north-1": _35, "eu-south-1": _35, "eu-south-2": _35, "eu-west-1": _35, "eu-west-2": _35, "eu-west-3": _35, "il-central-1": _35, "me-central-1": _35, "me-south-1": _35, "sa-east-1": _35, "us-east-1": _36, "us-east-2": _36, "us-gov-west-1": [0, { "auth-fips": _3 }], "us-west-1": _36, "us-west-2": _36 }], "amplifyapp": _3, "awsapprunner": _5, "awsapps": _3, "elasticbeanstalk": [2, { "af-south-1": _3, "ap-east-1": _3, "ap-northeast-1": _3, "ap-northeast-2": _3, "ap-northeast-3": _3, "ap-south-1": _3, "ap-southeast-1": _3, "ap-southeast-2": _3, "ap-southeast-3": _3, "ca-central-1": _3, "eu-central-1": _3, "eu-north-1": _3, "eu-south-1": _3, "eu-west-1": _3, "eu-west-2": _3, "eu-west-3": _3, "il-central-1": _3, "me-south-1": _3, "sa-east-1": _3, "us-east-1": _3, "us-east-2": _3, "us-gov-east-1": _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, "cdn77-storage": _3, "br": _3, "cn": _3, "de": _3, "eu": _3, "jpn": _3, "mex": _3, "ru": _3, "sa": _3, "uk": _3, "us": _3, "za": _3, "clever-cloud": [0, { "services": _5 }], "dnsabr": _3, "ip-ddns": _3, "jdevcloud": _3, "wpdevcloud": _3, "cf-ipfs": _3, "cloudflare-ipfs": _3, "trycloudflare": _3, "co": _3, "builtwithdark": _3, "datadetect": [0, { "demo": _3, "instance": _3 }], "dattolocal": _3, "dattorelay": _3, "dattoweb": _3, "mydatto": _3, "digitaloceanspaces": _5, "discordsays": _3, "discordsez": _3, "drayddns": _3, "dreamhosters": _3, "durumis": _3, "mydrobo": _3, "blogdns": _3, "cechire": _3, "dnsalias": _3, "dnsdojo": _3, "doesntexist": _3, "dontexist": _3, "doomdns": _3, "dyn-o-saur": _3, "dynalias": _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, "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, "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, { "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, "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, "aliases121": _3, "gentapps": _3, "gentlentapis": _3, "githubusercontent": _3, "0emm": _5, "appspot": [2, { "r": _5 }], "blogspot": _3, "codespot": _3, "googleapis": _3, "googlecode": _3, "pagespeedmobilizer": _3, "withgoogle": _3, "withyoutube": _3, "grayjayleagues": _3, "hatenablog": _3, "hatenadiary": _3, "herokuapp": _3, "herokussl": _3, "gr": _3, "smushcdn": _3, "wphostedmail": _3, "wpmucdn": _3, "pixolino": _3, "apps-1and1": _3, "live-website": _3, "dopaas": _3, "hosted-by-previder": _38, "hosteur": [0, { "rag-cloud": _3, "rag-cloud-ch": _3 }], "ik-server": [0, { "jcloud": _3, "jcloud-ver-jpc": _3 }], "jelastic": [0, { "demo": _3 }], "massivegrid": _38, "wafaicloud": [0, { "jed": _3, "ryd": _3 }], "webadorsite": _3, "joyent": [0, { "cns": _5 }], "lpusercontent": _3, "linode": [0, { "members": _3, "nodebalancer": _5 }], "linodeobjects": _5, "linodeusercontent": [0, { "ip": _3 }], "barsycenter": _3, "barsyonline": _3, "modelscape": _3, "mwcloudnonprod": _3, "polyspace": _3, "mazeplay": _3, "miniserver": _3, "atmeta": _3, "fbsbx": _37, "meteorapp": _39, "routingthecloud": _3, "mydbserver": _3, "hostedpi": _3, "mythic-beasts": [0, { "caracal": _3, "customer": _3, "fentiger": _3, "lynx": _3, "ocelot": _3, "oncilla": _3, "onza": _3, "sphinx": _3, "vs": _3, "x": _3, "yali": _3 }], "nospamproxy": _16, "4u": _3, "nfshost": _3, "3utilities": _3, "blogsyte": _3, "ciscofreak": _3, "damnserver": _3, "ddnsking": _3, "ditchyourip": _3, "dnsiskinky": _3, "dynns": _3, "geekgalaxy": _3, "health-carereform": _3, "homesecuritymac": _3, "homesecuritypc": _3, "myactivedirectory": _3, "mysecuritycamera": _3, "myvnc": _3, "net-freaks": _3, "onthewifi": _3, "point2this": _3, "quicksytes": _3, "securitytactics": _3, "servebeer": _3, "servecounterstrike": _3, "serveexchange": _3, "serveftp": _3, "servegame": _3, "servehalflife": _3, "servehttp": _3, "servehumour": _3, "serveirc": _3, "servemp3": _3, "servep2p": _3, "servepics": _3, "servequake": _3, "servesarcasm": _3, "stufftoread": _3, "unusualperson": _3, "workisboring": _3, "001www": _3, "myiphost": _3, "observableusercontent": [0, { "static": _3 }], "simplesite": _3, "orsites": _3, "operaunite": _3, "customer-oci": [0, { "*": _3, "oci": _5, "ocp": _5, "ocs": _5 }], "oraclecloudapps": _5, "oraclegovcloudapps": _5, "authgear-staging": _3, "authgearapps": _3, "skygearapp": _3, "outsystemscloud": _3, "ownprovider": _3, "pgfog": _3, "pagexl": _3, "gotpantheon": _3, "paywhirl": _5, "upsunapp": _3, "platter-app": _3, "postman-echo": _3, "prgmr": [0, { "xen": _3 }], "pythonanywhere": _39, "qa2": _3, "alpha-myqnapcloud": _3, "dev-myqnapcloud": _3, "mycloudnas": _3, "mynascloud": _3, "myqnapcloud": _3, "qualifioapp": _3, "ladesk": _3, "qbuser": _3, "quipelements": _5, "rackmaze": _3, "readthedocs-hosted": _3, "rhcloud": _3, "onrender": _3, "render": _40, "180r": _3, "dojin": _3, "sakuratan": _3, "sakuraweb": _3, "x0": _3, "code": [0, { "builder": _5, "dev-builder": _5, "stg-builder": _5 }], "salesforce": [0, { "platform": [0, { "code-builder-stg": [0, { "test": [0, { "001": _5 }] }] }] }], "logoip": _3, "scrysec": _3, "firewall-gateway": _3, "myshopblocks": _3, "myshopify": _3, "shopitsite": _3, "1kapp": _3, "appchizi": _3, "applinzi": _3, "sinaapp": _3, "vipsinaapp": _3, "streamlitapp": _3, "try-snowplow": _3, "playstation-cloud": _3, "myspreadshop": _3, "w-corp-staticblitz": _3, "w-credentialless-staticblitz": _3, "w-staticblitz": _3, "stackhero-network": _3, "stdlib": [0, { "api": _3 }], "strapiapp": [2, { "media": _3 }], "streak-link": _3, "streaklinks": _3, "streakusercontent": _3, "temp-dns": _3, "dsmynas": _3, "familyds": _3, "mytabit": _3, "taveusercontent": _3, "tb-hosting": _41, "reservd": _3, "thingdustdata": _3, "townnews-staging": _3, "typeform": [0, { "pro": _3 }], "hk": _3, "it": _3, "vultrobjects": _5, "wafflecell": _3, "hotelwithflight": _3, "reserve-online": _3, "cprapid": _3, "pleskns": _3, "remotewd": _3, "wiardweb": [0, { "pages": _3 }], "wixsite": _3, "wixstudio": _3, "messwithdns": _3, "woltlab-demo": _3, "wpenginepowered": [2, { "js": _3 }], "xnbay": [2, { "u2": _3, "u2-local": _3 }], "yolasite": _3 }], "coop": _2, "cr": [1, { "ac": _2, "co": _2, "ed": _2, "fi": _2, "go": _2, "or": _2, "sa": _2 }], "cu": [1, { "com": _2, "edu": _2, "gob": _2, "inf": _2, "nat": _2, "net": _2, "org": _2 }], "cv": [1, { "com": _2, "edu": _2, "int": _2, "nome": _2, "org": _2, "blogspot": _3 }], "cw": _42, "cx": [1, { "gov": _2, "cloudns": _3, "ath": _3, "info": _3, "assessments": _3, "calculators": _3, "funnels": _3, "paynow": _3, "quizzes": _3, "researched": _3, "tests": _3 }], "cy": [1, { "ac": _2, "biz": _2, "com": [1, { "blogspot": _3, "scaleforce": _43 }], "ekloges": _2, "gov": _2, "ltd": _2, "mil": _2, "net": _2, "org": _2, "press": _2, "pro": _2, "tm": _2 }], "cz": [1, { "contentproxy9": [0, { "rsc": _3 }], "realm": _3, "e4": _3, "blogspot": _3, "co": _3, "metacentrum": [0, { "cloud": _5, "custom": _3 }], "muni": [0, { "cloud": [0, { "flt": _3, "usr": _3 }] }] }], "de": [1, { "bplaced": _3, "square7": _3, "com": _3, "cosidns": [0, { "dyn": _3 }], "dnsupdater": _3, "dynamisches-dns": _3, "internet-dns": _3, "l-o-g-i-n": _3, "ddnss": [2, { "dyn": _3, "dyndns": _3 }], "dyn-ip24": _3, "dyndns1": _3, "home-webserver": [2, { "dyn": _3 }], "myhome-server": _3, "dnshome": _3, "fuettertdasnetz": _3, "isteingeek": _3, "istmein": _3, "lebtimnetz": _3, "leitungsen": _3, "traeumtgerade": _3, "frusky": _5, "goip": _3, "blogspot": _3, "xn--gnstigbestellen-zvb": _3, "günstigbestellen": _3, "xn--gnstigliefern-wob": _3, "günstigliefern": _3, "hs-heilbronn": [0, { "it": [0, { "pages": _3, "pages-research": _3 }] }], "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, "webspaceconfig": _3, "123webseite": _3, "logoip": _3, "firewall-gateway": _3, "my-gateway": _3, "my-router": _3, "spdns": _3, "speedpartner": [0, { "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, "virtual-user": _3, "virtualuser": _3, "community-pro": _3, "diskussionsbereich": _3 }], "dj": _2, "dk": [1, { "biz": _3, "co": _3, "firm": _3, "reg": _3, "store": _3, "blogspot": _3, "123hjemmeside": _3, "myspreadshop": _3 }], "dm": _4, "do": [1, { "art": _2, "com": _2, "edu": _2, "gob": _2, "gov": _2, "mil": _2, "net": _2, "org": _2, "sld": _2, "web": _2 }], "dz": [1, { "art": _2, "asso": _2, "com": _2, "edu": _2, "gov": _2, "org": _2, "net": _2, "pol": _2, "soc": _2, "tm": _2 }], "ec": [1, { "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, { "rit": [0, { "git-pages": _3 }] }], "ee": [1, { "edu": _2, "gov": _2, "riik": _2, "lib": _2, "med": _2, "com": _8, "pri": _2, "aip": _2, "org": _2, "fie": _2 }], "eg": [1, { "com": _8, "edu": _2, "eun": _2, "gov": _2, "mil": _2, "name": _2, "net": _2, "org": _2, "sci": _2 }], "er": _15, "es": [1, { "com": _8, "nom": _2, "org": _2, "gob": _2, "edu": _2, "123miweb": _3, "myspreadshop": _3 }], "et": [1, { "com": _2, "gov": _2, "org": _2, "edu": _2, "biz": _2, "name": _2, "info": _2, "net": _2 }], "eu": [1, { "airkitapps": _3, "cloudns": _3, "dogado": [0, { "jelastic": _3 }], "barsy": _3, "spdns": _3, "transurl": _5, "diskstation": _3 }], "fi": [1, { "aland": _2, "dy": _3, "blogspot": _3, "xn--hkkinen-5wa": _3, "häkkinen": _3, "iki": _3, "cloudplatform": [0, { "fi": _3 }], "datacenter": [0, { "demo": _3, "paas": _3 }], "kapsi": _3, "123kotisivu": _3, "myspreadshop": _3 }], "fj": [1, { "ac": _2, "biz": _2, "com": _2, "gov": _2, "info": _2, "mil": _2, "name": _2, "net": _2, "org": _2, "pro": _2 }], "fk": _15, "fm": [1, { "com": _2, "edu": _2, "net": _2, "org": _2, "radio": _3, "user": _5 }], "fo": _2, "fr": [1, { "asso": _2, "com": _2, "gouv": _2, "nom": _2, "prd": _2, "tm": _2, "avoues": _2, "cci": _2, "greta": _2, "huissier-justice": _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, "aeroport": _3, "avocat": _3, "chambagri": _3, "chirurgiens-dentistes": _3, "experts-comptables": _3, "medecin": _3, "notaires": _3, "pharmacien": _3, "port": _3, "veterinaire": _3, "myspreadshop": _3, "ynh": _3 }], "ga": _2, "gb": _2, "gd": [1, { "edu": _2, "gov": _2 }], "ge": [1, { "com": _2, "edu": _2, "gov": _2, "org": _2, "mil": _2, "net": _2, "pvt": _2 }], "gf": _2, "gg": [1, { "co": _2, "net": _2, "org": _2, "kaas": _3, "stackit": _3, "panel": [2, { "daemon": _3 }] }], "gh": [1, { "com": _2, "edu": _2, "gov": _2, "org": _2, "mil": _2 }], "gi": [1, { "com": _2, "ltd": _2, "gov": _2, "mod": _2, "edu": _2, "org": _2 }], "gl": [1, { "co": _2, "com": _2, "edu": _2, "net": _2, "org": _2, "biz": _3 }], "gm": _2, "gn": [1, { "ac": _2, "com": _2, "edu": _2, "gov": _2, "org": _2, "net": _2 }], "gov": _2, "gp": [1, { "com": _2, "net": _2, "mobi": _2, "edu": _2, "org": _2, "asso": _2 }], "gq": _2, "gr": [1, { "com": _2, "edu": _2, "net": _2, "org": _2, "gov": _2, "blogspot": _3, "barsy": _3, "simplesite": _3 }], "gs": _2, "gt": [1, { "com": _2, "edu": _2, "gob": _2, "ind": _2, "mil": _2, "net": _2, "org": _2 }], "gu": [1, { "com": _2, "edu": _2, "gov": _2, "guam": _2, "info": _2, "net": _2, "org": _2, "web": _2 }], "gw": _2, "gy": [1, { "co": _2, "com": _2, "edu": _2, "gov": _2, "net": _2, "org": _2 }], "hk": [1, { "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, "inc": _3, "ltd": _3 }], "hm": _2, "hn": [1, { "com": _2, "edu": _2, "org": _2, "net": _2, "mil": _2, "gob": _2 }], "hr": [1, { "iz": _2, "from": _2, "name": _2, "com": _2, "brendly": _46, "blogspot": _3, "free": _3 }], "ht": [1, { "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, "rt": _3 }], "hu": [1, { "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, { "ac": _2, "biz": _2, "co": _8, "desa": _2, "go": _2, "mil": _2, "my": [1, { "rss": _3 }], "net": _2, "or": _2, "ponpes": _2, "sch": _2, "web": _2 }], "ie": [1, { "gov": _2, "blogspot": _3, "myspreadshop": _3 }], "il": [1, { "ac": _2, "co": [1, { "blogspot": _3, "ravpage": _3, "mytabit": _3, "tabitorder": _3 }], "gov": _2, "idf": _2, "k12": _2, "muni": _2, "net": _2, "org": _2 }], "xn--4dbrk0ce": [1, { "xn--4dbgdty6c": _2, "xn--5dbhl8d": _2, "xn--8dbq2a": _2, "xn--hebda8b": _2 }], "ישראל": [1, { "אקדמיה": _2, "ישוב": _2, "צהל": _2, "ממשל": _2 }], "im": [1, { "ac": _2, "co": [1, { "ltd": _2, "plc": _2 }], "com": _2, "net": _2, "org": _2, "tt": _2, "tv": _2 }], "in": [1, { "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, "cloudns": _3, "blogspot": _3, "barsy": _3, "web": _3, "supabase": _3 }], "info": [1, { "cloudns": _3, "dynamic-dns": _3, "barrel-of-knowledge": _3, "barrell-of-knowledge": _3, "dyndns": _3, "for-our": _3, "groks-the": _3, "groks-this": _3, "here-for-more": _3, "knowsitall": _3, "selfip": _3, "webhop": _3, "barsy": _3, "mayfirst": _3, "mittwald": _3, "mittwaldserver": _3, "typo3server": _3, "dvrcam": _3, "ilovecollege": _3, "no-ip": _3, "forumz": _3, "nsupdate": _3, "dnsupdate": _3, "v-info": _3 }], "int": [1, { "eu": _2 }], "io": [1, { "2038": _3, "co": _2, "com": _2, "edu": _2, "gov": _2, "mil": _2, "net": _2, "nom": _2, "org": _2, "on-acorn": _5, "apigee": _3, "b-data": _3, "beagleboard": _3, "bitbucket": _3, "bluebite": _3, "boxfuse": _3, "brave": [0, { "s": _5 }], "browsersafetymark": _3, "bigv": [0, { "uk0": _3 }], "cleverapps": _3, "dappnode": [0, { "dyndns": _3 }], "darklang": _3, "definima": _3, "dedyn": _3, "drud": _3, "fh-muenster": _3, "shw": _3, "forgerock": [0, { "id": _3 }], "github": _3, "gitlab": _3, "lolipop": _3, "hasura-app": _3, "hostyhosting": _3, "hypernode": _3, "moonscale": _5, "beebyte": _38, "beebyteapp": [0, { "sekd1": _3 }], "jele": _3, "webthings": _3, "loginline": _3, "barsy": _3, "azurecontainer": _5, "ngrok": [2, { "ap": _3, "au": _3, "eu": _3, "in": _3, "jp": _3, "sa": _3, "us": _3 }], "nodeart": [0, { "stage": _3 }], "pantheonsite": _3, "pstmn": [2, { "mock": _3 }], "protonet": _3, "qcx": [2, { "sys": _5 }], "qoto": _3, "vaporcloud": _3, "myrdbx": _3, "rb-hosting": _41, "on-k3s": _5, "on-rio": _5, "readthedocs": _3, "resindevice": _3, "resinstaging": [0, { "devices": _3 }], "hzc": _3, "sandcats": _3, "scrypted": [0, { "client": _3 }], "shiftedit": _3, "mo-siemens": _3, "lair": _37, "stolos": _5, "spacekit": _3, "musician": _3, "utwente": _3, "edugit": _3, "telebit": _3, "thingdust": [0, { "dev": _47, "disrec": _47, "prod": _48, "testing": _47 }], "tickets": _3, "upli": _3, "webflow": _3, "webflowtest": _3, "editorx": _3, "wixstudio": _3, "basicserver": _3, "virtualserver": _3 }], "iq": _49, "ir": [1, { "ac": _2, "co": _2, "gov": _2, "id": _2, "net": _2, "org": _2, "sch": _2, "xn--mgba3a4f16a": _2, "ایران": _2, "xn--mgba3a4fra": _2, "ايران": _2, "arvanedge": _3 }], "is": [1, { "net": _2, "com": _2, "edu": _2, "gov": _2, "org": _2, "int": _2, "blogspot": _3 }], "it": [1, { "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, "12chars": _3, "blogspot": _3, "ibxos": _3, "iliadboxos": _3, "neen": [0, { "jc": _3 }], "123homepage": _3, "16-b": _3, "32-b": _3, "64-b": _3, "myspreadshop": _3, "syncloud": _3 }], "je": [1, { "co": _2, "net": _2, "org": _2, "of": _3 }], "jm": _15, "jo": [1, { "com": _2, "org": _2, "net": _2, "edu": _2, "sch": _2, "gov": _2, "mil": _2, "name": _2 }], "jobs": _2, "jp": [1, { "ac": _2, "ad": _2, "co": _2, "ed": _2, "go": _2, "gr": _2, "lg": _2, "ne": [1, { "aseinet": _45, "gehirn": _3, "ivory": _3, "mail-box": _3, "mints": _3, "mokuren": _3, "opal": _3, "sakura": _3, "sumomo": _3, "topaz": _3 }], "or": _2, "aichi": [1, { "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, { "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, { "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, { "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, { "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, { "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, { "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, { "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, { "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, { "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, { "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, { "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, { "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, { "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, { "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, { "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, { "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, { "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, { "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, { "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, { "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, { "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, { "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, { "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, { "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, { "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, { "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, { "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, { "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, { "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, { "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, { "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, { "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, { "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, { "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, { "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, { "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, { "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, { "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, { "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, { "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, { "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, { "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, { "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, { "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, { "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, { "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": _15, "kitakyushu": _15, "kobe": _15, "nagoya": _15, "sapporo": _15, "sendai": _15, "yokohama": _15, "buyshop": _3, "fashionstore": _3, "handcrafted": _3, "kawaiishop": _3, "supersale": _3, "theshop": _3, "0am": _3, "0g0": _3, "0j0": _3, "0t0": _3, "mydns": _3, "pgw": _3, "wjg": _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, "hateblo": _3, "hatenablog": _3, "hatenadiary": _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, { "isk01": _50, "isk02": _50 }], "saloon": _3, "sblo": _3, "skr": _3, "tank": _3, "uh-oh": _3, "undo": _3, "webaccel": [0, { "rs": _3, "user": _3 }], "websozai": _3, "xii": _3 }], "ke": [1, { "ac": _2, "co": _8, "go": _2, "info": _2, "me": _2, "mobi": _2, "ne": _2, "or": _2, "sc": _2 }], "kg": [1, { "org": _2, "net": _2, "com": _2, "edu": _2, "gov": _2, "mil": _2, "us": _3 }], "kh": _15, "ki": _51, "km": [1, { "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, { "net": _2, "org": _2, "edu": _2, "gov": _2 }], "kp": [1, { "com": _2, "edu": _2, "gov": _2, "org": _2, "rep": _2, "tra": _2 }], "kr": [1, { "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, { "com": _2, "edu": _2, "emb": _2, "gov": _2, "ind": _2, "net": _2, "org": _2 }], "ky": _42, "kz": [1, { "org": _2, "edu": _2, "net": _2, "gov": _2, "mil": _2, "com": _2, "jcloud": _3 }], "la": [1, { "int": _2, "net": _2, "info": _2, "edu": _2, "gov": _2, "per": _2, "com": _2, "org": _2, "bnr": _3 }], "lb": _4, "lc": [1, { "com": _2, "net": _2, "co": _2, "org": _2, "edu": _2, "gov": _2, "oy": _3 }], "li": [1, { "blogspot": _3, "caa": _3 }], "lk": [1, { "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, { "ac": _2, "biz": _2, "co": _2, "edu": _2, "gov": _2, "info": _2, "net": _2, "org": _2, "sc": _2 }], "lt": [1, { "gov": _2, "blogspot": _3 }], "lu": [1, { "blogspot": _3, "123website": _3 }], "lv": [1, { "com": _2, "edu": _2, "gov": _2, "org": _2, "mil": _2, "id": _2, "net": _2, "asn": _2, "conf": _2 }], "ly": [1, { "com": _2, "net": _2, "gov": _2, "plc": _2, "edu": _2, "sch": _2, "med": _2, "org": _2, "id": _2 }], "ma": [1, { "co": _2, "net": _2, "gov": _2, "org": _2, "ac": _2, "press": _2 }], "mc": [1, { "tm": _2, "asso": _2 }], "md": [1, { "blogspot": _3, "ir": _3 }], "me": [1, { "co": _2, "net": _2, "org": _2, "edu": _2, "ac": _2, "gov": _2, "its": _2, "priv": _2, "c66": _3, "craft": _3, "edgestack": _3, "filegear": _3, "glitch": _3, "filegear-sg": _3, "lohmus": _3, "barsy": _3, "mcdir": _3, "mcpe": _3, "brasilia": _3, "ddns": _3, "dnsfor": _3, "hopto": _3, "loginto": _3, "noip": _3, "webhop": _3, "soundcast": _3, "tcp4": _3, "vp4": _3, "diskstation": _3, "dscloud": _3, "i234": _3, "myds": _3, "synology": _3, "transip": _41, "yombo": _3, "nohost": _3 }], "mg": [1, { "org": _2, "nom": _2, "gov": _2, "prd": _2, "tm": _2, "edu": _2, "mil": _2, "com": _2, "co": _2 }], "mh": _2, "mil": _2, "mk": [1, { "com": _2, "org": _2, "net": _2, "edu": _2, "gov": _2, "inf": _2, "name": _2, "blogspot": _3 }], "ml": [1, { "com": _2, "edu": _2, "gouv": _2, "gov": _2, "net": _2, "org": _2, "presse": _2 }], "mm": _15, "mn": [1, { "gov": _2, "edu": _2, "org": _2, "nyc": _3 }], "mo": _4, "mobi": [1, { "barsy": _3, "dscloud": _3 }], "mp": [1, { "ju": _3 }], "mq": _2, "mr": _9, "ms": [1, { "com": _2, "edu": _2, "gov": _2, "net": _2, "org": _2, "lab": _3, "minisite": _3 }], "mt": [1, { "com": _8, "edu": _2, "net": _2, "org": _2 }], "mu": [1, { "com": _2, "net": _2, "org": _2, "gov": _2, "ac": _2, "co": _2, "or": _2 }], "museum": _2, "mv": [1, { "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, { "ac": _2, "biz": _2, "co": _2, "com": _2, "coop": _2, "edu": _2, "gov": _2, "int": _2, "net": _2, "org": _2 }], "mx": [1, { "com": _2, "org": _2, "gob": _2, "edu": _2, "net": _2, "blogspot": _3 }], "my": [1, { "biz": _2, "com": _2, "edu": _2, "gov": _2, "mil": _2, "name": _2, "net": _2, "org": _2, "blogspot": _3 }], "mz": [1, { "ac": _2, "adv": _2, "co": _2, "edu": _2, "gov": _2, "mil": _2, "net": _2, "org": _2 }], "na": [1, { "alt": _2, "co": _2, "com": _2, "gov": _2, "net": _2, "org": _2 }], "name": [1, { "her": _53, "his": _53 }], "nc": [1, { "asso": _2, "nom": _2 }], "ne": _2, "net": [1, { "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, "appudo": _3, "atlassian-dev": [0, { "prod": _54 }], "myfritz": _3, "onavstack": _3, "shopselect": _3, "blackbaudcdn": _3, "boomla": _3, "bplaced": _3, "square7": _3, "cdn77": [0, { "r": _3 }], "cdn77-ssl": _3, "gb": _3, "hu": _3, "jp": _3, "se": _3, "uk": _3, "clickrising": _3, "ddns-ip": _3, "dns-cloud": _3, "dns-dynamic": _3, "cloudaccess": _3, "cloudflare": [2, { "cdn": _3 }], "cloudflareanycast": _54, "cloudflarecn": _54, "cloudflareglobal": _54, "ctfcloud": _3, "feste-ip": _3, "knx-server": _3, "static-access": _3, "cryptonomic": _5, "dattolocal": _3, "mydatto": _3, "debian": _3, "definima": _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, "casacam": _3, "dynu": _3, "dynv6": _3, "twmail": _3, "ru": _3, "channelsdvr": [2, { "u": _3 }], "fastly": [0, { "freetls": _3, "map": _3, "prod": [0, { "a": _3, "global": _3 }], "ssl": [0, { "a": _3, "b": _3, "global": _3 }] }], "fastlylb": [2, { "map": _3 }], "edgeapp": _3, "keyword-on": _3, "live-on": _3, "server-on": _3, "cdn-edges": _3, "localcert": _3, "localhostcert": _3, "heteml": _3, "cloudfunctions": _3, "grafana-dev": _3, "iobb": _3, "moonscale": _3, "in-dsl": _3, "in-vpn": _3, "apps-1and1": _3, "ipifony": _3, "cloudjiffy": [2, { "fra1-de": _3, "west1-us": _3 }], "elastx": [0, { "jls-sto1": _3, "jls-sto2": _3, "jls-sto3": _3 }], "massivegrid": [0, { "paas": [0, { "fr-1": _3, "lon-1": _3, "lon-2": _3, "ny-1": _3, "ny-2": _3, "sg-1": _3 }] }], "saveincloud": [0, { "jelastic": _3, "nordeste-idc": _3 }], "scaleforce": _43, "kinghost": _3, "uni5": _3, "krellian": _3, "ggff": _3, "barsy": _3, "memset": _3, "azure-api": _3, "azure-mobile": _3, "azureedge": _3, "azurefd": _3, "azurestaticapps": [2, { "1": _3, "2": _3, "3": _3, "4": _3, "5": _3, "6": _3, "7": _3, "centralus": _3, "eastasia": _3, "eastus2": _3, "westeurope": _3, "westus2": _3 }], "azurewebsites": _3, "cloudapp": _3, "trafficmanager": _3, "windows": [0, { "core": [0, { "blob": _3 }], "servicebus": _3 }], "mynetname": [0, { "sn": _3 }], "routingthecloud": _3, "bounceme": _3, "ddns": _3, "eating-organic": _3, "mydissent": _3, "myeffect": _3, "mymediapc": _3, "mypsx": _3, "mysecuritycamera": _3, "nhlfan": _3, "no-ip": _3, "pgafan": _3, "privatizehealthinsurance": _3, "redirectme": _3, "serveblog": _3, "serveminecraft": _3, "sytes": _3, "dnsup": _3, "hicam": _3, "now-dns": _3, "ownip": _3, "vpndns": _3, "cloudycluster": _3, "ovh": [0, { "hosting": _5, "webpaas": _5 }], "rackmaze": _3, "myradweb": _3, "in": _3, "squares": _3, "schokokeks": _3, "firewall-gateway": _3, "seidat": _3, "senseering": _3, "siteleaf": _3, "mafelo": _3, "myspreadshop": _3, "vps-host": [2, { "jelastic": [0, { "atl": _3, "njs": _3, "ric": _3 }] }], "srcf": [0, { "soc": _3, "user": _3 }], "supabase": _3, "dsmynas": _3, "familyds": _3, "ts": [2, { "c": _5 }], "torproject": [2, { "pages": _3 }], "vusercontent": _3, "reserve-online": _3, "community-pro": _3, "meinforum": _3, "yandexcloud": [2, { "storage": _3, "website": _3 }], "za": _3 }], "nf": [1, { "com": _2, "net": _2, "per": _2, "rec": _2, "web": _2, "arts": _2, "firm": _2, "info": _2, "other": _2, "store": _2 }], "ng": [1, { "com": _8, "edu": _2, "gov": _2, "i": _2, "mil": _2, "mobi": _2, "name": _2, "net": _2, "org": _2, "sch": _2, "biz": [2, { "co": _3, "dl": _3, "go": _3, "lg": _3, "on": _3 }], "col": _3, "firm": _3, "gen": _3, "ltd": _3, "ngo": _3, "plc": _3 }], "ni": [1, { "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, { "co": _3, "hosting-cluster": _3, "blogspot": _3, "gov": _3, "khplay": _3, "123website": _3, "myspreadshop": _3, "transurl": _5, "cistron": _3, "demon": _3 }], "no": [1, { "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": _55, "ah": _55, "bu": _55, "fm": _55, "hl": _55, "hm": _55, "jan-mayen": _55, "mr": _55, "nl": _55, "nt": _55, "of": _55, "ol": _55, "oslo": _55, "rl": _55, "sf": _55, "st": _55, "svalbard": _55, "tm": _55, "tr": _55, "va": _55, "vf": _55, "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, { "bo": _2, "xn--b-5ga": _2, "bø": _2 }], "nordland": [0, { "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, { "heroy": _2, "sande": _2 }], "xn--mre-og-romsdal-qqb": [0, { "xn--hery-ira": _2, "sande": _2 }], "møre-og-romsdal": [0, { "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": _56, "buskerud": _56, "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, { "os": _2, "valer": _2, "xn--vler-qoa": _2, "våler": _2 }], "hordaland": [0, { "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, { "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, { "valer": _2 }], "xn--stfold-9xa": [0, { "xn--vler-qoa": _2 }], "østfold": [0, { "våler": _2 }], "co": _3, "blogspot": _3, "123hjemmeside": _3, "myspreadshop": _3 }], "np": _15, "nr": _51, "nu": [1, { "merseine": _3, "mine": _3, "shacknet": _3, "enterprisecloud": _3 }], "nz": [1, { "ac": _2, "co": _8, "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, "cloudns": _3 }], "om": [1, { "co": _2, "com": _2, "edu": _2, "gov": _2, "med": _2, "museum": _2, "net": _2, "org": _2, "pro": _2 }], "onion": _2, "org": [1, { "altervista": _3, "pimienta": _3, "poivron": _3, "potager": _3, "sweetpepper": _3, "cdn77": [0, { "c": _3, "rsc": _3 }], "cdn77-secure": [0, { "origin": [0, { "ssl": _3 }] }], "ae": _3, "cloudns": _3, "ip-dynamic": _3, "ddnss": _3, "duckdns": _3, "tunk": _3, "blogdns": _3, "blogsite": _3, "boldlygoingnowhere": _3, "dnsalias": _3, "dnsdojo": _3, "doesntexist": _3, "dontexist": _3, "doomdns": _3, "dvrdns": _3, "dynalias": _3, "dyndns": [2, { "go": _3, "home": _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, "accesscam": _3, "camdvr": _3, "freeddns": _3, "mywire": _3, "webredirect": _3, "twmail": _3, "eu": [2, { "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, "me": _3, "mk": _3, "mt": _3, "my": _3, "net": _3, "ng": _3, "nl": _3, "no": _3, "nz": _3, "pl": _3, "pt": _3, "ro": _3, "ru": _3, "se": _3, "si": _3, "sk": _3, "tr": _3, "uk": _3, "us": _3 }], "fedorainfracloud": _3, "fedorapeople": _3, "fedoraproject": [0, { "cloud": _3, "os": _40, "stg": [0, { "os": _40 }] }], "freedesktop": _3, "hatenadiary": _3, "hepforge": _3, "in-dsl": _3, "in-vpn": _3, "js": _3, "barsy": _3, "mayfirst": _3, "routingthecloud": _3, "bmoattachments": _3, "cable-modem": _3, "collegefan": _3, "couchpotatofries": _3, "hopto": _3, "mlbfan": _3, "myftp": _3, "mysecuritycamera": _3, "nflfan": _3, "no-ip": _3, "read-books": _3, "ufcfan": _3, "zapto": _3, "dynserv": _3, "now-dns": _3, "is-local": _3, "httpbin": _3, "pubtls": _3, "jpn": _3, "my-firewall": _3, "myfirewall": _3, "spdns": _3, "small-web": _3, "dsmynas": _3, "familyds": _3, "teckids": _50, "tuxfamily": _3, "diskstation": _3, "hk": _3, "us": _3, "toolforge": _3, "wmcloud": _3, "wmflabs": _3, "za": _3 }], "pa": [1, { "ac": _2, "gob": _2, "com": _2, "org": _2, "sld": _2, "edu": _2, "net": _2, "ing": _2, "abo": _2, "med": _2, "nom": _2 }], "pe": [1, { "edu": _2, "gob": _2, "nom": _2, "mil": _2, "org": _2, "com": _2, "net": _2, "blogspot": _3 }], "pf": [1, { "com": _2, "org": _2, "edu": _2 }], "pg": _15, "ph": [1, { "com": _2, "net": _2, "org": _2, "gov": _2, "edu": _2, "ngo": _2, "mil": _2, "i": _2, "cloudns": _3 }], "pk": [1, { "ac": _2, "biz": _2, "com": _2, "edu": _2, "fam": _2, "gkp": _2, "gob": _2, "gog": _2, "gok": _2, "gon": _2, "gop": _2, "gos": _2, "gov": _2, "net": _2, "org": _2, "web": _2 }], "pl": [1, { "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, { "ap": _2, "griw": _2, "ic": _2, "is": _2, "kmpsp": _2, "konsulat": _2, "kppsp": _2, "kwp": _2, "kwpsp": _2, "mup": _2, "mw": _2, "oia": _2, "oirm": _2, "oke": _2, "oow": _2, "oschr": _2, "oum": _2, "pa": _2, "pinb": _2, "piw": _2, "po": _2, "pr": _2, "psp": _2, "psse": _2, "pup": _2, "rzgw": _2, "sa": _2, "sdn": _2, "sko": _2, "so": _2, "sr": _2, "starostwo": _2, "ug": _2, "ugim": _2, "um": _2, "umig": _2, "upow": _2, "uppo": _2, "us": _2, "uw": _2, "uzs": _2, "wif": _2, "wiih": _2, "winb": _2, "wios": _2, "witd": _2, "wiw": _2, "wkz": _2, "wsa": _2, "wskr": _2, "wsse": _2, "wuoz": _2, "wzmiuw": _2, "zp": _2, "zpisdn": _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, "art": _3, "gliwice": _3, "krakow": _3, "poznan": _3, "wroc": _3, "zakopane": _3, "beep": _3, "ecommerce-shop": _3, "cfolks": _3, "dfirma": _3, "dkonto": _3, "you2": _3, "shoparena": _3, "homesklep": _3, "sdscloud": _3, "unicloud": _3, "lodz": _3, "pabianice": _3, "plock": _3, "sieradz": _3, "skierniewice": _3, "zgierz": _3, "krasnik": _3, "leczna": _3, "lubartow": _3, "lublin": _3, "poniatowa": _3, "swidnik": _3, "co": _3, "torun": _3, "simplesite": _3, "myspreadshop": _3, "gda": _3, "gdansk": _3, "gdynia": _3, "med": _3, "sopot": _3, "bielsko": _3 }], "pm": [1, { "own": _3, "name": _3 }], "pn": [1, { "gov": _2, "co": _2, "org": _2, "edu": _2, "net": _2 }], "post": _2, "pr": [1, { "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, { "aaa": _2, "aca": _2, "acct": _2, "avocat": _2, "bar": _2, "cpa": _2, "eng": _2, "jur": _2, "law": _2, "med": _2, "recht": _2, "12chars": _3, "cloudns": _3, "barsy": _3, "ngrok": _3 }], "ps": [1, { "edu": _2, "gov": _2, "sec": _2, "plo": _2, "com": _2, "org": _2, "net": _2 }], "pt": [1, { "net": _2, "gov": _2, "org": _2, "edu": _2, "int": _2, "publ": _2, "com": _2, "nome": _2, "blogspot": _3, "123paginaweb": _3 }], "pw": [1, { "co": _2, "or": _2, "ed": _2, "go": _2, "belau": _2, "cloudns": _3, "x443": _3 }], "py": [1, { "com": _2, "coop": _2, "edu": _2, "gov": _2, "mil": _2, "net": _2, "org": _2 }], "qa": [1, { "com": _2, "edu": _2, "gov": _2, "mil": _2, "name": _2, "net": _2, "org": _2, "sch": _2, "blogspot": _3 }], "re": [1, { "asso": _2, "com": _2, "nom": _2, "blogspot": _3, "can": _3 }], "ro": [1, { "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, { "ac": _2, "co": _2, "edu": _2, "gov": _2, "in": _2, "org": _2, "brendly": _46, "blogspot": _3, "ua": _3, "barsy": _3, "ox": _3 }], "ru": [1, { "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, "myjino": [2, { "hosting": _5, "landing": _5, "spectrum": _5, "vps": _5 }], "cldmail": [0, { "hb": _3 }], "mcdir": [2, { "vps": _3 }], "mcpre": _3, "net": _3, "org": _3, "pp": _3, "lk3": _3, "ras": _3 }], "rw": [1, { "ac": _2, "co": _2, "coop": _2, "gov": _2, "mil": _2, "net": _2, "org": _2 }], "sa": [1, { "com": _2, "net": _2, "org": _2, "gov": _2, "med": _2, "pub": _2, "edu": _2, "sch": _2 }], "sb": _4, "sc": _4, "sd": [1, { "com": _2, "net": _2, "org": _2, "edu": _2, "med": _2, "tv": _2, "gov": _2, "info": _2 }], "se": [1, { "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 }], "sg": [1, { "com": _2, "net": _2, "org": _2, "gov": _2, "edu": _2, "per": _2, "blogspot": _3, "enscaled": _3 }], "sh": [1, { "com": _2, "net": _2, "gov": _2, "org": _2, "mil": _2, "hashbang": _3, "platform": [0, { "ent": _3, "eu": _3, "us": _3 }], "now": _3 }], "si": [1, { "f5": _3, "gitapp": _3, "gitpage": _3, "blogspot": _3 }], "sj": _2, "sk": _8, "sl": _4, "sm": _2, "sn": [1, { "art": _2, "com": _2, "edu": _2, "gouv": _2, "org": _2, "perso": _2, "univ": _2, "blogspot": _3 }], "so": [1, { "com": _2, "edu": _2, "gov": _2, "me": _2, "net": _2, "org": _2, "surveys": _3 }], "sr": _2, "ss": [1, { "biz": _2, "co": _2, "com": _2, "edu": _2, "gov": _2, "me": _2, "net": _2, "org": _2, "sch": _2 }], "st": [1, { "co": _2, "com": _2, "consulado": _2, "edu": _2, "embaixada": _2, "mil": _2, "net": _2, "org": _2, "principe": _2, "saotome": _2, "store": _2, "helioho": _3, "kirara": _3, "noho": _3 }], "su": [1, { "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, { "com": _2, "edu": _2, "gob": _2, "org": _2, "red": _2 }], "sx": _9, "sy": _49, "sz": [1, { "co": _2, "ac": _2, "org": _2 }], "tc": _2, "td": _8, "tel": _2, "tf": [1, { "sch": _3 }], "tg": _2, "th": [1, { "ac": _2, "co": _2, "go": _2, "in": _2, "mi": _2, "net": _2, "or": _2, "online": _3, "shop": _3 }], "tj": [1, { "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": _9, "tm": [1, { "com": _2, "co": _2, "org": _2, "net": _2, "nom": _2, "gov": _2, "mil": _2, "edu": _2 }], "tn": [1, { "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, { "611": _3, "com": _2, "gov": _2, "net": _2, "org": _2, "edu": _2, "mil": _2, "oya": _3, "x0": _3, "quickconnect": _23, "vpnplus": _3 }], "tr": [1, { "av": _2, "bbs": _2, "bel": _2, "biz": _2, "com": _8, "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": _9 }], "tt": [1, { "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, { "better-than": _3, "dyndns": _3, "on-the-web": _3, "worse-than": _3, "from": _3, "sakura": _3 }], "tw": [1, { "edu": _2, "gov": _2, "mil": _2, "com": [1, { "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, "mydns": _3, "blogspot": _3 }], "tz": [1, { "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, { "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, "kropyvnytskyi": _2, "krym": _2, "ks": _2, "kv": _2, "kyiv": _2, "lg": _2, "lt": _2, "lugansk": _2, "luhansk": _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, "uzhhorod": _2, "vinnica": _2, "vinnytsia": _2, "vn": _2, "volyn": _2, "yalta": _2, "zakarpattia": _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, { "co": _2, "or": _2, "ac": _2, "sc": _2, "go": _2, "ne": _2, "com": _2, "org": _2, "blogspot": _3 }], "uk": [1, { "ac": _2, "co": [1, { "bytemark": [0, { "dh": _3, "vm": _3 }], "blogspot": _3, "layershift": _43, "barsy": _3, "barsyonline": _3, "retrosnub": _48, "nh-serv": _3, "no-ip": _3, "adimo": _3, "myspreadshop": _3 }], "gov": [1, { "api": _3, "campaign": _3, "service": _3 }], "ltd": _2, "me": _2, "net": _2, "nhs": _2, "org": [1, { "glug": _3, "lug": _3, "lugs": _3, "affinitylottery": _3, "raffleentry": _3, "weeklylottery": _3 }], "plc": _2, "police": _2, "sch": _15, "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, "nimsite": _3, "oraclegovcloudapps": _5 }], "us": [1, { "dni": _2, "fed": _2, "isa": _2, "kids": _2, "nsn": _2, "ak": _57, "al": _57, "ar": _57, "as": _57, "az": _57, "ca": _57, "co": _57, "ct": _57, "dc": _57, "de": [1, { "cc": _2, "lib": _3 }], "fl": _57, "ga": _57, "gu": _57, "hi": _58, "ia": _57, "id": _57, "il": _57, "in": _57, "ks": _57, "ky": _57, "la": _57, "ma": [1, { "k12": [1, { "pvt": _2, "chtr": _2, "paroch": _2 }], "cc": _2, "lib": _2 }], "md": _57, "me": _57, "mi": [1, { "k12": _2, "cc": _2, "lib": _2, "ann-arbor": _2, "cog": _2, "dst": _2, "eaton": _2, "gen": _2, "mus": _2, "tec": _2, "washtenaw": _2 }], "mn": _57, "mo": _57, "ms": _57, "mt": _57, "nc": _57, "nd": _58, "ne": _57, "nh": _57, "nj": _57, "nm": _57, "nv": _57, "ny": _57, "oh": _57, "ok": _57, "or": _57, "pa": _57, "pr": _57, "ri": _58, "sc": _57, "sd": _58, "tn": _57, "tx": _57, "ut": _57, "vi": _57, "vt": _57, "va": _57, "wa": _57, "wi": _57, "wv": [1, { "cc": _2 }], "wy": _57, "cloudns": _3, "drud": _3, "is-by": _3, "land-4-sale": _3, "stuff-4-sale": _3, "heliohost": _3, "enscaled": [0, { "phx": _3 }], "mircloud": _3, "ngo": _3, "golffan": _3, "noip": _3, "pointto": _3, "freeddns": _3, "srv": [2, { "gh": _3, "gl": _3 }], "platterp": _3, "servername": _3 }], "uy": [1, { "com": _8, "edu": _2, "gub": _2, "mil": _2, "net": _2, "org": _2 }], "uz": [1, { "co": _2, "com": _2, "net": _2, "org": _2 }], "va": _2, "vc": [1, { "com": _2, "net": _2, "org": _2, "gov": _2, "mil": _2, "edu": _2, "gv": [2, { "d": _3 }], "0e": _3, "mydns": _3 }], "ve": [1, { "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": _2, "vi": [1, { "co": _2, "com": _2, "k12": _2, "net": _2, "org": _2 }], "vn": [1, { "ac": _2, "ai": _2, "biz": _2, "com": _2, "edu": _2, "gov": _2, "health": _2, "id": _2, "info": _2, "int": _2, "io": _2, "name": _2, "net": _2, "org": _2, "pro": _2, "angiang": _2, "bacgiang": _2, "backan": _2, "baclieu": _2, "bacninh": _2, "baria-vungtau": _2, "bentre": _2, "binhdinh": _2, "binhduong": _2, "binhphuoc": _2, "binhthuan": _2, "camau": _2, "cantho": _2, "caobang": _2, "daklak": _2, "daknong": _2, "danang": _2, "dienbien": _2, "dongnai": _2, "dongthap": _2, "gialai": _2, "hagiang": _2, "haiduong": _2, "haiphong": _2, "hanam": _2, "hanoi": _2, "hatinh": _2, "haugiang": _2, "hoabinh": _2, "hungyen": _2, "khanhhoa": _2, "kiengiang": _2, "kontum": _2, "laichau": _2, "lamdong": _2, "langson": _2, "laocai": _2, "longan": _2, "namdinh": _2, "nghean": _2, "ninhbinh": _2, "ninhthuan": _2, "phutho": _2, "phuyen": _2, "quangbinh": _2, "quangnam": _2, "quangngai": _2, "quangninh": _2, "quangtri": _2, "soctrang": _2, "sonla": _2, "tayninh": _2, "thaibinh": _2, "thainguyen": _2, "thanhhoa": _2, "thanhphohochiminh": _2, "thuathienhue": _2, "tiengiang": _2, "travinh": _2, "tuyenquang": _2, "vinhlong": _2, "vinhphuc": _2, "yenbai": _2, "blogspot": _3 }], "vu": _42, "wf": [1, { "biz": _3, "sch": _3 }], "ws": [1, { "com": _2, "net": _2, "org": _2, "gov": _2, "edu": _2, "advisor": _5, "cloud66": _3, "dyndns": _3, "mypets": _3 }], "yt": [1, { "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, { "xn--55qx5d": _2, "xn--wcvs22d": _2, "xn--mxtq1m": _2, "xn--gmqw5a": _2, "xn--od0alg": _2, "xn--uc0atv": _2 }], "香港": [1, { "公司": _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, { "xn--o1ac": _2, "xn--c1avg": _2, "xn--90azh": _2, "xn--d1at": _2, "xn--o1ach": _2, "xn--80au": _2 }], "срб": [1, { "пр": _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, { "xn--12c1fe0br": _2, "xn--12co0c3b4eva": _2, "xn--h3cuzk1di": _2, "xn--o3cyx2a": _2, "xn--m3ch0j3a": _2, "xn--12cfi8ixb8l": _2 }], "ไทย": [1, { "ศึกษา": _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": _49, "za": [0, { "ac": _2, "agric": _2, "alt": _2, "co": _8, "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, { "ac": _2, "biz": _2, "co": _2, "com": _2, "edu": _2, "gov": _2, "info": _2, "mil": _2, "net": _2, "org": _2, "sch": _2 }], "zw": [1, { "ac": _2, "co": _2, "gov": _2, "mil": _2, "org": _2 }], "aaa": _2, "aarp": _2, "abb": _2, "abbott": _2, "abbvie": _2, "abc": _2, "able": _2, "abogado": _2, "abudhabi": _2, "academy": [1, { "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, "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, { "adaptable": _3, "beget": _5, "clerk": _3, "clerkstage": _3, "wnext": _3, "csb": [2, { "preview": _3 }], "platform0": _3, "deta": _3, "ondigitalocean": _3, "easypanel": _3, "encr": _3, "evervault": _6, "expo": [2, { "staging": _3 }], "edgecompute": _3, "flutterflow": _3, "framer": _3, "hosted": _5, "run": _5, "web": _3, "hasura": _3, "loginline": _3, "medusajs": _3, "messerli": _3, "netfy": _3, "netlify": _3, "ngrok": _3, "ngrok-free": _3, "developer": _5, "noop": _3, "northflank": _5, "upsun": _5, "replit": _7, "nyat": _3, "snowflake": [0, { "*": _3, "privatelink": _5 }], "streamlit": _3, "storipress": _3, "telebit": _3, "typedream": _3, "vercel": _3, "bookonline": _3, "wdh": _3, "zeabur": _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, "aws": [1, { "sagemaker": [0, { "ap-northeast-1": _11, "ap-northeast-2": _11, "ap-south-1": _11, "ap-southeast-1": _11, "ap-southeast-2": _11, "ca-central-1": _13, "eu-central-1": _11, "eu-west-1": _11, "eu-west-2": _11, "us-east-1": _13, "us-east-2": _13, "us-west-2": _13, "af-south-1": _10, "ap-east-1": _10, "ap-northeast-3": _10, "ap-south-2": _12, "ap-southeast-3": _10, "ap-southeast-4": _12, "ca-west-1": [0, { "notebook": _3, "notebook-fips": _3 }], "eu-central-2": _12, "eu-north-1": _10, "eu-south-1": _10, "eu-south-2": _10, "eu-west-3": _10, "il-central-1": _10, "me-central-1": _10, "me-south-1": _10, "sa-east-1": _10, "us-gov-east-1": _14, "us-gov-west-1": _14, "us-west-1": [0, { "notebook": _3, "notebook-fips": _3, "studio": _3 }], "experiments": _5 }], "repost": [0, { "private": _5 }] }], "axa": _2, "azure": _2, "baby": _2, "baidu": _2, "banamex": _2, "band": _2, "bank": _2, "bar": _2, "barcelona": _2, "barclaycard": _2, "barclays": _2, "barefoot": _2, "bargains": _2, "baseball": _2, "basketball": [1, { "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": [1, { "v0": _3 }], "builders": [1, { "cloudsite": _3 }], "business": _17, "buy": _2, "buzz": _2, "bzh": _2, "cab": _2, "cafe": _2, "cal": _2, "call": _2, "calvinklein": _2, "cam": _2, "camera": _2, "camp": [1, { "emf": [0, { "at": _3 }] }], "canon": _2, "capetown": _2, "capital": _2, "capitalone": _2, "car": _2, "caravan": _2, "cards": _2, "care": _2, "career": _2, "careers": _2, "cars": _2, "casa": [1, { "nabu": [0, { "ui": _3 }] }], "case": _2, "cash": _2, "casino": _2, "catering": _2, "catholic": _2, "cba": _2, "cbn": _2, "cbre": _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, "claims": _2, "cleaning": _2, "click": _2, "clinic": _2, "clinique": _2, "clothing": _2, "cloud": [1, { "elementor": _3, "encoway": [0, { "eu": _3 }], "statics": _5, "ravendb": _3, "axarnet": [0, { "es-1": _3 }], "diadem": _3, "jelastic": [0, { "vip": _3 }], "jele": _3, "jenv-aruba": [0, { "aruba": [0, { "eur": [0, { "it1": _3 }] }], "it1": _3 }], "keliweb": [2, { "cs": _3 }], "oxa": [2, { "tn": _3, "uk": _3 }], "primetel": [2, { "uk": _3 }], "reclaim": [0, { "ca": _3, "uk": _3, "us": _3 }], "trendhosting": [0, { "ch": _3, "de": _3 }], "jotelulu": _3, "kuleuven": _3, "linkyard": _3, "magentosite": _5, "matlab": _3, "observablehq": _3, "perspecta": _3, "vapor": _3, "on-rancher": _5, "scw": [0, { "baremetal": [0, { "fr-par-1": _3, "fr-par-2": _3, "nl-ams-1": _3 }], "fr-par": [0, { "cockpit": _3, "fnc": [2, { "functions": _3 }], "k8s": _19, "s3": _3, "s3-website": _3, "whm": _3 }], "instances": [0, { "priv": _3, "pub": _3 }], "k8s": _3, "nl-ams": [0, { "cockpit": _3, "k8s": _19, "s3": _3, "s3-website": _3, "whm": _3 }], "pl-waw": [0, { "cockpit": _3, "k8s": _19, "s3": _3, "s3-website": _3 }], "scalebook": _3, "smartlabeling": _3 }], "servebolt": _3, "onstackit": [0, { "runs": _3 }], "trafficplex": _3, "unison-services": _3, "urown": _3, "voorloper": _3, "zap": _3 }], "club": [1, { "cloudns": _3, "jele": _3, "barsy": _3 }], "clubmed": _2, "coach": _2, "codes": [1, { "owo": _5 }], "coffee": _2, "college": _2, "cologne": _2, "commbank": _2, "community": [1, { "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, "cool": [1, { "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, "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, { "graphic": _3, "bss": _3 }], "dev": [1, { "12chars": _3, "panel": _3, "lcl": _5, "lclstage": _5, "stg": _5, "stgstage": _5, "pages": _3, "r2": _3, "workers": _3, "curv": _3, "deno": _3, "deno-staging": _3, "deta": _3, "evervault": _6, "fly": _3, "githubpreview": _3, "gateway": _5, "hrsn": _3, "is-a-good": _3, "is-a": _3, "iserv": _3, "runcontainers": _3, "localcert": [0, { "user": _5 }], "loginline": _3, "barsy": _3, "mediatech": _3, "modx": _3, "ngrok": _3, "ngrok-free": _3, "is-a-fullstack": _3, "is-cool": _3, "is-not-a": _3, "localplayer": _3, "xmit": _3, "platter-app": _3, "replit": [2, { "archer": _3, "bones": _3, "canary": _3, "global": _3, "hacker": _3, "id": _3, "janeway": _3, "kim": _3, "kira": _3, "kirk": _3, "odo": _3, "paris": _3, "picard": _3, "pike": _3, "prerelease": _3, "reed": _3, "riker": _3, "sisko": _3, "spock": _3, "staging": _3, "sulu": _3, "tarpit": _3, "teams": _3, "tucker": _3, "wesley": _3, "worf": _3 }], "crm": [0, { "d": _5, "w": _5, "wa": _5, "wb": _5, "wc": _5, "wd": _5, "we": _5, "wf": _5 }], "vercel": _3, "webhare": _5 }], "dhl": _2, "diamonds": _2, "diet": _2, "digital": [1, { "cloudapps": [2, { "london": _3 }] }], "direct": [1, { "libp2p": _3 }], "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": _2, "eat": _2, "eco": _2, "edeka": _2, "education": _17, "email": [1, { "crisp": [0, { "on": _3 }], "tawk": _44, "tawkto": _44 }], "emerck": _2, "energy": _2, "engineer": _2, "engineering": _2, "enterprises": _2, "epson": _2, "equipment": _2, "ericsson": _2, "erni": _2, "esq": _2, "estate": [1, { "compute": _5 }], "eurovision": _2, "eus": [1, { "party": _45 }], "events": [1, { "koobin": _3, "co": _3 }], "exchange": _2, "expert": _2, "exposed": _2, "express": _2, "extraspace": _2, "fage": _2, "fail": _2, "fairwinds": _2, "faith": _2, "family": _2, "fan": _2, "fans": _2, "farm": [1, { "storj": _3 }], "farmers": _2, "fashion": _2, "fast": _2, "fedex": _2, "feedback": _2, "ferrari": _2, "ferrero": _2, "fidelity": _2, "fido": _2, "film": _2, "final": _2, "finance": _2, "financial": _17, "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, "football": _2, "ford": _2, "forex": _2, "forsale": _2, "forum": _2, "foundation": _2, "fox": _2, "free": _2, "fresenius": _2, "frl": _2, "frogans": _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": [1, { "pley": _3, "sheezy": _3 }], "gap": _2, "garden": _2, "gay": [1, { "pages": _3 }], "gbiz": _2, "gdn": [1, { "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, { "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, { "discourse": _3 }], "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, { "hra": _3 }], "healthcare": _2, "help": _2, "helsinki": _2, "here": _2, "hermes": _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, { "cloudaccess": _3, "freesite": _3, "easypanel": _3, "fastvps": _3, "myfast": _3, "tempurl": _3, "wpmudev": _3, "jele": _3, "mircloud": _3, "wp2": _3, "half": _3 }], "hosting": [1, { "opencraft": _3 }], "hot": _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, "kindle": _2, "kitchen": _2, "kiwi": _2, "koeln": _2, "komatsu": _2, "kosher": _2, "kpmg": _2, "kpn": _2, "krd": [1, { "co": _3, "edu": _3 }], "kred": _2, "kuokgroup": _2, "kyoto": _2, "lacaixa": _2, "lamborghini": _2, "lamer": _2, "lancaster": _2, "land": _2, "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, { "myfritz": _3, "cyon": _3, "dweb": _5, "nftstorage": [0, { "ipfs": _3 }], "mypep": _3 }], "lipsy": _2, "live": [1, { "aem": _3, "hlx": _3, "ewp": _5 }], "living": _2, "llc": _2, "llp": _2, "loan": _2, "loans": _2, "locker": _2, "locus": _2, "lol": [1, { "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, { "router": _3 }], "mango": _2, "map": _2, "market": _2, "marketing": _2, "markets": _2, "marriott": _2, "marshalls": _2, "mattel": _2, "mba": _2, "mckinsey": _2, "med": _2, "media": _52, "meet": _2, "melbourne": _2, "meme": _2, "memorial": _2, "men": _2, "menu": [1, { "barsy": _3, "barsyonline": _3 }], "merck": _2, "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": [1, { "ind": _3 }], "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, "nab": _2, "nagoya": _2, "navy": _2, "nba": _2, "nec": _2, "netbank": _2, "netflix": _2, "network": [1, { "alces": _5, "co": _3, "arvo": _3, "azimuth": _3, "tlon": _3 }], "neustar": _2, "new": _2, "news": [1, { "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, "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, "ollo": _2, "omega": _2, "one": [1, { "kin": _5, "service": _3 }], "ong": [1, { "obl": _3 }], "onl": _2, "online": [1, { "eero": _3, "eero-stage": _3, "websitebuilder": _3, "barsy": _3 }], "ooo": _2, "open": _2, "oracle": _2, "orange": [1, { "tech": _3 }], "organic": _2, "origins": _2, "osaka": _2, "otsuka": _2, "ott": _2, "ovh": [1, { "nerdpol": _3 }], "page": [1, { "aem": _3, "hlx": _3, "hlx3": _3, "translated": _3, "codeberg": _3, "prvcy": _3, "rocky": _3, "pdns": _3, "plesk": _3 }], "panasonic": _2, "paris": _2, "pars": _2, "partners": _2, "parts": _2, "party": _2, "pay": _2, "pccw": _2, "pet": _2, "pfizer": _2, "pharmacy": _2, "phd": _2, "philips": _2, "phone": _2, "photo": _2, "photography": _2, "photos": _52, "physio": _2, "pics": _2, "pictet": _2, "pictures": [1, { "1337": _3 }], "pid": _2, "pin": _2, "ping": _2, "pink": _2, "pioneer": _2, "pizza": [1, { "ngrok": _3 }], "place": _17, "play": _2, "playstation": _2, "plumbing": _2, "plus": _2, "pnc": _2, "pohl": _2, "poker": _2, "politie": _2, "porn": _2, "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": [1, { "id": _5, "kin": _5, "barsy": _3 }], "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": _2, "reviews": _2, "rexroth": _2, "rich": _2, "richardli": _2, "ricoh": _2, "ril": _2, "rio": _2, "rip": [1, { "clan": _3 }], "rocks": [1, { "myddns": _3, "stackit": _3, "lima-city": _3, "webspace": _3 }], "rodeo": _2, "rogers": _2, "room": _2, "rsvp": _2, "rugby": _2, "ruhr": _2, "run": [1, { "development": _3, "ravendb": _3, "servers": _3, "build": _5, "code": _5, "database": _5, "migration": _5, "onporter": _3, "repl": _3, "stackit": _3, "val": [0, { "express": _3, "web": _3 }], "wix": _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, "scb": _2, "schaeffler": _2, "schmidt": _2, "scholarships": _2, "school": _2, "schule": _2, "schwarz": _2, "science": _2, "scot": [1, { "gov": [2, { "service": _3 }] }], "search": _2, "seat": _2, "secure": _2, "security": _2, "seek": _2, "select": _2, "sener": _2, "services": [1, { "loginline": _3 }], "seven": _2, "sew": _2, "sex": _2, "sexy": _2, "sfr": _2, "shangrila": _2, "sharp": _2, "shell": _2, "shia": _2, "shiksha": _2, "shoes": _2, "shop": [1, { "base": _3, "hoplix": _3, "barsy": _3, "barsyonline": _3, "shopware": _3 }], "shopping": _2, "shouji": _2, "show": _2, "silk": _2, "sina": _2, "singles": _2, "site": [1, { "canva": _20, "cloudera": _5, "convex": _3, "cyon": _3, "fnwk": _3, "folionetwork": _3, "fastvps": _3, "jele": _3, "jouwweb": _3, "lelux": _3, "loginline": _3, "barsy": _3, "notion": _3, "omniwe": _3, "opensocial": _3, "madethis": _3, "platformsh": _5, "tst": _5, "byen": _3, "srht": _3, "novecore": _3, "wpsquared": _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, { "diher": _3 }], "song": _2, "sony": _2, "soy": _2, "spa": _2, "space": [1, { "myfast": _3, "heiyu": _3, "hf": [2, { "static": _3 }], "app-ionos": _3, "project": _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, { "barsy": _3, "sellfy": _3, "shopware": _3, "storebase": _3 }], "stream": _2, "studio": _2, "study": _2, "style": _2, "sucks": _2, "supplies": _2, "supply": _2, "support": [1, { "barsy": _3 }], "surf": _2, "surgery": _2, "suzuki": _2, "swatch": _2, "swiss": _2, "sydney": _2, "systems": [1, { "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, { "discourse": _3, "jelastic": _3 }], "tech": [1, { "cleverapps": _3 }], "technology": _17, "temasek": _2, "tennis": _2, "teva": _2, "thd": _2, "theater": _2, "theatre": _2, "tiaa": _2, "tickets": _2, "tienda": _2, "tips": _2, "tires": _2, "tirol": _2, "tjmaxx": _2, "tjx": _2, "tkmaxx": _2, "tmall": _2, "today": [1, { "prequalifyme": _3 }], "tokyo": _2, "tools": _2, "top": [1, { "now-dns": _3, "ntdll": _3, "wadl": _5 }], "toray": _2, "toshiba": _2, "total": _2, "tours": _2, "town": _2, "toyota": _2, "toys": _2, "trade": _2, "trading": _2, "training": _2, "travel": _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": [1, { "aaa": _3 }], "volvo": _2, "vote": _2, "voting": _2, "voto": _2, "voyage": _2, "wales": _2, "walmart": _2, "walter": _2, "wang": _2, "wanggou": _2, "watch": _2, "watches": _2, "weather": _2, "weatherchannel": _2, "webcam": _2, "weber": _2, "website": _52, "wed": _2, "wedding": _2, "weibo": _2, "weir": _2, "whoswho": _2, "wien": _2, "wiki": _52, "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, "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--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, { "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, { "биз": _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, { "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, { "cloud66": _3, "triton": _5, "stackit": _3, "lima": _3 }], "zuerich": _2 }];
    return rules;
})();

;// CONCATENATED MODULE: ./node_modules/.pnpm/tldts@6.1.61/node_modules/tldts/dist/es6/src/suffix-trie.js


/**
 * Lookup parts of domain in Trie
 */
function lookupInTrie(parts, trie, index, allowedMask) {
    let result = null;
    let node = trie;
    while (node !== undefined) {
        // We have a match!
        if ((node[0] & allowedMask) !== 0) {
            result = {
                index: index + 1,
                isIcann: node[0] === 1 /* RULE_TYPE.ICANN */,
                isPrivate: node[0] === 2 /* RULE_TYPE.PRIVATE */,
            };
        }
        // No more `parts` to look for
        if (index === -1) {
            break;
        }
        const succ = node[1];
        node = Object.prototype.hasOwnProperty.call(succ, parts[index])
            ? succ[parts[index]]
            : succ['*'];
        index -= 1;
    }
    return result;
}
/**
 * Check if `hostname` has a valid public suffix in `trie`.
 */
function suffix_trie_suffixLookup(hostname, options, out) {
    var _a;
    if (fast_path(hostname, options, out)) {
        return;
    }
    const hostnameParts = hostname.split('.');
    const allowedMask = (options.allowPrivateDomains ? 2 /* RULE_TYPE.PRIVATE */ : 0) |
        (options.allowIcannDomains ? 1 /* RULE_TYPE.ICANN */ : 0);
    // Look for exceptions
    const 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
    const 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 = (_a = hostnameParts[hostnameParts.length - 1]) !== null && _a !== void 0 ? _a : null;
}

;// CONCATENATED MODULE: ./node_modules/.pnpm/tldts@6.1.61/node_modules/tldts/dist/es6/index.js


// 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.
const RESULT = getEmptyResult();
function parse(url, options = {}) {
    return factory_parseImpl(url, 5 /* FLAG.ALL */, suffix_trie_suffixLookup, options, getEmptyResult());
}
function getHostname(url, options = {}) {
    /*@__INLINE__*/ factory_resetResult(RESULT);
    return factory_parseImpl(url, 0 /* FLAG.HOSTNAME */, suffix_trie_suffixLookup, options, RESULT).hostname;
}
function getPublicSuffix(url, options = {}) {
    /*@__INLINE__*/ factory_resetResult(RESULT);
    return factory_parseImpl(url, 2 /* FLAG.PUBLIC_SUFFIX */, suffix_trie_suffixLookup, options, RESULT)
        .publicSuffix;
}
function es6_getDomain(url, options = {}) {
    /*@__INLINE__*/ factory_resetResult(RESULT);
    return factory_parseImpl(url, 3 /* FLAG.DOMAIN */, suffix_trie_suffixLookup, options, RESULT).domain;
}
function es6_getSubdomain(url, options = {}) {
    /*@__INLINE__*/ resetResult(RESULT);
    return parseImpl(url, 4 /* FLAG.SUB_DOMAIN */, suffixLookup, options, RESULT)
        .subdomain;
}
function es6_getDomainWithoutSuffix(url, options = {}) {
    /*@__INLINE__*/ resetResult(RESULT);
    return parseImpl(url, 5 /* FLAG.ALL */, suffixLookup, options, RESULT)
        .domainWithoutSuffix;
}


/***/ }),

/***/ 70914:
/***/ (function(module, exports) {

var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;(function (global, factory) {
  if (true) {
    !(__WEBPACK_AMD_DEFINE_ARRAY__ = [module], __WEBPACK_AMD_DEFINE_FACTORY__ = (factory),
		__WEBPACK_AMD_DEFINE_RESULT__ = (typeof __WEBPACK_AMD_DEFINE_FACTORY__ === 'function' ?
		(__WEBPACK_AMD_DEFINE_FACTORY__.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__)) : __WEBPACK_AMD_DEFINE_FACTORY__),
		__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
  } else { var mod; }
})(typeof globalThis !== "undefined" ? globalThis : typeof self !== "undefined" ? self : this, function (module) {
  /* webextension-polyfill - v0.12.0 - Tue May 14 2024 18:01:29 */
  /* -*- Mode: indent-tabs-mode: nil; js-indent-level: 2 -*- */
  /* vim: set sts=2 sw=2 et tw=80: */
  /* This Source Code Form is subject to the terms of the Mozilla Public
   * License, v. 2.0. If a copy of the MPL was not distributed with this
   * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
  "use strict";

  if (!(globalThis.chrome && globalThis.chrome.runtime && globalThis.chrome.runtime.id)) {
    throw new Error("This script should only be loaded in a browser extension.");
  }
  if (!(globalThis.browser && globalThis.browser.runtime && globalThis.browser.runtime.id)) {
    const CHROME_SEND_MESSAGE_CALLBACK_NO_RESPONSE_MESSAGE = "The message port closed before a response was received.";

    // Wrapping the bulk of this polyfill in a one-time-use function is a minor
    // optimization for Firefox. Since Spidermonkey does not fully parse the
    // contents of a function until the first time it's called, and since it will
    // never actually need to be called, this allows the polyfill to be included
    // in Firefox nearly for free.
    const wrapAPIs = extensionAPIs => {
      // NOTE: apiMetadata is associated to the content of the api-metadata.json file
      // at build time by replacing the following "include" with the content of the
      // JSON file.
      const apiMetadata = {
        "alarms": {
          "clear": {
            "minArgs": 0,
            "maxArgs": 1
          },
          "clearAll": {
            "minArgs": 0,
            "maxArgs": 0
          },
          "get": {
            "minArgs": 0,
            "maxArgs": 1
          },
          "getAll": {
            "minArgs": 0,
            "maxArgs": 0
          }
        },
        "bookmarks": {
          "create": {
            "minArgs": 1,
            "maxArgs": 1
          },
          "get": {
            "minArgs": 1,
            "maxArgs": 1
          },
          "getChildren": {
            "minArgs": 1,
            "maxArgs": 1
          },
          "getRecent": {
            "minArgs": 1,
            "maxArgs": 1
          },
          "getSubTree": {
            "minArgs": 1,
            "maxArgs": 1
          },
          "getTree": {
            "minArgs": 0,
            "maxArgs": 0
          },
          "move": {
            "minArgs": 2,
            "maxArgs": 2
          },
          "remove": {
            "minArgs": 1,
            "maxArgs": 1
          },
          "removeTree": {
            "minArgs": 1,
            "maxArgs": 1
          },
          "search": {
            "minArgs": 1,
            "maxArgs": 1
          },
          "update": {
            "minArgs": 2,
            "maxArgs": 2
          }
        },
        "browserAction": {
          "disable": {
            "minArgs": 0,
            "maxArgs": 1,
            "fallbackToNoCallback": true
          },
          "enable": {
            "minArgs": 0,
            "maxArgs": 1,
            "fallbackToNoCallback": true
          },
          "getBadgeBackgroundColor": {
            "minArgs": 1,
            "maxArgs": 1
          },
          "getBadgeText": {
            "minArgs": 1,
            "maxArgs": 1
          },
          "getPopup": {
            "minArgs": 1,
            "maxArgs": 1
          },
          "getTitle": {
            "minArgs": 1,
            "maxArgs": 1
          },
          "openPopup": {
            "minArgs": 0,
            "maxArgs": 0
          },
          "setBadgeBackgroundColor": {
            "minArgs": 1,
            "maxArgs": 1,
            "fallbackToNoCallback": true
          },
          "setBadgeText": {
            "minArgs": 1,
            "maxArgs": 1,
            "fallbackToNoCallback": true
          },
          "setIcon": {
            "minArgs": 1,
            "maxArgs": 1
          },
          "setPopup": {
            "minArgs": 1,
            "maxArgs": 1,
            "fallbackToNoCallback": true
          },
          "setTitle": {
            "minArgs": 1,
            "maxArgs": 1,
            "fallbackToNoCallback": true
          }
        },
        "browsingData": {
          "remove": {
            "minArgs": 2,
            "maxArgs": 2
          },
          "removeCache": {
            "minArgs": 1,
            "maxArgs": 1
          },
          "removeCookies": {
            "minArgs": 1,
            "maxArgs": 1
          },
          "removeDownloads": {
            "minArgs": 1,
            "maxArgs": 1
          },
          "removeFormData": {
            "minArgs": 1,
            "maxArgs": 1
          },
          "removeHistory": {
            "minArgs": 1,
            "maxArgs": 1
          },
          "removeLocalStorage": {
            "minArgs": 1,
            "maxArgs": 1
          },
          "removePasswords": {
            "minArgs": 1,
            "maxArgs": 1
          },
          "removePluginData": {
            "minArgs": 1,
            "maxArgs": 1
          },
          "settings": {
            "minArgs": 0,
            "maxArgs": 0
          }
        },
        "commands": {
          "getAll": {
            "minArgs": 0,
            "maxArgs": 0
          }
        },
        "contextMenus": {
          "remove": {
            "minArgs": 1,
            "maxArgs": 1
          },
          "removeAll": {
            "minArgs": 0,
            "maxArgs": 0
          },
          "update": {
            "minArgs": 2,
            "maxArgs": 2
          }
        },
        "cookies": {
          "get": {
            "minArgs": 1,
            "maxArgs": 1
          },
          "getAll": {
            "minArgs": 1,
            "maxArgs": 1
          },
          "getAllCookieStores": {
            "minArgs": 0,
            "maxArgs": 0
          },
          "remove": {
            "minArgs": 1,
            "maxArgs": 1
          },
          "set": {
            "minArgs": 1,
            "maxArgs": 1
          }
        },
        "devtools": {
          "inspectedWindow": {
            "eval": {
              "minArgs": 1,
              "maxArgs": 2,
              "singleCallbackArg": false
            }
          },
          "panels": {
            "create": {
              "minArgs": 3,
              "maxArgs": 3,
              "singleCallbackArg": true
            },
            "elements": {
              "createSidebarPane": {
                "minArgs": 1,
                "maxArgs": 1
              }
            }
          }
        },
        "downloads": {
          "cancel": {
            "minArgs": 1,
            "maxArgs": 1
          },
          "download": {
            "minArgs": 1,
            "maxArgs": 1
          },
          "erase": {
            "minArgs": 1,
            "maxArgs": 1
          },
          "getFileIcon": {
            "minArgs": 1,
            "maxArgs": 2
          },
          "open": {
            "minArgs": 1,
            "maxArgs": 1,
            "fallbackToNoCallback": true
          },
          "pause": {
            "minArgs": 1,
            "maxArgs": 1
          },
          "removeFile": {
            "minArgs": 1,
            "maxArgs": 1
          },
          "resume": {
            "minArgs": 1,
            "maxArgs": 1
          },
          "search": {
            "minArgs": 1,
            "maxArgs": 1
          },
          "show": {
            "minArgs": 1,
            "maxArgs": 1,
            "fallbackToNoCallback": true
          }
        },
        "extension": {
          "isAllowedFileSchemeAccess": {
            "minArgs": 0,
            "maxArgs": 0
          },
          "isAllowedIncognitoAccess": {
            "minArgs": 0,
            "maxArgs": 0
          }
        },
        "history": {
          "addUrl": {
            "minArgs": 1,
            "maxArgs": 1
          },
          "deleteAll": {
            "minArgs": 0,
            "maxArgs": 0
          },
          "deleteRange": {
            "minArgs": 1,
            "maxArgs": 1
          },
          "deleteUrl": {
            "minArgs": 1,
            "maxArgs": 1
          },
          "getVisits": {
            "minArgs": 1,
            "maxArgs": 1
          },
          "search": {
            "minArgs": 1,
            "maxArgs": 1
          }
        },
        "i18n": {
          "detectLanguage": {
            "minArgs": 1,
            "maxArgs": 1
          },
          "getAcceptLanguages": {
            "minArgs": 0,
            "maxArgs": 0
          }
        },
        "identity": {
          "launchWebAuthFlow": {
            "minArgs": 1,
            "maxArgs": 1
          }
        },
        "idle": {
          "queryState": {
            "minArgs": 1,
            "maxArgs": 1
          }
        },
        "management": {
          "get": {
            "minArgs": 1,
            "maxArgs": 1
          },
          "getAll": {
            "minArgs": 0,
            "maxArgs": 0
          },
          "getSelf": {
            "minArgs": 0,
            "maxArgs": 0
          },
          "setEnabled": {
            "minArgs": 2,
            "maxArgs": 2
          },
          "uninstallSelf": {
            "minArgs": 0,
            "maxArgs": 1
          }
        },
        "notifications": {
          "clear": {
            "minArgs": 1,
            "maxArgs": 1
          },
          "create": {
            "minArgs": 1,
            "maxArgs": 2
          },
          "getAll": {
            "minArgs": 0,
            "maxArgs": 0
          },
          "getPermissionLevel": {
            "minArgs": 0,
            "maxArgs": 0
          },
          "update": {
            "minArgs": 2,
            "maxArgs": 2
          }
        },
        "pageAction": {
          "getPopup": {
            "minArgs": 1,
            "maxArgs": 1
          },
          "getTitle": {
            "minArgs": 1,
            "maxArgs": 1
          },
          "hide": {
            "minArgs": 1,
            "maxArgs": 1,
            "fallbackToNoCallback": true
          },
          "setIcon": {
            "minArgs": 1,
            "maxArgs": 1
          },
          "setPopup": {
            "minArgs": 1,
            "maxArgs": 1,
            "fallbackToNoCallback": true
          },
          "setTitle": {
            "minArgs": 1,
            "maxArgs": 1,
            "fallbackToNoCallback": true
          },
          "show": {
            "minArgs": 1,
            "maxArgs": 1,
            "fallbackToNoCallback": true
          }
        },
        "permissions": {
          "contains": {
            "minArgs": 1,
            "maxArgs": 1
          },
          "getAll": {
            "minArgs": 0,
            "maxArgs": 0
          },
          "remove": {
            "minArgs": 1,
            "maxArgs": 1
          },
          "request": {
            "minArgs": 1,
            "maxArgs": 1
          }
        },
        "runtime": {
          "getBackgroundPage": {
            "minArgs": 0,
            "maxArgs": 0
          },
          "getPlatformInfo": {
            "minArgs": 0,
            "maxArgs": 0
          },
          "openOptionsPage": {
            "minArgs": 0,
            "maxArgs": 0
          },
          "requestUpdateCheck": {
            "minArgs": 0,
            "maxArgs": 0
          },
          "sendMessage": {
            "minArgs": 1,
            "maxArgs": 3
          },
          "sendNativeMessage": {
            "minArgs": 2,
            "maxArgs": 2
          },
          "setUninstallURL": {
            "minArgs": 1,
            "maxArgs": 1
          }
        },
        "sessions": {
          "getDevices": {
            "minArgs": 0,
            "maxArgs": 1
          },
          "getRecentlyClosed": {
            "minArgs": 0,
            "maxArgs": 1
          },
          "restore": {
            "minArgs": 0,
            "maxArgs": 1
          }
        },
        "storage": {
          "local": {
            "clear": {
              "minArgs": 0,
              "maxArgs": 0
            },
            "get": {
              "minArgs": 0,
              "maxArgs": 1
            },
            "getBytesInUse": {
              "minArgs": 0,
              "maxArgs": 1
            },
            "remove": {
              "minArgs": 1,
              "maxArgs": 1
            },
            "set": {
              "minArgs": 1,
              "maxArgs": 1
            }
          },
          "managed": {
            "get": {
              "minArgs": 0,
              "maxArgs": 1
            },
            "getBytesInUse": {
              "minArgs": 0,
              "maxArgs": 1
            }
          },
          "sync": {
            "clear": {
              "minArgs": 0,
              "maxArgs": 0
            },
            "get": {
              "minArgs": 0,
              "maxArgs": 1
            },
            "getBytesInUse": {
              "minArgs": 0,
              "maxArgs": 1
            },
            "remove": {
              "minArgs": 1,
              "maxArgs": 1
            },
            "set": {
              "minArgs": 1,
              "maxArgs": 1
            }
          }
        },
        "tabs": {
          "captureVisibleTab": {
            "minArgs": 0,
            "maxArgs": 2
          },
          "create": {
            "minArgs": 1,
            "maxArgs": 1
          },
          "detectLanguage": {
            "minArgs": 0,
            "maxArgs": 1
          },
          "discard": {
            "minArgs": 0,
            "maxArgs": 1
          },
          "duplicate": {
            "minArgs": 1,
            "maxArgs": 1
          },
          "executeScript": {
            "minArgs": 1,
            "maxArgs": 2
          },
          "get": {
            "minArgs": 1,
            "maxArgs": 1
          },
          "getCurrent": {
            "minArgs": 0,
            "maxArgs": 0
          },
          "getZoom": {
            "minArgs": 0,
            "maxArgs": 1
          },
          "getZoomSettings": {
            "minArgs": 0,
            "maxArgs": 1
          },
          "goBack": {
            "minArgs": 0,
            "maxArgs": 1
          },
          "goForward": {
            "minArgs": 0,
            "maxArgs": 1
          },
          "highlight": {
            "minArgs": 1,
            "maxArgs": 1
          },
          "insertCSS": {
            "minArgs": 1,
            "maxArgs": 2
          },
          "move": {
            "minArgs": 2,
            "maxArgs": 2
          },
          "query": {
            "minArgs": 1,
            "maxArgs": 1
          },
          "reload": {
            "minArgs": 0,
            "maxArgs": 2
          },
          "remove": {
            "minArgs": 1,
            "maxArgs": 1
          },
          "removeCSS": {
            "minArgs": 1,
            "maxArgs": 2
          },
          "sendMessage": {
            "minArgs": 2,
            "maxArgs": 3
          },
          "setZoom": {
            "minArgs": 1,
            "maxArgs": 2
          },
          "setZoomSettings": {
            "minArgs": 1,
            "maxArgs": 2
          },
          "update": {
            "minArgs": 1,
            "maxArgs": 2
          }
        },
        "topSites": {
          "get": {
            "minArgs": 0,
            "maxArgs": 0
          }
        },
        "webNavigation": {
          "getAllFrames": {
            "minArgs": 1,
            "maxArgs": 1
          },
          "getFrame": {
            "minArgs": 1,
            "maxArgs": 1
          }
        },
        "webRequest": {
          "handlerBehaviorChanged": {
            "minArgs": 0,
            "maxArgs": 0
          }
        },
        "windows": {
          "create": {
            "minArgs": 0,
            "maxArgs": 1
          },
          "get": {
            "minArgs": 1,
            "maxArgs": 2
          },
          "getAll": {
            "minArgs": 0,
            "maxArgs": 1
          },
          "getCurrent": {
            "minArgs": 0,
            "maxArgs": 1
          },
          "getLastFocused": {
            "minArgs": 0,
            "maxArgs": 1
          },
          "remove": {
            "minArgs": 1,
            "maxArgs": 1
          },
          "update": {
            "minArgs": 2,
            "maxArgs": 2
          }
        }
      };
      if (Object.keys(apiMetadata).length === 0) {
        throw new Error("api-metadata.json has not been included in browser-polyfill");
      }

      /**
       * A WeakMap subclass which creates and stores a value for any key which does
       * not exist when accessed, but behaves exactly as an ordinary WeakMap
       * otherwise.
       *
       * @param {function} createItem
       *        A function which will be called in order to create the value for any
       *        key which does not exist, the first time it is accessed. The
       *        function receives, as its only argument, the key being created.
       */
      class DefaultWeakMap extends WeakMap {
        constructor(createItem, items = undefined) {
          super(items);
          this.createItem = createItem;
        }
        get(key) {
          if (!this.has(key)) {
            this.set(key, this.createItem(key));
          }
          return super.get(key);
        }
      }

      /**
       * Returns true if the given object is an object with a `then` method, and can
       * therefore be assumed to behave as a Promise.
       *
       * @param {*} value The value to test.
       * @returns {boolean} True if the value is thenable.
       */
      const isThenable = value => {
        return value && typeof value === "object" && typeof value.then === "function";
      };

      /**
       * Creates and returns a function which, when called, will resolve or reject
       * the given promise based on how it is called:
       *
       * - If, when called, `chrome.runtime.lastError` contains a non-null object,
       *   the promise is rejected with that value.
       * - If the function is called with exactly one argument, the promise is
       *   resolved to that value.
       * - Otherwise, the promise is resolved to an array containing all of the
       *   function's arguments.
       *
       * @param {object} promise
       *        An object containing the resolution and rejection functions of a
       *        promise.
       * @param {function} promise.resolve
       *        The promise's resolution function.
       * @param {function} promise.reject
       *        The promise's rejection function.
       * @param {object} metadata
       *        Metadata about the wrapped method which has created the callback.
       * @param {boolean} metadata.singleCallbackArg
       *        Whether or not the promise is resolved with only the first
       *        argument of the callback, alternatively an array of all the
       *        callback arguments is resolved. By default, if the callback
       *        function is invoked with only a single argument, that will be
       *        resolved to the promise, while all arguments will be resolved as
       *        an array if multiple are given.
       *
       * @returns {function}
       *        The generated callback function.
       */
      const makeCallback = (promise, metadata) => {
        return (...callbackArgs) => {
          if (extensionAPIs.runtime.lastError) {
            promise.reject(new Error(extensionAPIs.runtime.lastError.message));
          } else if (metadata.singleCallbackArg || callbackArgs.length <= 1 && metadata.singleCallbackArg !== false) {
            promise.resolve(callbackArgs[0]);
          } else {
            promise.resolve(callbackArgs);
          }
        };
      };
      const pluralizeArguments = numArgs => numArgs == 1 ? "argument" : "arguments";

      /**
       * Creates a wrapper function for a method with the given name and metadata.
       *
       * @param {string} name
       *        The name of the method which is being wrapped.
       * @param {object} metadata
       *        Metadata about the method being wrapped.
       * @param {integer} metadata.minArgs
       *        The minimum number of arguments which must be passed to the
       *        function. If called with fewer than this number of arguments, the
       *        wrapper will raise an exception.
       * @param {integer} metadata.maxArgs
       *        The maximum number of arguments which may be passed to the
       *        function. If called with more than this number of arguments, the
       *        wrapper will raise an exception.
       * @param {boolean} metadata.singleCallbackArg
       *        Whether or not the promise is resolved with only the first
       *        argument of the callback, alternatively an array of all the
       *        callback arguments is resolved. By default, if the callback
       *        function is invoked with only a single argument, that will be
       *        resolved to the promise, while all arguments will be resolved as
       *        an array if multiple are given.
       *
       * @returns {function(object, ...*)}
       *       The generated wrapper function.
       */
      const wrapAsyncFunction = (name, metadata) => {
        return function asyncFunctionWrapper(target, ...args) {
          if (args.length < metadata.minArgs) {
            throw new Error(`Expected at least ${metadata.minArgs} ${pluralizeArguments(metadata.minArgs)} for ${name}(), got ${args.length}`);
          }
          if (args.length > metadata.maxArgs) {
            throw new Error(`Expected at most ${metadata.maxArgs} ${pluralizeArguments(metadata.maxArgs)} for ${name}(), got ${args.length}`);
          }
          return new Promise((resolve, reject) => {
            if (metadata.fallbackToNoCallback) {
              // This API method has currently no callback on Chrome, but it return a promise on Firefox,
              // and so the polyfill will try to call it with a callback first, and it will fallback
              // to not passing the callback if the first call fails.
              try {
                target[name](...args, makeCallback({
                  resolve,
                  reject
                }, metadata));
              } catch (cbError) {
                console.warn(`${name} API method doesn't seem to support the callback parameter, ` + "falling back to call it without a callback: ", cbError);
                target[name](...args);

                // Update the API method metadata, so that the next API calls will not try to
                // use the unsupported callback anymore.
                metadata.fallbackToNoCallback = false;
                metadata.noCallback = true;
                resolve();
              }
            } else if (metadata.noCallback) {
              target[name](...args);
              resolve();
            } else {
              target[name](...args, makeCallback({
                resolve,
                reject
              }, metadata));
            }
          });
        };
      };

      /**
       * Wraps an existing method of the target object, so that calls to it are
       * intercepted by the given wrapper function. The wrapper function receives,
       * as its first argument, the original `target` object, followed by each of
       * the arguments passed to the original method.
       *
       * @param {object} target
       *        The original target object that the wrapped method belongs to.
       * @param {function} method
       *        The method being wrapped. This is used as the target of the Proxy
       *        object which is created to wrap the method.
       * @param {function} wrapper
       *        The wrapper function which is called in place of a direct invocation
       *        of the wrapped method.
       *
       * @returns {Proxy<function>}
       *        A Proxy object for the given method, which invokes the given wrapper
       *        method in its place.
       */
      const wrapMethod = (target, method, wrapper) => {
        return new Proxy(method, {
          apply(targetMethod, thisObj, args) {
            return wrapper.call(thisObj, target, ...args);
          }
        });
      };
      let hasOwnProperty = Function.call.bind(Object.prototype.hasOwnProperty);

      /**
       * Wraps an object in a Proxy which intercepts and wraps certain methods
       * based on the given `wrappers` and `metadata` objects.
       *
       * @param {object} target
       *        The target object to wrap.
       *
       * @param {object} [wrappers = {}]
       *        An object tree containing wrapper functions for special cases. Any
       *        function present in this object tree is called in place of the
       *        method in the same location in the `target` object tree. These
       *        wrapper methods are invoked as described in {@see wrapMethod}.
       *
       * @param {object} [metadata = {}]
       *        An object tree containing metadata used to automatically generate
       *        Promise-based wrapper functions for asynchronous. Any function in
       *        the `target` object tree which has a corresponding metadata object
       *        in the same location in the `metadata` tree is replaced with an
       *        automatically-generated wrapper function, as described in
       *        {@see wrapAsyncFunction}
       *
       * @returns {Proxy<object>}
       */
      const wrapObject = (target, wrappers = {}, metadata = {}) => {
        let cache = Object.create(null);
        let handlers = {
          has(proxyTarget, prop) {
            return prop in target || prop in cache;
          },
          get(proxyTarget, prop, receiver) {
            if (prop in cache) {
              return cache[prop];
            }
            if (!(prop in target)) {
              return undefined;
            }
            let value = target[prop];
            if (typeof value === "function") {
              // This is a method on the underlying object. Check if we need to do
              // any wrapping.

              if (typeof wrappers[prop] === "function") {
                // We have a special-case wrapper for this method.
                value = wrapMethod(target, target[prop], wrappers[prop]);
              } else if (hasOwnProperty(metadata, prop)) {
                // This is an async method that we have metadata for. Create a
                // Promise wrapper for it.
                let wrapper = wrapAsyncFunction(prop, metadata[prop]);
                value = wrapMethod(target, target[prop], wrapper);
              } else {
                // This is a method that we don't know or care about. Return the
                // original method, bound to the underlying object.
                value = value.bind(target);
              }
            } else if (typeof value === "object" && value !== null && (hasOwnProperty(wrappers, prop) || hasOwnProperty(metadata, prop))) {
              // This is an object that we need to do some wrapping for the children
              // of. Create a sub-object wrapper for it with the appropriate child
              // metadata.
              value = wrapObject(value, wrappers[prop], metadata[prop]);
            } else if (hasOwnProperty(metadata, "*")) {
              // Wrap all properties in * namespace.
              value = wrapObject(value, wrappers[prop], metadata["*"]);
            } else {
              // We don't need to do any wrapping for this property,
              // so just forward all access to the underlying object.
              Object.defineProperty(cache, prop, {
                configurable: true,
                enumerable: true,
                get() {
                  return target[prop];
                },
                set(value) {
                  target[prop] = value;
                }
              });
              return value;
            }
            cache[prop] = value;
            return value;
          },
          set(proxyTarget, prop, value, receiver) {
            if (prop in cache) {
              cache[prop] = value;
            } else {
              target[prop] = value;
            }
            return true;
          },
          defineProperty(proxyTarget, prop, desc) {
            return Reflect.defineProperty(cache, prop, desc);
          },
          deleteProperty(proxyTarget, prop) {
            return Reflect.deleteProperty(cache, prop);
          }
        };

        // Per contract of the Proxy API, the "get" proxy handler must return the
        // original value of the target if that value is declared read-only and
        // non-configurable. For this reason, we create an object with the
        // prototype set to `target` instead of using `target` directly.
        // Otherwise we cannot return a custom object for APIs that
        // are declared read-only and non-configurable, such as `chrome.devtools`.
        //
        // The proxy handlers themselves will still use the original `target`
        // instead of the `proxyTarget`, so that the methods and properties are
        // dereferenced via the original targets.
        let proxyTarget = Object.create(target);
        return new Proxy(proxyTarget, handlers);
      };

      /**
       * Creates a set of wrapper functions for an event object, which handles
       * wrapping of listener functions that those messages are passed.
       *
       * A single wrapper is created for each listener function, and stored in a
       * map. Subsequent calls to `addListener`, `hasListener`, or `removeListener`
       * retrieve the original wrapper, so that  attempts to remove a
       * previously-added listener work as expected.
       *
       * @param {DefaultWeakMap<function, function>} wrapperMap
       *        A DefaultWeakMap object which will create the appropriate wrapper
       *        for a given listener function when one does not exist, and retrieve
       *        an existing one when it does.
       *
       * @returns {object}
       */
      const wrapEvent = wrapperMap => ({
        addListener(target, listener, ...args) {
          target.addListener(wrapperMap.get(listener), ...args);
        },
        hasListener(target, listener) {
          return target.hasListener(wrapperMap.get(listener));
        },
        removeListener(target, listener) {
          target.removeListener(wrapperMap.get(listener));
        }
      });
      const onRequestFinishedWrappers = new DefaultWeakMap(listener => {
        if (typeof listener !== "function") {
          return listener;
        }

        /**
         * Wraps an onRequestFinished listener function so that it will return a
         * `getContent()` property which returns a `Promise` rather than using a
         * callback API.
         *
         * @param {object} req
         *        The HAR entry object representing the network request.
         */
        return function onRequestFinished(req) {
          const wrappedReq = wrapObject(req, {} /* wrappers */, {
            getContent: {
              minArgs: 0,
              maxArgs: 0
            }
          });
          listener(wrappedReq);
        };
      });
      const onMessageWrappers = new DefaultWeakMap(listener => {
        if (typeof listener !== "function") {
          return listener;
        }

        /**
         * Wraps a message listener function so that it may send responses based on
         * its return value, rather than by returning a sentinel value and calling a
         * callback. If the listener function returns a Promise, the response is
         * sent when the promise either resolves or rejects.
         *
         * @param {*} message
         *        The message sent by the other end of the channel.
         * @param {object} sender
         *        Details about the sender of the message.
         * @param {function(*)} sendResponse
         *        A callback which, when called with an arbitrary argument, sends
         *        that value as a response.
         * @returns {boolean}
         *        True if the wrapped listener returned a Promise, which will later
         *        yield a response. False otherwise.
         */
        return function onMessage(message, sender, sendResponse) {
          let didCallSendResponse = false;
          let wrappedSendResponse;
          let sendResponsePromise = new Promise(resolve => {
            wrappedSendResponse = function (response) {
              didCallSendResponse = true;
              resolve(response);
            };
          });
          let result;
          try {
            result = listener(message, sender, wrappedSendResponse);
          } catch (err) {
            result = Promise.reject(err);
          }
          const isResultThenable = result !== true && isThenable(result);

          // If the listener didn't returned true or a Promise, or called
          // wrappedSendResponse synchronously, we can exit earlier
          // because there will be no response sent from this listener.
          if (result !== true && !isResultThenable && !didCallSendResponse) {
            return false;
          }

          // A small helper to send the message if the promise resolves
          // and an error if the promise rejects (a wrapped sendMessage has
          // to translate the message into a resolved promise or a rejected
          // promise).
          const sendPromisedResult = promise => {
            promise.then(msg => {
              // send the message value.
              sendResponse(msg);
            }, error => {
              // Send a JSON representation of the error if the rejected value
              // is an instance of error, or the object itself otherwise.
              let message;
              if (error && (error instanceof Error || typeof error.message === "string")) {
                message = error.message;
              } else {
                message = "An unexpected error occurred";
              }
              sendResponse({
                __mozWebExtensionPolyfillReject__: true,
                message
              });
            }).catch(err => {
              // Print an error on the console if unable to send the response.
              console.error("Failed to send onMessage rejected reply", err);
            });
          };

          // If the listener returned a Promise, send the resolved value as a
          // result, otherwise wait the promise related to the wrappedSendResponse
          // callback to resolve and send it as a response.
          if (isResultThenable) {
            sendPromisedResult(result);
          } else {
            sendPromisedResult(sendResponsePromise);
          }

          // Let Chrome know that the listener is replying.
          return true;
        };
      });
      const wrappedSendMessageCallback = ({
        reject,
        resolve
      }, reply) => {
        if (extensionAPIs.runtime.lastError) {
          // Detect when none of the listeners replied to the sendMessage call and resolve
          // the promise to undefined as in Firefox.
          // See https://github.com/mozilla/webextension-polyfill/issues/130
          if (extensionAPIs.runtime.lastError.message === CHROME_SEND_MESSAGE_CALLBACK_NO_RESPONSE_MESSAGE) {
            resolve();
          } else {
            reject(new Error(extensionAPIs.runtime.lastError.message));
          }
        } else if (reply && reply.__mozWebExtensionPolyfillReject__) {
          // Convert back the JSON representation of the error into
          // an Error instance.
          reject(new Error(reply.message));
        } else {
          resolve(reply);
        }
      };
      const wrappedSendMessage = (name, metadata, apiNamespaceObj, ...args) => {
        if (args.length < metadata.minArgs) {
          throw new Error(`Expected at least ${metadata.minArgs} ${pluralizeArguments(metadata.minArgs)} for ${name}(), got ${args.length}`);
        }
        if (args.length > metadata.maxArgs) {
          throw new Error(`Expected at most ${metadata.maxArgs} ${pluralizeArguments(metadata.maxArgs)} for ${name}(), got ${args.length}`);
        }
        return new Promise((resolve, reject) => {
          const wrappedCb = wrappedSendMessageCallback.bind(null, {
            resolve,
            reject
          });
          args.push(wrappedCb);
          apiNamespaceObj.sendMessage(...args);
        });
      };
      const staticWrappers = {
        devtools: {
          network: {
            onRequestFinished: wrapEvent(onRequestFinishedWrappers)
          }
        },
        runtime: {
          onMessage: wrapEvent(onMessageWrappers),
          onMessageExternal: wrapEvent(onMessageWrappers),
          sendMessage: wrappedSendMessage.bind(null, "sendMessage", {
            minArgs: 1,
            maxArgs: 3
          })
        },
        tabs: {
          sendMessage: wrappedSendMessage.bind(null, "sendMessage", {
            minArgs: 2,
            maxArgs: 3
          })
        }
      };
      const settingMetadata = {
        clear: {
          minArgs: 1,
          maxArgs: 1
        },
        get: {
          minArgs: 1,
          maxArgs: 1
        },
        set: {
          minArgs: 1,
          maxArgs: 1
        }
      };
      apiMetadata.privacy = {
        network: {
          "*": settingMetadata
        },
        services: {
          "*": settingMetadata
        },
        websites: {
          "*": settingMetadata
        }
      };
      return wrapObject(extensionAPIs, staticWrappers, apiMetadata);
    };

    // The build process adds a UMD wrapper around this file, which makes the
    // `module` variable available.
    module.exports = wrapAPIs(chrome);
  } else {
    module.exports = globalThis.browser;
  }
});


/***/ }),

/***/ 7462:
/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {

"use strict";
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "Z": () => (__WEBPACK_DEFAULT_EXPORT__)
/* harmony export */ });
/* harmony import */ var _hashClear_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(17307);
/* harmony import */ var _hashDelete_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(19668);
/* harmony import */ var _hashGet_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(71450);
/* harmony import */ var _hashHas_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(10423);
/* harmony import */ var _hashSet_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(24734);






/**
 * Creates a hash object.
 *
 * @private
 * @constructor
 * @param {Array} [entries] The key-value pairs to cache.
 */
function Hash(entries) {
  var index = -1,
      length = entries == null ? 0 : entries.length;

  this.clear();
  while (++index < length) {
    var entry = entries[index];
    this.set(entry[0], entry[1]);
  }
}

// Add methods to `Hash`.
Hash.prototype.clear = _hashClear_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"] */ .Z;
Hash.prototype['delete'] = _hashDelete_js__WEBPACK_IMPORTED_MODULE_1__/* ["default"] */ .Z;
Hash.prototype.get = _hashGet_js__WEBPACK_IMPORTED_MODULE_2__/* ["default"] */ .Z;
Hash.prototype.has = _hashHas_js__WEBPACK_IMPORTED_MODULE_3__/* ["default"] */ .Z;
Hash.prototype.set = _hashSet_js__WEBPACK_IMPORTED_MODULE_4__/* ["default"] */ .Z;

/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (Hash);


/***/ }),

/***/ 9932:
/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {

"use strict";
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "Z": () => (__WEBPACK_DEFAULT_EXPORT__)
/* harmony export */ });
/* harmony import */ var _listCacheClear_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(22737);
/* harmony import */ var _listCacheDelete_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(53229);
/* harmony import */ var _listCacheGet_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(80438);
/* harmony import */ var _listCacheHas_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(73375);
/* harmony import */ var _listCacheSet_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(24957);






/**
 * Creates an list cache object.
 *
 * @private
 * @constructor
 * @param {Array} [entries] The key-value pairs to cache.
 */
function ListCache(entries) {
  var index = -1,
      length = entries == null ? 0 : entries.length;

  this.clear();
  while (++index < length) {
    var entry = entries[index];
    this.set(entry[0], entry[1]);
  }
}

// Add methods to `ListCache`.
ListCache.prototype.clear = _listCacheClear_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"] */ .Z;
ListCache.prototype['delete'] = _listCacheDelete_js__WEBPACK_IMPORTED_MODULE_1__/* ["default"] */ .Z;
ListCache.prototype.get = _listCacheGet_js__WEBPACK_IMPORTED_MODULE_2__/* ["default"] */ .Z;
ListCache.prototype.has = _listCacheHas_js__WEBPACK_IMPORTED_MODULE_3__/* ["default"] */ .Z;
ListCache.prototype.set = _listCacheSet_js__WEBPACK_IMPORTED_MODULE_4__/* ["default"] */ .Z;

/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (ListCache);


/***/ }),

/***/ 3806:
/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {

"use strict";
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "Z": () => (__WEBPACK_DEFAULT_EXPORT__)
/* harmony export */ });
/* harmony import */ var _getNative_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(80156);
/* harmony import */ var _root_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(5665);



/* Built-in method references that are verified to be native. */
var Map = (0,_getNative_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"] */ .Z)(_root_js__WEBPACK_IMPORTED_MODULE_1__/* ["default"] */ .Z, 'Map');

/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (Map);


/***/ }),

/***/ 14356:
/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {

"use strict";
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "Z": () => (__WEBPACK_DEFAULT_EXPORT__)
/* harmony export */ });
/* harmony import */ var _mapCacheClear_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(27697);
/* harmony import */ var _mapCacheDelete_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(72633);
/* harmony import */ var _mapCacheGet_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(59465);
/* harmony import */ var _mapCacheHas_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(62117);
/* harmony import */ var _mapCacheSet_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(69481);






/**
 * Creates a map cache object to store key-value pairs.
 *
 * @private
 * @constructor
 * @param {Array} [entries] The key-value pairs to cache.
 */
function MapCache(entries) {
  var index = -1,
      length = entries == null ? 0 : entries.length;

  this.clear();
  while (++index < length) {
    var entry = entries[index];
    this.set(entry[0], entry[1]);
  }
}

// Add methods to `MapCache`.
MapCache.prototype.clear = _mapCacheClear_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"] */ .Z;
MapCache.prototype['delete'] = _mapCacheDelete_js__WEBPACK_IMPORTED_MODULE_1__/* ["default"] */ .Z;
MapCache.prototype.get = _mapCacheGet_js__WEBPACK_IMPORTED_MODULE_2__/* ["default"] */ .Z;
MapCache.prototype.has = _mapCacheHas_js__WEBPACK_IMPORTED_MODULE_3__/* ["default"] */ .Z;
MapCache.prototype.set = _mapCacheSet_js__WEBPACK_IMPORTED_MODULE_4__/* ["default"] */ .Z;

/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (MapCache);


/***/ }),

/***/ 74225:
/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {

"use strict";

// EXPORTS
__webpack_require__.d(__webpack_exports__, {
  "Z": () => (/* binding */ _Stack)
});

// EXTERNAL MODULE: ./node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/_ListCache.js
var _ListCache = __webpack_require__(9932);
;// CONCATENATED MODULE: ./node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/_stackClear.js


/**
 * Removes all key-value entries from the stack.
 *
 * @private
 * @name clear
 * @memberOf Stack
 */
function stackClear() {
  this.__data__ = new _ListCache/* default */.Z;
  this.size = 0;
}

/* harmony default export */ const _stackClear = (stackClear);

;// CONCATENATED MODULE: ./node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/_stackDelete.js
/**
 * Removes `key` and its value from the stack.
 *
 * @private
 * @name delete
 * @memberOf Stack
 * @param {string} key The key of the value to remove.
 * @returns {boolean} Returns `true` if the entry was removed, else `false`.
 */
function stackDelete(key) {
  var data = this.__data__,
      result = data['delete'](key);

  this.size = data.size;
  return result;
}

/* harmony default export */ const _stackDelete = (stackDelete);

;// CONCATENATED MODULE: ./node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/_stackGet.js
/**
 * Gets the stack value for `key`.
 *
 * @private
 * @name get
 * @memberOf Stack
 * @param {string} key The key of the value to get.
 * @returns {*} Returns the entry value.
 */
function stackGet(key) {
  return this.__data__.get(key);
}

/* harmony default export */ const _stackGet = (stackGet);

;// CONCATENATED MODULE: ./node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/_stackHas.js
/**
 * Checks if a stack value for `key` exists.
 *
 * @private
 * @name has
 * @memberOf Stack
 * @param {string} key The key of the entry to check.
 * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.
 */
function stackHas(key) {
  return this.__data__.has(key);
}

/* harmony default export */ const _stackHas = (stackHas);

// EXTERNAL MODULE: ./node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/_Map.js
var _Map = __webpack_require__(3806);
// EXTERNAL MODULE: ./node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/_MapCache.js
var _MapCache = __webpack_require__(14356);
;// CONCATENATED MODULE: ./node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/_stackSet.js




/** Used as the size to enable large array optimizations. */
var LARGE_ARRAY_SIZE = 200;

/**
 * Sets the stack `key` to `value`.
 *
 * @private
 * @name set
 * @memberOf Stack
 * @param {string} key The key of the value to set.
 * @param {*} value The value to set.
 * @returns {Object} Returns the stack cache instance.
 */
function stackSet(key, value) {
  var data = this.__data__;
  if (data instanceof _ListCache/* default */.Z) {
    var pairs = data.__data__;
    if (!_Map/* default */.Z || (pairs.length < LARGE_ARRAY_SIZE - 1)) {
      pairs.push([key, value]);
      this.size = ++data.size;
      return this;
    }
    data = this.__data__ = new _MapCache/* default */.Z(pairs);
  }
  data.set(key, value);
  this.size = data.size;
  return this;
}

/* harmony default export */ const _stackSet = (stackSet);

;// CONCATENATED MODULE: ./node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/_Stack.js







/**
 * Creates a stack cache object to store key-value pairs.
 *
 * @private
 * @constructor
 * @param {Array} [entries] The key-value pairs to cache.
 */
function Stack(entries) {
  var data = this.__data__ = new _ListCache/* default */.Z(entries);
  this.size = data.size;
}

// Add methods to `Stack`.
Stack.prototype.clear = _stackClear;
Stack.prototype['delete'] = _stackDelete;
Stack.prototype.get = _stackGet;
Stack.prototype.has = _stackHas;
Stack.prototype.set = _stackSet;

/* harmony default export */ const _Stack = (Stack);


/***/ }),

/***/ 19474:
/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {

"use strict";
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "Z": () => (__WEBPACK_DEFAULT_EXPORT__)
/* harmony export */ });
/* harmony import */ var _root_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(5665);


/** Built-in value references. */
var Symbol = _root_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"].Symbol */ .Z.Symbol;

/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (Symbol);


/***/ }),

/***/ 9128:
/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {

"use strict";
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "Z": () => (__WEBPACK_DEFAULT_EXPORT__)
/* harmony export */ });
/* harmony import */ var _root_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(5665);


/** Built-in value references. */
var Uint8Array = _root_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"].Uint8Array */ .Z.Uint8Array;

/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (Uint8Array);


/***/ }),

/***/ 68180:
/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {

"use strict";

// EXPORTS
__webpack_require__.d(__webpack_exports__, {
  "Z": () => (/* binding */ _arrayLikeKeys)
});

;// CONCATENATED MODULE: ./node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/_baseTimes.js
/**
 * The base implementation of `_.times` without support for iteratee shorthands
 * or max array length checks.
 *
 * @private
 * @param {number} n The number of times to invoke `iteratee`.
 * @param {Function} iteratee The function invoked per iteration.
 * @returns {Array} Returns the array of results.
 */
function baseTimes(n, iteratee) {
  var index = -1,
      result = Array(n);

  while (++index < n) {
    result[index] = iteratee(index);
  }
  return result;
}

/* harmony default export */ const _baseTimes = (baseTimes);

// EXTERNAL MODULE: ./node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/isArguments.js
var isArguments = __webpack_require__(66161);
// EXTERNAL MODULE: ./node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/isArray.js
var isArray = __webpack_require__(24254);
// EXTERNAL MODULE: ./node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/isBuffer.js
var isBuffer = __webpack_require__(5950);
// EXTERNAL MODULE: ./node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/_isIndex.js
var _isIndex = __webpack_require__(91661);
// EXTERNAL MODULE: ./node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/isTypedArray.js
var isTypedArray = __webpack_require__(90284);
;// CONCATENATED MODULE: ./node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/_arrayLikeKeys.js







/** Used for built-in method references. */
var objectProto = Object.prototype;

/** Used to check objects for own properties. */
var _arrayLikeKeys_hasOwnProperty = objectProto.hasOwnProperty;

/**
 * Creates an array of the enumerable property names of the array-like `value`.
 *
 * @private
 * @param {*} value The value to query.
 * @param {boolean} inherited Specify returning inherited property names.
 * @returns {Array} Returns the array of property names.
 */
function arrayLikeKeys(value, inherited) {
  var isArr = (0,isArray/* default */.Z)(value),
      isArg = !isArr && (0,isArguments/* default */.Z)(value),
      isBuff = !isArr && !isArg && (0,isBuffer/* default */.Z)(value),
      isType = !isArr && !isArg && !isBuff && (0,isTypedArray/* default */.Z)(value),
      skipIndexes = isArr || isArg || isBuff || isType,
      result = skipIndexes ? _baseTimes(value.length, String) : [],
      length = result.length;

  for (var key in value) {
    if ((inherited || _arrayLikeKeys_hasOwnProperty.call(value, key)) &&
        !(skipIndexes && (
           // Safari 9 has enumerable `arguments.length` in strict mode.
           key == 'length' ||
           // Node.js 0.10 has enumerable non-index properties on buffers.
           (isBuff && (key == 'offset' || key == 'parent')) ||
           // PhantomJS 2 has enumerable non-index properties on typed arrays.
           (isType && (key == 'buffer' || key == 'byteLength' || key == 'byteOffset')) ||
           // Skip index properties.
           (0,_isIndex/* default */.Z)(key, length)
        ))) {
      result.push(key);
    }
  }
  return result;
}

/* harmony default export */ const _arrayLikeKeys = (arrayLikeKeys);


/***/ }),

/***/ 59606:
/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {

"use strict";
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "Z": () => (__WEBPACK_DEFAULT_EXPORT__)
/* harmony export */ });
/**
 * A specialized version of `_.map` for arrays without support for iteratee
 * shorthands.
 *
 * @private
 * @param {Array} [array] The array to iterate over.
 * @param {Function} iteratee The function invoked per iteration.
 * @returns {Array} Returns the new mapped array.
 */
function arrayMap(array, iteratee) {
  var index = -1,
      length = array == null ? 0 : array.length,
      result = Array(length);

  while (++index < length) {
    result[index] = iteratee(array[index], index, array);
  }
  return result;
}

/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (arrayMap);


/***/ }),

/***/ 48176:
/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {

"use strict";
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "Z": () => (__WEBPACK_DEFAULT_EXPORT__)
/* harmony export */ });
/**
 * Appends the elements of `values` to `array`.
 *
 * @private
 * @param {Array} array The array to modify.
 * @param {Array} values The values to append.
 * @returns {Array} Returns `array`.
 */
function arrayPush(array, values) {
  var index = -1,
      length = values.length,
      offset = array.length;

  while (++index < length) {
    array[offset + index] = values[index];
  }
  return array;
}

/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (arrayPush);


/***/ }),

/***/ 33909:
/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {

"use strict";
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "Z": () => (__WEBPACK_DEFAULT_EXPORT__)
/* harmony export */ });
/**
 * A specialized version of `_.some` for arrays without support for iteratee
 * shorthands.
 *
 * @private
 * @param {Array} [array] The array to iterate over.
 * @param {Function} predicate The function invoked per iteration.
 * @returns {boolean} Returns `true` if any element passes the predicate check,
 *  else `false`.
 */
function arraySome(array, predicate) {
  var index = -1,
      length = array == null ? 0 : array.length;

  while (++index < length) {
    if (predicate(array[index], index, array)) {
      return true;
    }
  }
  return false;
}

/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (arraySome);


/***/ }),

/***/ 54171:
/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {

"use strict";
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "Z": () => (__WEBPACK_DEFAULT_EXPORT__)
/* harmony export */ });
/* harmony import */ var _eq_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(99581);


/**
 * Gets the index at which the `key` is found in `array` of key-value pairs.
 *
 * @private
 * @param {Array} array The array to inspect.
 * @param {*} key The key to search for.
 * @returns {number} Returns the index of the matched value, else `-1`.
 */
function assocIndexOf(array, key) {
  var length = array.length;
  while (length--) {
    if ((0,_eq_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"] */ .Z)(array[length][0], key)) {
      return length;
    }
  }
  return -1;
}

/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (assocIndexOf);


/***/ }),

/***/ 65758:
/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {

"use strict";

// EXPORTS
__webpack_require__.d(__webpack_exports__, {
  "Z": () => (/* binding */ _baseEach)
});

// EXTERNAL MODULE: ./node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/_baseFor.js + 1 modules
var _baseFor = __webpack_require__(92822);
// EXTERNAL MODULE: ./node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/keys.js + 2 modules
var keys = __webpack_require__(12395);
;// CONCATENATED MODULE: ./node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/_baseForOwn.js



/**
 * The base implementation of `_.forOwn` without support for iteratee shorthands.
 *
 * @private
 * @param {Object} object The object to iterate over.
 * @param {Function} iteratee The function invoked per iteration.
 * @returns {Object} Returns `object`.
 */
function baseForOwn(object, iteratee) {
  return object && (0,_baseFor/* default */.Z)(object, iteratee, keys/* default */.Z);
}

/* harmony default export */ const _baseForOwn = (baseForOwn);

// EXTERNAL MODULE: ./node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/isArrayLike.js
var isArrayLike = __webpack_require__(2762);
;// CONCATENATED MODULE: ./node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/_createBaseEach.js


/**
 * Creates a `baseEach` or `baseEachRight` function.
 *
 * @private
 * @param {Function} eachFunc The function to iterate over a collection.
 * @param {boolean} [fromRight] Specify iterating from right to left.
 * @returns {Function} Returns the new base function.
 */
function createBaseEach(eachFunc, fromRight) {
  return function(collection, iteratee) {
    if (collection == null) {
      return collection;
    }
    if (!(0,isArrayLike/* default */.Z)(collection)) {
      return eachFunc(collection, iteratee);
    }
    var length = collection.length,
        index = fromRight ? length : -1,
        iterable = Object(collection);

    while ((fromRight ? index-- : ++index < length)) {
      if (iteratee(iterable[index], index, iterable) === false) {
        break;
      }
    }
    return collection;
  };
}

/* harmony default export */ const _createBaseEach = (createBaseEach);

;// CONCATENATED MODULE: ./node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/_baseEach.js



/**
 * The base implementation of `_.forEach` without support for iteratee shorthands.
 *
 * @private
 * @param {Array|Object} collection The collection to iterate over.
 * @param {Function} iteratee The function invoked per iteration.
 * @returns {Array|Object} Returns `collection`.
 */
var baseEach = _createBaseEach(_baseForOwn);

/* harmony default export */ const _baseEach = (baseEach);


/***/ }),

/***/ 90094:
/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {

"use strict";

// EXPORTS
__webpack_require__.d(__webpack_exports__, {
  "Z": () => (/* binding */ _baseFlatten)
});

// EXTERNAL MODULE: ./node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/_arrayPush.js
var _arrayPush = __webpack_require__(48176);
// EXTERNAL MODULE: ./node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/_Symbol.js
var _Symbol = __webpack_require__(19474);
// EXTERNAL MODULE: ./node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/isArguments.js
var isArguments = __webpack_require__(66161);
// EXTERNAL MODULE: ./node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/isArray.js
var isArray = __webpack_require__(24254);
;// CONCATENATED MODULE: ./node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/_isFlattenable.js




/** Built-in value references. */
var spreadableSymbol = _Symbol/* default */.Z ? _Symbol/* default.isConcatSpreadable */.Z.isConcatSpreadable : undefined;

/**
 * Checks if `value` is a flattenable `arguments` object or array.
 *
 * @private
 * @param {*} value The value to check.
 * @returns {boolean} Returns `true` if `value` is flattenable, else `false`.
 */
function isFlattenable(value) {
  return (0,isArray/* default */.Z)(value) || (0,isArguments/* default */.Z)(value) ||
    !!(spreadableSymbol && value && value[spreadableSymbol]);
}

/* harmony default export */ const _isFlattenable = (isFlattenable);

;// CONCATENATED MODULE: ./node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/_baseFlatten.js



/**
 * The base implementation of `_.flatten` with support for restricting flattening.
 *
 * @private
 * @param {Array} array The array to flatten.
 * @param {number} depth The maximum recursion depth.
 * @param {boolean} [predicate=isFlattenable] The function invoked per iteration.
 * @param {boolean} [isStrict] Restrict to values that pass `predicate` checks.
 * @param {Array} [result=[]] The initial result value.
 * @returns {Array} Returns the new flattened array.
 */
function baseFlatten(array, depth, predicate, isStrict, result) {
  var index = -1,
      length = array.length;

  predicate || (predicate = _isFlattenable);
  result || (result = []);

  while (++index < length) {
    var value = array[index];
    if (depth > 0 && predicate(value)) {
      if (depth > 1) {
        // Recursively flatten arrays (susceptible to call stack limits).
        baseFlatten(value, depth - 1, predicate, isStrict, result);
      } else {
        (0,_arrayPush/* default */.Z)(result, value);
      }
    } else if (!isStrict) {
      result[result.length] = value;
    }
  }
  return result;
}

/* harmony default export */ const _baseFlatten = (baseFlatten);


/***/ }),

/***/ 92822:
/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {

"use strict";

// EXPORTS
__webpack_require__.d(__webpack_exports__, {
  "Z": () => (/* binding */ _baseFor)
});

;// CONCATENATED MODULE: ./node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/_createBaseFor.js
/**
 * Creates a base function for methods like `_.forIn` and `_.forOwn`.
 *
 * @private
 * @param {boolean} [fromRight] Specify iterating from right to left.
 * @returns {Function} Returns the new base function.
 */
function createBaseFor(fromRight) {
  return function(object, iteratee, keysFunc) {
    var index = -1,
        iterable = Object(object),
        props = keysFunc(object),
        length = props.length;

    while (length--) {
      var key = props[fromRight ? length : ++index];
      if (iteratee(iterable[key], key, iterable) === false) {
        break;
      }
    }
    return object;
  };
}

/* harmony default export */ const _createBaseFor = (createBaseFor);

;// CONCATENATED MODULE: ./node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/_baseFor.js


/**
 * The base implementation of `baseForOwn` which iterates over `object`
 * properties returned by `keysFunc` and invokes `iteratee` for each property.
 * Iteratee functions may exit iteration early by explicitly returning `false`.
 *
 * @private
 * @param {Object} object The object to iterate over.
 * @param {Function} iteratee The function invoked per iteration.
 * @param {Function} keysFunc The function to get the keys of `object`.
 * @returns {Object} Returns `object`.
 */
var baseFor = _createBaseFor();

/* harmony default export */ const _baseFor = (baseFor);


/***/ }),

/***/ 42043:
/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {

"use strict";
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "Z": () => (__WEBPACK_DEFAULT_EXPORT__)
/* harmony export */ });
/* harmony import */ var _castPath_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(70093);
/* harmony import */ var _toKey_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(53069);



/**
 * The base implementation of `_.get` without support for default values.
 *
 * @private
 * @param {Object} object The object to query.
 * @param {Array|string} path The path of the property to get.
 * @returns {*} Returns the resolved value.
 */
function baseGet(object, path) {
  path = (0,_castPath_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"] */ .Z)(path, object);

  var index = 0,
      length = path.length;

  while (object != null && index < length) {
    object = object[(0,_toKey_js__WEBPACK_IMPORTED_MODULE_1__/* ["default"] */ .Z)(path[index++])];
  }
  return (index && index == length) ? object : undefined;
}

/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (baseGet);


/***/ }),

/***/ 85086:
/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {

"use strict";
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "Z": () => (__WEBPACK_DEFAULT_EXPORT__)
/* harmony export */ });
/* harmony import */ var _Symbol_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(19474);
/* harmony import */ var _getRawTag_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(1866);
/* harmony import */ var _objectToString_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(31710);




/** `Object#toString` result references. */
var nullTag = '[object Null]',
    undefinedTag = '[object Undefined]';

/** Built-in value references. */
var symToStringTag = _Symbol_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"] */ .Z ? _Symbol_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"].toStringTag */ .Z.toStringTag : undefined;

/**
 * The base implementation of `getTag` without fallbacks for buggy environments.
 *
 * @private
 * @param {*} value The value to query.
 * @returns {string} Returns the `toStringTag`.
 */
function baseGetTag(value) {
  if (value == null) {
    return value === undefined ? undefinedTag : nullTag;
  }
  return (symToStringTag && symToStringTag in Object(value))
    ? (0,_getRawTag_js__WEBPACK_IMPORTED_MODULE_1__/* ["default"] */ .Z)(value)
    : (0,_objectToString_js__WEBPACK_IMPORTED_MODULE_2__/* ["default"] */ .Z)(value);
}

/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (baseGetTag);


/***/ }),

/***/ 27166:
/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {

"use strict";
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "Z": () => (__WEBPACK_DEFAULT_EXPORT__)
/* harmony export */ });
/* harmony import */ var _baseGetTag_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(85086);
/* harmony import */ var _isObjectLike_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(95690);



/** `Object#toString` result references. */
var argsTag = '[object Arguments]';

/**
 * The base implementation of `_.isArguments`.
 *
 * @private
 * @param {*} value The value to check.
 * @returns {boolean} Returns `true` if `value` is an `arguments` object,
 */
function baseIsArguments(value) {
  return (0,_isObjectLike_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"] */ .Z)(value) && (0,_baseGetTag_js__WEBPACK_IMPORTED_MODULE_1__/* ["default"] */ .Z)(value) == argsTag;
}

/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (baseIsArguments);


/***/ }),

/***/ 34558:
/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {

"use strict";
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "Z": () => (__WEBPACK_DEFAULT_EXPORT__)
/* harmony export */ });
/* harmony import */ var _isFunction_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(25827);
/* harmony import */ var _isMasked_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(66836);
/* harmony import */ var _isObject_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(62893);
/* harmony import */ var _toSource_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(55736);





/**
 * Used to match `RegExp`
 * [syntax characters](http://ecma-international.org/ecma-262/7.0/#sec-patterns).
 */
var reRegExpChar = /[\\^$.*+?()[\]{}|]/g;

/** Used to detect host constructors (Safari). */
var reIsHostCtor = /^\[object .+?Constructor\]$/;

/** Used for built-in method references. */
var funcProto = Function.prototype,
    objectProto = Object.prototype;

/** Used to resolve the decompiled source of functions. */
var funcToString = funcProto.toString;

/** Used to check objects for own properties. */
var hasOwnProperty = objectProto.hasOwnProperty;

/** Used to detect if a method is native. */
var reIsNative = RegExp('^' +
  funcToString.call(hasOwnProperty).replace(reRegExpChar, '\\$&')
  .replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g, '$1.*?') + '$'
);

/**
 * The base implementation of `_.isNative` without bad shim checks.
 *
 * @private
 * @param {*} value The value to check.
 * @returns {boolean} Returns `true` if `value` is a native function,
 *  else `false`.
 */
function baseIsNative(value) {
  if (!(0,_isObject_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"] */ .Z)(value) || (0,_isMasked_js__WEBPACK_IMPORTED_MODULE_1__/* ["default"] */ .Z)(value)) {
    return false;
  }
  var pattern = (0,_isFunction_js__WEBPACK_IMPORTED_MODULE_2__/* ["default"] */ .Z)(value) ? reIsNative : reIsHostCtor;
  return pattern.test((0,_toSource_js__WEBPACK_IMPORTED_MODULE_3__/* ["default"] */ .Z)(value));
}

/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (baseIsNative);


/***/ }),

/***/ 56896:
/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {

"use strict";
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "Z": () => (__WEBPACK_DEFAULT_EXPORT__)
/* harmony export */ });
/* harmony import */ var _baseGetTag_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(85086);
/* harmony import */ var _isLength_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(55477);
/* harmony import */ var _isObjectLike_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(95690);




/** `Object#toString` result references. */
var argsTag = '[object Arguments]',
    arrayTag = '[object Array]',
    boolTag = '[object Boolean]',
    dateTag = '[object Date]',
    errorTag = '[object Error]',
    funcTag = '[object Function]',
    mapTag = '[object Map]',
    numberTag = '[object Number]',
    objectTag = '[object Object]',
    regexpTag = '[object RegExp]',
    setTag = '[object Set]',
    stringTag = '[object String]',
    weakMapTag = '[object WeakMap]';

var arrayBufferTag = '[object ArrayBuffer]',
    dataViewTag = '[object DataView]',
    float32Tag = '[object Float32Array]',
    float64Tag = '[object Float64Array]',
    int8Tag = '[object Int8Array]',
    int16Tag = '[object Int16Array]',
    int32Tag = '[object Int32Array]',
    uint8Tag = '[object Uint8Array]',
    uint8ClampedTag = '[object Uint8ClampedArray]',
    uint16Tag = '[object Uint16Array]',
    uint32Tag = '[object Uint32Array]';

/** Used to identify `toStringTag` values of typed arrays. */
var typedArrayTags = {};
typedArrayTags[float32Tag] = typedArrayTags[float64Tag] =
typedArrayTags[int8Tag] = typedArrayTags[int16Tag] =
typedArrayTags[int32Tag] = typedArrayTags[uint8Tag] =
typedArrayTags[uint8ClampedTag] = typedArrayTags[uint16Tag] =
typedArrayTags[uint32Tag] = true;
typedArrayTags[argsTag] = typedArrayTags[arrayTag] =
typedArrayTags[arrayBufferTag] = typedArrayTags[boolTag] =
typedArrayTags[dataViewTag] = typedArrayTags[dateTag] =
typedArrayTags[errorTag] = typedArrayTags[funcTag] =
typedArrayTags[mapTag] = typedArrayTags[numberTag] =
typedArrayTags[objectTag] = typedArrayTags[regexpTag] =
typedArrayTags[setTag] = typedArrayTags[stringTag] =
typedArrayTags[weakMapTag] = false;

/**
 * The base implementation of `_.isTypedArray` without Node.js optimizations.
 *
 * @private
 * @param {*} value The value to check.
 * @returns {boolean} Returns `true` if `value` is a typed array, else `false`.
 */
function baseIsTypedArray(value) {
  return (0,_isObjectLike_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"] */ .Z)(value) &&
    (0,_isLength_js__WEBPACK_IMPORTED_MODULE_1__/* ["default"] */ .Z)(value.length) && !!typedArrayTags[(0,_baseGetTag_js__WEBPACK_IMPORTED_MODULE_2__/* ["default"] */ .Z)(value)];
}

/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (baseIsTypedArray);


/***/ }),

/***/ 45981:
/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {

"use strict";

// EXPORTS
__webpack_require__.d(__webpack_exports__, {
  "Z": () => (/* binding */ _baseIteratee)
});

// EXTERNAL MODULE: ./node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/_Stack.js + 5 modules
var _Stack = __webpack_require__(74225);
// EXTERNAL MODULE: ./node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/_MapCache.js
var _MapCache = __webpack_require__(14356);
;// CONCATENATED MODULE: ./node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/_setCacheAdd.js
/** Used to stand-in for `undefined` hash values. */
var HASH_UNDEFINED = '__lodash_hash_undefined__';

/**
 * Adds `value` to the array cache.
 *
 * @private
 * @name add
 * @memberOf SetCache
 * @alias push
 * @param {*} value The value to cache.
 * @returns {Object} Returns the cache instance.
 */
function setCacheAdd(value) {
  this.__data__.set(value, HASH_UNDEFINED);
  return this;
}

/* harmony default export */ const _setCacheAdd = (setCacheAdd);

;// CONCATENATED MODULE: ./node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/_setCacheHas.js
/**
 * Checks if `value` is in the array cache.
 *
 * @private
 * @name has
 * @memberOf SetCache
 * @param {*} value The value to search for.
 * @returns {number} Returns `true` if `value` is found, else `false`.
 */
function setCacheHas(value) {
  return this.__data__.has(value);
}

/* harmony default export */ const _setCacheHas = (setCacheHas);

;// CONCATENATED MODULE: ./node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/_SetCache.js




/**
 *
 * Creates an array cache object to store unique values.
 *
 * @private
 * @constructor
 * @param {Array} [values] The values to cache.
 */
function SetCache(values) {
  var index = -1,
      length = values == null ? 0 : values.length;

  this.__data__ = new _MapCache/* default */.Z;
  while (++index < length) {
    this.add(values[index]);
  }
}

// Add methods to `SetCache`.
SetCache.prototype.add = SetCache.prototype.push = _setCacheAdd;
SetCache.prototype.has = _setCacheHas;

/* harmony default export */ const _SetCache = (SetCache);

// EXTERNAL MODULE: ./node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/_arraySome.js
var _arraySome = __webpack_require__(33909);
;// CONCATENATED MODULE: ./node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/_cacheHas.js
/**
 * Checks if a `cache` value for `key` exists.
 *
 * @private
 * @param {Object} cache The cache to query.
 * @param {string} key The key of the entry to check.
 * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.
 */
function cacheHas(cache, key) {
  return cache.has(key);
}

/* harmony default export */ const _cacheHas = (cacheHas);

;// CONCATENATED MODULE: ./node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/_equalArrays.js




/** Used to compose bitmasks for value comparisons. */
var COMPARE_PARTIAL_FLAG = 1,
    COMPARE_UNORDERED_FLAG = 2;

/**
 * A specialized version of `baseIsEqualDeep` for arrays with support for
 * partial deep comparisons.
 *
 * @private
 * @param {Array} array The array to compare.
 * @param {Array} other The other array to compare.
 * @param {number} bitmask The bitmask flags. See `baseIsEqual` for more details.
 * @param {Function} customizer The function to customize comparisons.
 * @param {Function} equalFunc The function to determine equivalents of values.
 * @param {Object} stack Tracks traversed `array` and `other` objects.
 * @returns {boolean} Returns `true` if the arrays are equivalent, else `false`.
 */
function equalArrays(array, other, bitmask, customizer, equalFunc, stack) {
  var isPartial = bitmask & COMPARE_PARTIAL_FLAG,
      arrLength = array.length,
      othLength = other.length;

  if (arrLength != othLength && !(isPartial && othLength > arrLength)) {
    return false;
  }
  // Check that cyclic values are equal.
  var arrStacked = stack.get(array);
  var othStacked = stack.get(other);
  if (arrStacked && othStacked) {
    return arrStacked == other && othStacked == array;
  }
  var index = -1,
      result = true,
      seen = (bitmask & COMPARE_UNORDERED_FLAG) ? new _SetCache : undefined;

  stack.set(array, other);
  stack.set(other, array);

  // Ignore non-index properties.
  while (++index < arrLength) {
    var arrValue = array[index],
        othValue = other[index];

    if (customizer) {
      var compared = isPartial
        ? customizer(othValue, arrValue, index, other, array, stack)
        : customizer(arrValue, othValue, index, array, other, stack);
    }
    if (compared !== undefined) {
      if (compared) {
        continue;
      }
      result = false;
      break;
    }
    // Recursively compare arrays (susceptible to call stack limits).
    if (seen) {
      if (!(0,_arraySome/* default */.Z)(other, function(othValue, othIndex) {
            if (!_cacheHas(seen, othIndex) &&
                (arrValue === othValue || equalFunc(arrValue, othValue, bitmask, customizer, stack))) {
              return seen.push(othIndex);
            }
          })) {
        result = false;
        break;
      }
    } else if (!(
          arrValue === othValue ||
            equalFunc(arrValue, othValue, bitmask, customizer, stack)
        )) {
      result = false;
      break;
    }
  }
  stack['delete'](array);
  stack['delete'](other);
  return result;
}

/* harmony default export */ const _equalArrays = (equalArrays);

// EXTERNAL MODULE: ./node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/_Symbol.js
var _Symbol = __webpack_require__(19474);
// EXTERNAL MODULE: ./node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/_Uint8Array.js
var _Uint8Array = __webpack_require__(9128);
// EXTERNAL MODULE: ./node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/eq.js
var eq = __webpack_require__(99581);
;// CONCATENATED MODULE: ./node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/_mapToArray.js
/**
 * Converts `map` to its key-value pairs.
 *
 * @private
 * @param {Object} map The map to convert.
 * @returns {Array} Returns the key-value pairs.
 */
function mapToArray(map) {
  var index = -1,
      result = Array(map.size);

  map.forEach(function(value, key) {
    result[++index] = [key, value];
  });
  return result;
}

/* harmony default export */ const _mapToArray = (mapToArray);

;// CONCATENATED MODULE: ./node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/_setToArray.js
/**
 * Converts `set` to an array of its values.
 *
 * @private
 * @param {Object} set The set to convert.
 * @returns {Array} Returns the values.
 */
function setToArray(set) {
  var index = -1,
      result = Array(set.size);

  set.forEach(function(value) {
    result[++index] = value;
  });
  return result;
}

/* harmony default export */ const _setToArray = (setToArray);

;// CONCATENATED MODULE: ./node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/_equalByTag.js







/** Used to compose bitmasks for value comparisons. */
var _equalByTag_COMPARE_PARTIAL_FLAG = 1,
    _equalByTag_COMPARE_UNORDERED_FLAG = 2;

/** `Object#toString` result references. */
var boolTag = '[object Boolean]',
    dateTag = '[object Date]',
    errorTag = '[object Error]',
    mapTag = '[object Map]',
    numberTag = '[object Number]',
    regexpTag = '[object RegExp]',
    setTag = '[object Set]',
    stringTag = '[object String]',
    symbolTag = '[object Symbol]';

var arrayBufferTag = '[object ArrayBuffer]',
    dataViewTag = '[object DataView]';

/** Used to convert symbols to primitives and strings. */
var symbolProto = _Symbol/* default */.Z ? _Symbol/* default.prototype */.Z.prototype : undefined,
    symbolValueOf = symbolProto ? symbolProto.valueOf : undefined;

/**
 * A specialized version of `baseIsEqualDeep` for comparing objects of
 * the same `toStringTag`.
 *
 * **Note:** This function only supports comparing values with tags of
 * `Boolean`, `Date`, `Error`, `Number`, `RegExp`, or `String`.
 *
 * @private
 * @param {Object} object The object to compare.
 * @param {Object} other The other object to compare.
 * @param {string} tag The `toStringTag` of the objects to compare.
 * @param {number} bitmask The bitmask flags. See `baseIsEqual` for more details.
 * @param {Function} customizer The function to customize comparisons.
 * @param {Function} equalFunc The function to determine equivalents of values.
 * @param {Object} stack Tracks traversed `object` and `other` objects.
 * @returns {boolean} Returns `true` if the objects are equivalent, else `false`.
 */
function equalByTag(object, other, tag, bitmask, customizer, equalFunc, stack) {
  switch (tag) {
    case dataViewTag:
      if ((object.byteLength != other.byteLength) ||
          (object.byteOffset != other.byteOffset)) {
        return false;
      }
      object = object.buffer;
      other = other.buffer;

    case arrayBufferTag:
      if ((object.byteLength != other.byteLength) ||
          !equalFunc(new _Uint8Array/* default */.Z(object), new _Uint8Array/* default */.Z(other))) {
        return false;
      }
      return true;

    case boolTag:
    case dateTag:
    case numberTag:
      // Coerce booleans to `1` or `0` and dates to milliseconds.
      // Invalid dates are coerced to `NaN`.
      return (0,eq/* default */.Z)(+object, +other);

    case errorTag:
      return object.name == other.name && object.message == other.message;

    case regexpTag:
    case stringTag:
      // Coerce regexes to strings and treat strings, primitives and objects,
      // as equal. See http://www.ecma-international.org/ecma-262/7.0/#sec-regexp.prototype.tostring
      // for more details.
      return object == (other + '');

    case mapTag:
      var convert = _mapToArray;

    case setTag:
      var isPartial = bitmask & _equalByTag_COMPARE_PARTIAL_FLAG;
      convert || (convert = _setToArray);

      if (object.size != other.size && !isPartial) {
        return false;
      }
      // Assume cyclic values are equal.
      var stacked = stack.get(object);
      if (stacked) {
        return stacked == other;
      }
      bitmask |= _equalByTag_COMPARE_UNORDERED_FLAG;

      // Recursively compare objects (susceptible to call stack limits).
      stack.set(object, other);
      var result = _equalArrays(convert(object), convert(other), bitmask, customizer, equalFunc, stack);
      stack['delete'](object);
      return result;

    case symbolTag:
      if (symbolValueOf) {
        return symbolValueOf.call(object) == symbolValueOf.call(other);
      }
  }
  return false;
}

/* harmony default export */ const _equalByTag = (equalByTag);

// EXTERNAL MODULE: ./node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/_arrayPush.js
var _arrayPush = __webpack_require__(48176);
// EXTERNAL MODULE: ./node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/isArray.js
var isArray = __webpack_require__(24254);
;// CONCATENATED MODULE: ./node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/_baseGetAllKeys.js



/**
 * The base implementation of `getAllKeys` and `getAllKeysIn` which uses
 * `keysFunc` and `symbolsFunc` to get the enumerable property names and
 * symbols of `object`.
 *
 * @private
 * @param {Object} object The object to query.
 * @param {Function} keysFunc The function to get the keys of `object`.
 * @param {Function} symbolsFunc The function to get the symbols of `object`.
 * @returns {Array} Returns the array of property names and symbols.
 */
function baseGetAllKeys(object, keysFunc, symbolsFunc) {
  var result = keysFunc(object);
  return (0,isArray/* default */.Z)(object) ? result : (0,_arrayPush/* default */.Z)(result, symbolsFunc(object));
}

/* harmony default export */ const _baseGetAllKeys = (baseGetAllKeys);

;// CONCATENATED MODULE: ./node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/_arrayFilter.js
/**
 * A specialized version of `_.filter` for arrays without support for
 * iteratee shorthands.
 *
 * @private
 * @param {Array} [array] The array to iterate over.
 * @param {Function} predicate The function invoked per iteration.
 * @returns {Array} Returns the new filtered array.
 */
function arrayFilter(array, predicate) {
  var index = -1,
      length = array == null ? 0 : array.length,
      resIndex = 0,
      result = [];

  while (++index < length) {
    var value = array[index];
    if (predicate(value, index, array)) {
      result[resIndex++] = value;
    }
  }
  return result;
}

/* harmony default export */ const _arrayFilter = (arrayFilter);

;// CONCATENATED MODULE: ./node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/stubArray.js
/**
 * This method returns a new empty array.
 *
 * @static
 * @memberOf _
 * @since 4.13.0
 * @category Util
 * @returns {Array} Returns the new empty array.
 * @example
 *
 * var arrays = _.times(2, _.stubArray);
 *
 * console.log(arrays);
 * // => [[], []]
 *
 * console.log(arrays[0] === arrays[1]);
 * // => false
 */
function stubArray() {
  return [];
}

/* harmony default export */ const lodash_es_stubArray = (stubArray);

;// CONCATENATED MODULE: ./node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/_getSymbols.js



/** Used for built-in method references. */
var objectProto = Object.prototype;

/** Built-in value references. */
var propertyIsEnumerable = objectProto.propertyIsEnumerable;

/* Built-in method references for those with the same name as other `lodash` methods. */
var nativeGetSymbols = Object.getOwnPropertySymbols;

/**
 * Creates an array of the own enumerable symbols of `object`.
 *
 * @private
 * @param {Object} object The object to query.
 * @returns {Array} Returns the array of symbols.
 */
var getSymbols = !nativeGetSymbols ? lodash_es_stubArray : function(object) {
  if (object == null) {
    return [];
  }
  object = Object(object);
  return _arrayFilter(nativeGetSymbols(object), function(symbol) {
    return propertyIsEnumerable.call(object, symbol);
  });
};

/* harmony default export */ const _getSymbols = (getSymbols);

// EXTERNAL MODULE: ./node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/keys.js + 2 modules
var keys = __webpack_require__(12395);
;// CONCATENATED MODULE: ./node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/_getAllKeys.js




/**
 * Creates an array of own enumerable property names and symbols of `object`.
 *
 * @private
 * @param {Object} object The object to query.
 * @returns {Array} Returns the array of property names and symbols.
 */
function getAllKeys(object) {
  return _baseGetAllKeys(object, keys/* default */.Z, _getSymbols);
}

/* harmony default export */ const _getAllKeys = (getAllKeys);

;// CONCATENATED MODULE: ./node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/_equalObjects.js


/** Used to compose bitmasks for value comparisons. */
var _equalObjects_COMPARE_PARTIAL_FLAG = 1;

/** Used for built-in method references. */
var _equalObjects_objectProto = Object.prototype;

/** Used to check objects for own properties. */
var _equalObjects_hasOwnProperty = _equalObjects_objectProto.hasOwnProperty;

/**
 * A specialized version of `baseIsEqualDeep` for objects with support for
 * partial deep comparisons.
 *
 * @private
 * @param {Object} object The object to compare.
 * @param {Object} other The other object to compare.
 * @param {number} bitmask The bitmask flags. See `baseIsEqual` for more details.
 * @param {Function} customizer The function to customize comparisons.
 * @param {Function} equalFunc The function to determine equivalents of values.
 * @param {Object} stack Tracks traversed `object` and `other` objects.
 * @returns {boolean} Returns `true` if the objects are equivalent, else `false`.
 */
function equalObjects(object, other, bitmask, customizer, equalFunc, stack) {
  var isPartial = bitmask & _equalObjects_COMPARE_PARTIAL_FLAG,
      objProps = _getAllKeys(object),
      objLength = objProps.length,
      othProps = _getAllKeys(other),
      othLength = othProps.length;

  if (objLength != othLength && !isPartial) {
    return false;
  }
  var index = objLength;
  while (index--) {
    var key = objProps[index];
    if (!(isPartial ? key in other : _equalObjects_hasOwnProperty.call(other, key))) {
      return false;
    }
  }
  // Check that cyclic values are equal.
  var objStacked = stack.get(object);
  var othStacked = stack.get(other);
  if (objStacked && othStacked) {
    return objStacked == other && othStacked == object;
  }
  var result = true;
  stack.set(object, other);
  stack.set(other, object);

  var skipCtor = isPartial;
  while (++index < objLength) {
    key = objProps[index];
    var objValue = object[key],
        othValue = other[key];

    if (customizer) {
      var compared = isPartial
        ? customizer(othValue, objValue, key, other, object, stack)
        : customizer(objValue, othValue, key, object, other, stack);
    }
    // Recursively compare objects (susceptible to call stack limits).
    if (!(compared === undefined
          ? (objValue === othValue || equalFunc(objValue, othValue, bitmask, customizer, stack))
          : compared
        )) {
      result = false;
      break;
    }
    skipCtor || (skipCtor = key == 'constructor');
  }
  if (result && !skipCtor) {
    var objCtor = object.constructor,
        othCtor = other.constructor;

    // Non `Object` object instances with different constructors are not equal.
    if (objCtor != othCtor &&
        ('constructor' in object && 'constructor' in other) &&
        !(typeof objCtor == 'function' && objCtor instanceof objCtor &&
          typeof othCtor == 'function' && othCtor instanceof othCtor)) {
      result = false;
    }
  }
  stack['delete'](object);
  stack['delete'](other);
  return result;
}

/* harmony default export */ const _equalObjects = (equalObjects);

// EXTERNAL MODULE: ./node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/_getNative.js
var _getNative = __webpack_require__(80156);
// EXTERNAL MODULE: ./node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/_root.js
var _root = __webpack_require__(5665);
;// CONCATENATED MODULE: ./node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/_DataView.js



/* Built-in method references that are verified to be native. */
var DataView = (0,_getNative/* default */.Z)(_root/* default */.Z, 'DataView');

/* harmony default export */ const _DataView = (DataView);

// EXTERNAL MODULE: ./node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/_Map.js
var _Map = __webpack_require__(3806);
;// CONCATENATED MODULE: ./node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/_Promise.js



/* Built-in method references that are verified to be native. */
var Promise = (0,_getNative/* default */.Z)(_root/* default */.Z, 'Promise');

/* harmony default export */ const _Promise = (Promise);

;// CONCATENATED MODULE: ./node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/_Set.js



/* Built-in method references that are verified to be native. */
var Set = (0,_getNative/* default */.Z)(_root/* default */.Z, 'Set');

/* harmony default export */ const _Set = (Set);

;// CONCATENATED MODULE: ./node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/_WeakMap.js



/* Built-in method references that are verified to be native. */
var WeakMap = (0,_getNative/* default */.Z)(_root/* default */.Z, 'WeakMap');

/* harmony default export */ const _WeakMap = (WeakMap);

// EXTERNAL MODULE: ./node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/_baseGetTag.js
var _baseGetTag = __webpack_require__(85086);
// EXTERNAL MODULE: ./node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/_toSource.js
var _toSource = __webpack_require__(55736);
;// CONCATENATED MODULE: ./node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/_getTag.js








/** `Object#toString` result references. */
var _getTag_mapTag = '[object Map]',
    objectTag = '[object Object]',
    promiseTag = '[object Promise]',
    _getTag_setTag = '[object Set]',
    weakMapTag = '[object WeakMap]';

var _getTag_dataViewTag = '[object DataView]';

/** Used to detect maps, sets, and weakmaps. */
var dataViewCtorString = (0,_toSource/* default */.Z)(_DataView),
    mapCtorString = (0,_toSource/* default */.Z)(_Map/* default */.Z),
    promiseCtorString = (0,_toSource/* default */.Z)(_Promise),
    setCtorString = (0,_toSource/* default */.Z)(_Set),
    weakMapCtorString = (0,_toSource/* default */.Z)(_WeakMap);

/**
 * Gets the `toStringTag` of `value`.
 *
 * @private
 * @param {*} value The value to query.
 * @returns {string} Returns the `toStringTag`.
 */
var getTag = _baseGetTag/* default */.Z;

// Fallback for data views, maps, sets, and weak maps in IE 11 and promises in Node.js < 6.
if ((_DataView && getTag(new _DataView(new ArrayBuffer(1))) != _getTag_dataViewTag) ||
    (_Map/* default */.Z && getTag(new _Map/* default */.Z) != _getTag_mapTag) ||
    (_Promise && getTag(_Promise.resolve()) != promiseTag) ||
    (_Set && getTag(new _Set) != _getTag_setTag) ||
    (_WeakMap && getTag(new _WeakMap) != weakMapTag)) {
  getTag = function(value) {
    var result = (0,_baseGetTag/* default */.Z)(value),
        Ctor = result == objectTag ? value.constructor : undefined,
        ctorString = Ctor ? (0,_toSource/* default */.Z)(Ctor) : '';

    if (ctorString) {
      switch (ctorString) {
        case dataViewCtorString: return _getTag_dataViewTag;
        case mapCtorString: return _getTag_mapTag;
        case promiseCtorString: return promiseTag;
        case setCtorString: return _getTag_setTag;
        case weakMapCtorString: return weakMapTag;
      }
    }
    return result;
  };
}

/* harmony default export */ const _getTag = (getTag);

// EXTERNAL MODULE: ./node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/isBuffer.js
var isBuffer = __webpack_require__(5950);
// EXTERNAL MODULE: ./node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/isTypedArray.js
var isTypedArray = __webpack_require__(90284);
;// CONCATENATED MODULE: ./node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/_baseIsEqualDeep.js









/** Used to compose bitmasks for value comparisons. */
var _baseIsEqualDeep_COMPARE_PARTIAL_FLAG = 1;

/** `Object#toString` result references. */
var argsTag = '[object Arguments]',
    arrayTag = '[object Array]',
    _baseIsEqualDeep_objectTag = '[object Object]';

/** Used for built-in method references. */
var _baseIsEqualDeep_objectProto = Object.prototype;

/** Used to check objects for own properties. */
var _baseIsEqualDeep_hasOwnProperty = _baseIsEqualDeep_objectProto.hasOwnProperty;

/**
 * A specialized version of `baseIsEqual` for arrays and objects which performs
 * deep comparisons and tracks traversed objects enabling objects with circular
 * references to be compared.
 *
 * @private
 * @param {Object} object The object to compare.
 * @param {Object} other The other object to compare.
 * @param {number} bitmask The bitmask flags. See `baseIsEqual` for more details.
 * @param {Function} customizer The function to customize comparisons.
 * @param {Function} equalFunc The function to determine equivalents of values.
 * @param {Object} [stack] Tracks traversed `object` and `other` objects.
 * @returns {boolean} Returns `true` if the objects are equivalent, else `false`.
 */
function baseIsEqualDeep(object, other, bitmask, customizer, equalFunc, stack) {
  var objIsArr = (0,isArray/* default */.Z)(object),
      othIsArr = (0,isArray/* default */.Z)(other),
      objTag = objIsArr ? arrayTag : _getTag(object),
      othTag = othIsArr ? arrayTag : _getTag(other);

  objTag = objTag == argsTag ? _baseIsEqualDeep_objectTag : objTag;
  othTag = othTag == argsTag ? _baseIsEqualDeep_objectTag : othTag;

  var objIsObj = objTag == _baseIsEqualDeep_objectTag,
      othIsObj = othTag == _baseIsEqualDeep_objectTag,
      isSameTag = objTag == othTag;

  if (isSameTag && (0,isBuffer/* default */.Z)(object)) {
    if (!(0,isBuffer/* default */.Z)(other)) {
      return false;
    }
    objIsArr = true;
    objIsObj = false;
  }
  if (isSameTag && !objIsObj) {
    stack || (stack = new _Stack/* default */.Z);
    return (objIsArr || (0,isTypedArray/* default */.Z)(object))
      ? _equalArrays(object, other, bitmask, customizer, equalFunc, stack)
      : _equalByTag(object, other, objTag, bitmask, customizer, equalFunc, stack);
  }
  if (!(bitmask & _baseIsEqualDeep_COMPARE_PARTIAL_FLAG)) {
    var objIsWrapped = objIsObj && _baseIsEqualDeep_hasOwnProperty.call(object, '__wrapped__'),
        othIsWrapped = othIsObj && _baseIsEqualDeep_hasOwnProperty.call(other, '__wrapped__');

    if (objIsWrapped || othIsWrapped) {
      var objUnwrapped = objIsWrapped ? object.value() : object,
          othUnwrapped = othIsWrapped ? other.value() : other;

      stack || (stack = new _Stack/* default */.Z);
      return equalFunc(objUnwrapped, othUnwrapped, bitmask, customizer, stack);
    }
  }
  if (!isSameTag) {
    return false;
  }
  stack || (stack = new _Stack/* default */.Z);
  return _equalObjects(object, other, bitmask, customizer, equalFunc, stack);
}

/* harmony default export */ const _baseIsEqualDeep = (baseIsEqualDeep);

// EXTERNAL MODULE: ./node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/isObjectLike.js
var isObjectLike = __webpack_require__(95690);
;// CONCATENATED MODULE: ./node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/_baseIsEqual.js



/**
 * The base implementation of `_.isEqual` which supports partial comparisons
 * and tracks traversed objects.
 *
 * @private
 * @param {*} value The value to compare.
 * @param {*} other The other value to compare.
 * @param {boolean} bitmask The bitmask flags.
 *  1 - Unordered comparison
 *  2 - Partial comparison
 * @param {Function} [customizer] The function to customize comparisons.
 * @param {Object} [stack] Tracks traversed `value` and `other` objects.
 * @returns {boolean} Returns `true` if the values are equivalent, else `false`.
 */
function baseIsEqual(value, other, bitmask, customizer, stack) {
  if (value === other) {
    return true;
  }
  if (value == null || other == null || (!(0,isObjectLike/* default */.Z)(value) && !(0,isObjectLike/* default */.Z)(other))) {
    return value !== value && other !== other;
  }
  return _baseIsEqualDeep(value, other, bitmask, customizer, baseIsEqual, stack);
}

/* harmony default export */ const _baseIsEqual = (baseIsEqual);

;// CONCATENATED MODULE: ./node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/_baseIsMatch.js



/** Used to compose bitmasks for value comparisons. */
var _baseIsMatch_COMPARE_PARTIAL_FLAG = 1,
    _baseIsMatch_COMPARE_UNORDERED_FLAG = 2;

/**
 * The base implementation of `_.isMatch` without support for iteratee shorthands.
 *
 * @private
 * @param {Object} object The object to inspect.
 * @param {Object} source The object of property values to match.
 * @param {Array} matchData The property names, values, and compare flags to match.
 * @param {Function} [customizer] The function to customize comparisons.
 * @returns {boolean} Returns `true` if `object` is a match, else `false`.
 */
function baseIsMatch(object, source, matchData, customizer) {
  var index = matchData.length,
      length = index,
      noCustomizer = !customizer;

  if (object == null) {
    return !length;
  }
  object = Object(object);
  while (index--) {
    var data = matchData[index];
    if ((noCustomizer && data[2])
          ? data[1] !== object[data[0]]
          : !(data[0] in object)
        ) {
      return false;
    }
  }
  while (++index < length) {
    data = matchData[index];
    var key = data[0],
        objValue = object[key],
        srcValue = data[1];

    if (noCustomizer && data[2]) {
      if (objValue === undefined && !(key in object)) {
        return false;
      }
    } else {
      var stack = new _Stack/* default */.Z;
      if (customizer) {
        var result = customizer(objValue, srcValue, key, object, source, stack);
      }
      if (!(result === undefined
            ? _baseIsEqual(srcValue, objValue, _baseIsMatch_COMPARE_PARTIAL_FLAG | _baseIsMatch_COMPARE_UNORDERED_FLAG, customizer, stack)
            : result
          )) {
        return false;
      }
    }
  }
  return true;
}

/* harmony default export */ const _baseIsMatch = (baseIsMatch);

// EXTERNAL MODULE: ./node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/isObject.js
var isObject = __webpack_require__(62893);
;// CONCATENATED MODULE: ./node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/_isStrictComparable.js


/**
 * Checks if `value` is suitable for strict equality comparisons, i.e. `===`.
 *
 * @private
 * @param {*} value The value to check.
 * @returns {boolean} Returns `true` if `value` if suitable for strict
 *  equality comparisons, else `false`.
 */
function isStrictComparable(value) {
  return value === value && !(0,isObject/* default */.Z)(value);
}

/* harmony default export */ const _isStrictComparable = (isStrictComparable);

;// CONCATENATED MODULE: ./node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/_getMatchData.js



/**
 * Gets the property names, values, and compare flags of `object`.
 *
 * @private
 * @param {Object} object The object to query.
 * @returns {Array} Returns the match data of `object`.
 */
function getMatchData(object) {
  var result = (0,keys/* default */.Z)(object),
      length = result.length;

  while (length--) {
    var key = result[length],
        value = object[key];

    result[length] = [key, value, _isStrictComparable(value)];
  }
  return result;
}

/* harmony default export */ const _getMatchData = (getMatchData);

;// CONCATENATED MODULE: ./node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/_matchesStrictComparable.js
/**
 * A specialized version of `matchesProperty` for source values suitable
 * for strict equality comparisons, i.e. `===`.
 *
 * @private
 * @param {string} key The key of the property to get.
 * @param {*} srcValue The value to match.
 * @returns {Function} Returns the new spec function.
 */
function matchesStrictComparable(key, srcValue) {
  return function(object) {
    if (object == null) {
      return false;
    }
    return object[key] === srcValue &&
      (srcValue !== undefined || (key in Object(object)));
  };
}

/* harmony default export */ const _matchesStrictComparable = (matchesStrictComparable);

;// CONCATENATED MODULE: ./node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/_baseMatches.js




/**
 * The base implementation of `_.matches` which doesn't clone `source`.
 *
 * @private
 * @param {Object} source The object of property values to match.
 * @returns {Function} Returns the new spec function.
 */
function baseMatches(source) {
  var matchData = _getMatchData(source);
  if (matchData.length == 1 && matchData[0][2]) {
    return _matchesStrictComparable(matchData[0][0], matchData[0][1]);
  }
  return function(object) {
    return object === source || _baseIsMatch(object, source, matchData);
  };
}

/* harmony default export */ const _baseMatches = (baseMatches);

// EXTERNAL MODULE: ./node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/get.js
var get = __webpack_require__(63784);
// EXTERNAL MODULE: ./node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/hasIn.js + 2 modules
var hasIn = __webpack_require__(94723);
// EXTERNAL MODULE: ./node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/_isKey.js
var _isKey = __webpack_require__(24993);
// EXTERNAL MODULE: ./node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/_toKey.js
var _toKey = __webpack_require__(53069);
;// CONCATENATED MODULE: ./node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/_baseMatchesProperty.js








/** Used to compose bitmasks for value comparisons. */
var _baseMatchesProperty_COMPARE_PARTIAL_FLAG = 1,
    _baseMatchesProperty_COMPARE_UNORDERED_FLAG = 2;

/**
 * The base implementation of `_.matchesProperty` which doesn't clone `srcValue`.
 *
 * @private
 * @param {string} path The path of the property to get.
 * @param {*} srcValue The value to match.
 * @returns {Function} Returns the new spec function.
 */
function baseMatchesProperty(path, srcValue) {
  if ((0,_isKey/* default */.Z)(path) && _isStrictComparable(srcValue)) {
    return _matchesStrictComparable((0,_toKey/* default */.Z)(path), srcValue);
  }
  return function(object) {
    var objValue = (0,get/* default */.Z)(object, path);
    return (objValue === undefined && objValue === srcValue)
      ? (0,hasIn/* default */.Z)(object, path)
      : _baseIsEqual(srcValue, objValue, _baseMatchesProperty_COMPARE_PARTIAL_FLAG | _baseMatchesProperty_COMPARE_UNORDERED_FLAG);
  };
}

/* harmony default export */ const _baseMatchesProperty = (baseMatchesProperty);

// EXTERNAL MODULE: ./node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/identity.js
var identity = __webpack_require__(91130);
// EXTERNAL MODULE: ./node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/_baseProperty.js
var _baseProperty = __webpack_require__(35661);
// EXTERNAL MODULE: ./node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/_baseGet.js
var _baseGet = __webpack_require__(42043);
;// CONCATENATED MODULE: ./node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/_basePropertyDeep.js


/**
 * A specialized version of `baseProperty` which supports deep paths.
 *
 * @private
 * @param {Array|string} path The path of the property to get.
 * @returns {Function} Returns the new accessor function.
 */
function basePropertyDeep(path) {
  return function(object) {
    return (0,_baseGet/* default */.Z)(object, path);
  };
}

/* harmony default export */ const _basePropertyDeep = (basePropertyDeep);

;// CONCATENATED MODULE: ./node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/property.js





/**
 * Creates a function that returns the value at `path` of a given object.
 *
 * @static
 * @memberOf _
 * @since 2.4.0
 * @category Util
 * @param {Array|string} path The path of the property to get.
 * @returns {Function} Returns the new accessor function.
 * @example
 *
 * var objects = [
 *   { 'a': { 'b': 2 } },
 *   { 'a': { 'b': 1 } }
 * ];
 *
 * _.map(objects, _.property('a.b'));
 * // => [2, 1]
 *
 * _.map(_.sortBy(objects, _.property(['a', 'b'])), 'a.b');
 * // => [1, 2]
 */
function property(path) {
  return (0,_isKey/* default */.Z)(path) ? (0,_baseProperty/* default */.Z)((0,_toKey/* default */.Z)(path)) : _basePropertyDeep(path);
}

/* harmony default export */ const lodash_es_property = (property);

;// CONCATENATED MODULE: ./node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/_baseIteratee.js






/**
 * The base implementation of `_.iteratee`.
 *
 * @private
 * @param {*} [value=_.identity] The value to convert to an iteratee.
 * @returns {Function} Returns the iteratee.
 */
function baseIteratee(value) {
  // Don't store the `typeof` result in a variable to avoid a JIT bug in Safari 9.
  // See https://bugs.webkit.org/show_bug.cgi?id=156034 for more details.
  if (typeof value == 'function') {
    return value;
  }
  if (value == null) {
    return identity/* default */.Z;
  }
  if (typeof value == 'object') {
    return (0,isArray/* default */.Z)(value)
      ? _baseMatchesProperty(value[0], value[1])
      : _baseMatches(value);
  }
  return lodash_es_property(value);
}

/* harmony default export */ const _baseIteratee = (baseIteratee);


/***/ }),

/***/ 35661:
/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {

"use strict";
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "Z": () => (__WEBPACK_DEFAULT_EXPORT__)
/* harmony export */ });
/**
 * The base implementation of `_.property` without support for deep paths.
 *
 * @private
 * @param {string} key The key of the property to get.
 * @returns {Function} Returns the new accessor function.
 */
function baseProperty(key) {
  return function(object) {
    return object == null ? undefined : object[key];
  };
}

/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (baseProperty);


/***/ }),

/***/ 39185:
/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {

"use strict";
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "Z": () => (__WEBPACK_DEFAULT_EXPORT__)
/* harmony export */ });
/* harmony import */ var _identity_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(91130);
/* harmony import */ var _overRest_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(53281);
/* harmony import */ var _setToString_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(26826);




/**
 * The base implementation of `_.rest` which doesn't validate or coerce arguments.
 *
 * @private
 * @param {Function} func The function to apply a rest parameter to.
 * @param {number} [start=func.length-1] The start position of the rest parameter.
 * @returns {Function} Returns the new function.
 */
function baseRest(func, start) {
  return (0,_setToString_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"] */ .Z)((0,_overRest_js__WEBPACK_IMPORTED_MODULE_1__/* ["default"] */ .Z)(func, start, _identity_js__WEBPACK_IMPORTED_MODULE_2__/* ["default"] */ .Z), func + '');
}

/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (baseRest);


/***/ }),

/***/ 43123:
/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {

"use strict";
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "Z": () => (__WEBPACK_DEFAULT_EXPORT__)
/* harmony export */ });
/* harmony import */ var _Symbol_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(19474);
/* harmony import */ var _arrayMap_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(59606);
/* harmony import */ var _isArray_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(24254);
/* harmony import */ var _isSymbol_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(12281);





/** Used as references for various `Number` constants. */
var INFINITY = 1 / 0;

/** Used to convert symbols to primitives and strings. */
var symbolProto = _Symbol_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"] */ .Z ? _Symbol_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"].prototype */ .Z.prototype : undefined,
    symbolToString = symbolProto ? symbolProto.toString : undefined;

/**
 * The base implementation of `_.toString` which doesn't convert nullish
 * values to empty strings.
 *
 * @private
 * @param {*} value The value to process.
 * @returns {string} Returns the string.
 */
function baseToString(value) {
  // Exit early for strings to avoid a performance hit in some environments.
  if (typeof value == 'string') {
    return value;
  }
  if ((0,_isArray_js__WEBPACK_IMPORTED_MODULE_1__/* ["default"] */ .Z)(value)) {
    // Recursively convert values (susceptible to call stack limits).
    return (0,_arrayMap_js__WEBPACK_IMPORTED_MODULE_2__/* ["default"] */ .Z)(value, baseToString) + '';
  }
  if ((0,_isSymbol_js__WEBPACK_IMPORTED_MODULE_3__/* ["default"] */ .Z)(value)) {
    return symbolToString ? symbolToString.call(value) : '';
  }
  var result = (value + '');
  return (result == '0' && (1 / value) == -INFINITY) ? '-0' : result;
}

/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (baseToString);


/***/ }),

/***/ 10451:
/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {

"use strict";
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "Z": () => (__WEBPACK_DEFAULT_EXPORT__)
/* harmony export */ });
/* harmony import */ var _trimmedEndIndex_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(23254);


/** Used to match leading whitespace. */
var reTrimStart = /^\s+/;

/**
 * The base implementation of `_.trim`.
 *
 * @private
 * @param {string} string The string to trim.
 * @returns {string} Returns the trimmed string.
 */
function baseTrim(string) {
  return string
    ? string.slice(0, (0,_trimmedEndIndex_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"] */ .Z)(string) + 1).replace(reTrimStart, '')
    : string;
}

/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (baseTrim);


/***/ }),

/***/ 31862:
/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {

"use strict";
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "Z": () => (__WEBPACK_DEFAULT_EXPORT__)
/* harmony export */ });
/**
 * The base implementation of `_.unary` without support for storing metadata.
 *
 * @private
 * @param {Function} func The function to cap arguments for.
 * @returns {Function} Returns the new capped function.
 */
function baseUnary(func) {
  return function(value) {
    return func(value);
  };
}

/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (baseUnary);


/***/ }),

/***/ 70093:
/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {

"use strict";
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "Z": () => (__WEBPACK_DEFAULT_EXPORT__)
/* harmony export */ });
/* harmony import */ var _isArray_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(24254);
/* harmony import */ var _isKey_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(24993);
/* harmony import */ var _stringToPath_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(2826);
/* harmony import */ var _toString_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(18316);





/**
 * Casts `value` to a path array if it's not one.
 *
 * @private
 * @param {*} value The value to inspect.
 * @param {Object} [object] The object to query keys on.
 * @returns {Array} Returns the cast property path array.
 */
function castPath(value, object) {
  if ((0,_isArray_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"] */ .Z)(value)) {
    return value;
  }
  return (0,_isKey_js__WEBPACK_IMPORTED_MODULE_1__/* ["default"] */ .Z)(value, object) ? [value] : (0,_stringToPath_js__WEBPACK_IMPORTED_MODULE_2__/* ["default"] */ .Z)((0,_toString_js__WEBPACK_IMPORTED_MODULE_3__/* ["default"] */ .Z)(value));
}

/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (castPath);


/***/ }),

/***/ 38633:
/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {

"use strict";
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "Z": () => (__WEBPACK_DEFAULT_EXPORT__)
/* harmony export */ });
/* harmony import */ var _root_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(5665);


/** Used to detect overreaching core-js shims. */
var coreJsData = _root_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"]["__core-js_shared__"] */ .Z["__core-js_shared__"];

/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (coreJsData);


/***/ }),

/***/ 97024:
/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {

"use strict";
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "Z": () => (__WEBPACK_DEFAULT_EXPORT__)
/* harmony export */ });
/* harmony import */ var _getNative_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(80156);


var defineProperty = (function() {
  try {
    var func = (0,_getNative_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"] */ .Z)(Object, 'defineProperty');
    func({}, '', {});
    return func;
  } catch (e) {}
}());

/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (defineProperty);


/***/ }),

/***/ 45249:
/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {

"use strict";
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "Z": () => (__WEBPACK_DEFAULT_EXPORT__)
/* harmony export */ });
/** Detect free variable `global` from Node.js. */
var freeGlobal = typeof global == 'object' && global && global.Object === Object && global;

/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (freeGlobal);


/***/ }),

/***/ 91357:
/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {

"use strict";
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "Z": () => (__WEBPACK_DEFAULT_EXPORT__)
/* harmony export */ });
/* harmony import */ var _isKeyable_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(76918);


/**
 * Gets the data for `map`.
 *
 * @private
 * @param {Object} map The map to query.
 * @param {string} key The reference key.
 * @returns {*} Returns the map data.
 */
function getMapData(map, key) {
  var data = map.__data__;
  return (0,_isKeyable_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"] */ .Z)(key)
    ? data[typeof key == 'string' ? 'string' : 'hash']
    : data.map;
}

/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (getMapData);


/***/ }),

/***/ 80156:
/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {

"use strict";
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "Z": () => (__WEBPACK_DEFAULT_EXPORT__)
/* harmony export */ });
/* harmony import */ var _baseIsNative_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(34558);
/* harmony import */ var _getValue_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(53871);



/**
 * Gets the native function at `key` of `object`.
 *
 * @private
 * @param {Object} object The object to query.
 * @param {string} key The key of the method to get.
 * @returns {*} Returns the function if it's native, else `undefined`.
 */
function getNative(object, key) {
  var value = (0,_getValue_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"] */ .Z)(object, key);
  return (0,_baseIsNative_js__WEBPACK_IMPORTED_MODULE_1__/* ["default"] */ .Z)(value) ? value : undefined;
}

/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (getNative);


/***/ }),

/***/ 1866:
/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {

"use strict";
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "Z": () => (__WEBPACK_DEFAULT_EXPORT__)
/* harmony export */ });
/* harmony import */ var _Symbol_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(19474);


/** Used for built-in method references. */
var objectProto = Object.prototype;

/** Used to check objects for own properties. */
var hasOwnProperty = objectProto.hasOwnProperty;

/**
 * Used to resolve the
 * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring)
 * of values.
 */
var nativeObjectToString = objectProto.toString;

/** Built-in value references. */
var symToStringTag = _Symbol_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"] */ .Z ? _Symbol_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"].toStringTag */ .Z.toStringTag : undefined;

/**
 * A specialized version of `baseGetTag` which ignores `Symbol.toStringTag` values.
 *
 * @private
 * @param {*} value The value to query.
 * @returns {string} Returns the raw `toStringTag`.
 */
function getRawTag(value) {
  var isOwn = hasOwnProperty.call(value, symToStringTag),
      tag = value[symToStringTag];

  try {
    value[symToStringTag] = undefined;
    var unmasked = true;
  } catch (e) {}

  var result = nativeObjectToString.call(value);
  if (unmasked) {
    if (isOwn) {
      value[symToStringTag] = tag;
    } else {
      delete value[symToStringTag];
    }
  }
  return result;
}

/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (getRawTag);


/***/ }),

/***/ 53871:
/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {

"use strict";
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "Z": () => (__WEBPACK_DEFAULT_EXPORT__)
/* harmony export */ });
/**
 * Gets the value at `key` of `object`.
 *
 * @private
 * @param {Object} [object] The object to query.
 * @param {string} key The key of the property to get.
 * @returns {*} Returns the property value.
 */
function getValue(object, key) {
  return object == null ? undefined : object[key];
}

/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (getValue);


/***/ }),

/***/ 17307:
/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {

"use strict";
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "Z": () => (__WEBPACK_DEFAULT_EXPORT__)
/* harmony export */ });
/* harmony import */ var _nativeCreate_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(54478);


/**
 * Removes all key-value entries from the hash.
 *
 * @private
 * @name clear
 * @memberOf Hash
 */
function hashClear() {
  this.__data__ = _nativeCreate_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"] */ .Z ? (0,_nativeCreate_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"] */ .Z)(null) : {};
  this.size = 0;
}

/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (hashClear);


/***/ }),

/***/ 19668:
/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {

"use strict";
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "Z": () => (__WEBPACK_DEFAULT_EXPORT__)
/* harmony export */ });
/**
 * Removes `key` and its value from the hash.
 *
 * @private
 * @name delete
 * @memberOf Hash
 * @param {Object} hash The hash to modify.
 * @param {string} key The key of the value to remove.
 * @returns {boolean} Returns `true` if the entry was removed, else `false`.
 */
function hashDelete(key) {
  var result = this.has(key) && delete this.__data__[key];
  this.size -= result ? 1 : 0;
  return result;
}

/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (hashDelete);


/***/ }),

/***/ 71450:
/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {

"use strict";
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "Z": () => (__WEBPACK_DEFAULT_EXPORT__)
/* harmony export */ });
/* harmony import */ var _nativeCreate_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(54478);


/** Used to stand-in for `undefined` hash values. */
var HASH_UNDEFINED = '__lodash_hash_undefined__';

/** Used for built-in method references. */
var objectProto = Object.prototype;

/** Used to check objects for own properties. */
var hasOwnProperty = objectProto.hasOwnProperty;

/**
 * Gets the hash value for `key`.
 *
 * @private
 * @name get
 * @memberOf Hash
 * @param {string} key The key of the value to get.
 * @returns {*} Returns the entry value.
 */
function hashGet(key) {
  var data = this.__data__;
  if (_nativeCreate_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"] */ .Z) {
    var result = data[key];
    return result === HASH_UNDEFINED ? undefined : result;
  }
  return hasOwnProperty.call(data, key) ? data[key] : undefined;
}

/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (hashGet);


/***/ }),

/***/ 10423:
/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {

"use strict";
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "Z": () => (__WEBPACK_DEFAULT_EXPORT__)
/* harmony export */ });
/* harmony import */ var _nativeCreate_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(54478);


/** Used for built-in method references. */
var objectProto = Object.prototype;

/** Used to check objects for own properties. */
var hasOwnProperty = objectProto.hasOwnProperty;

/**
 * Checks if a hash value for `key` exists.
 *
 * @private
 * @name has
 * @memberOf Hash
 * @param {string} key The key of the entry to check.
 * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.
 */
function hashHas(key) {
  var data = this.__data__;
  return _nativeCreate_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"] */ .Z ? (data[key] !== undefined) : hasOwnProperty.call(data, key);
}

/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (hashHas);


/***/ }),

/***/ 24734:
/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {

"use strict";
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "Z": () => (__WEBPACK_DEFAULT_EXPORT__)
/* harmony export */ });
/* harmony import */ var _nativeCreate_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(54478);


/** Used to stand-in for `undefined` hash values. */
var HASH_UNDEFINED = '__lodash_hash_undefined__';

/**
 * Sets the hash `key` to `value`.
 *
 * @private
 * @name set
 * @memberOf Hash
 * @param {string} key The key of the value to set.
 * @param {*} value The value to set.
 * @returns {Object} Returns the hash instance.
 */
function hashSet(key, value) {
  var data = this.__data__;
  this.size += this.has(key) ? 0 : 1;
  data[key] = (_nativeCreate_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"] */ .Z && value === undefined) ? HASH_UNDEFINED : value;
  return this;
}

/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (hashSet);


/***/ }),

/***/ 91661:
/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {

"use strict";
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "Z": () => (__WEBPACK_DEFAULT_EXPORT__)
/* harmony export */ });
/** Used as references for various `Number` constants. */
var MAX_SAFE_INTEGER = 9007199254740991;

/** Used to detect unsigned integer values. */
var reIsUint = /^(?:0|[1-9]\d*)$/;

/**
 * Checks if `value` is a valid array-like index.
 *
 * @private
 * @param {*} value The value to check.
 * @param {number} [length=MAX_SAFE_INTEGER] The upper bounds of a valid index.
 * @returns {boolean} Returns `true` if `value` is a valid index, else `false`.
 */
function isIndex(value, length) {
  var type = typeof value;
  length = length == null ? MAX_SAFE_INTEGER : length;

  return !!length &&
    (type == 'number' ||
      (type != 'symbol' && reIsUint.test(value))) &&
        (value > -1 && value % 1 == 0 && value < length);
}

/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (isIndex);


/***/ }),

/***/ 32554:
/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {

"use strict";
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "Z": () => (__WEBPACK_DEFAULT_EXPORT__)
/* harmony export */ });
/* harmony import */ var _eq_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(99581);
/* harmony import */ var _isArrayLike_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(2762);
/* harmony import */ var _isIndex_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(91661);
/* harmony import */ var _isObject_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(62893);





/**
 * Checks if the given arguments are from an iteratee call.
 *
 * @private
 * @param {*} value The potential iteratee value argument.
 * @param {*} index The potential iteratee index or key argument.
 * @param {*} object The potential iteratee object argument.
 * @returns {boolean} Returns `true` if the arguments are from an iteratee call,
 *  else `false`.
 */
function isIterateeCall(value, index, object) {
  if (!(0,_isObject_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"] */ .Z)(object)) {
    return false;
  }
  var type = typeof index;
  if (type == 'number'
        ? ((0,_isArrayLike_js__WEBPACK_IMPORTED_MODULE_1__/* ["default"] */ .Z)(object) && (0,_isIndex_js__WEBPACK_IMPORTED_MODULE_2__/* ["default"] */ .Z)(index, object.length))
        : (type == 'string' && index in object)
      ) {
    return (0,_eq_js__WEBPACK_IMPORTED_MODULE_3__/* ["default"] */ .Z)(object[index], value);
  }
  return false;
}

/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (isIterateeCall);


/***/ }),

/***/ 24993:
/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {

"use strict";
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "Z": () => (__WEBPACK_DEFAULT_EXPORT__)
/* harmony export */ });
/* harmony import */ var _isArray_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(24254);
/* harmony import */ var _isSymbol_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(12281);



/** Used to match property names within property paths. */
var reIsDeepProp = /\.|\[(?:[^[\]]*|(["'])(?:(?!\1)[^\\]|\\.)*?\1)\]/,
    reIsPlainProp = /^\w*$/;

/**
 * Checks if `value` is a property name and not a property path.
 *
 * @private
 * @param {*} value The value to check.
 * @param {Object} [object] The object to query keys on.
 * @returns {boolean} Returns `true` if `value` is a property name, else `false`.
 */
function isKey(value, object) {
  if ((0,_isArray_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"] */ .Z)(value)) {
    return false;
  }
  var type = typeof value;
  if (type == 'number' || type == 'symbol' || type == 'boolean' ||
      value == null || (0,_isSymbol_js__WEBPACK_IMPORTED_MODULE_1__/* ["default"] */ .Z)(value)) {
    return true;
  }
  return reIsPlainProp.test(value) || !reIsDeepProp.test(value) ||
    (object != null && value in Object(object));
}

/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (isKey);


/***/ }),

/***/ 76918:
/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {

"use strict";
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "Z": () => (__WEBPACK_DEFAULT_EXPORT__)
/* harmony export */ });
/**
 * Checks if `value` is suitable for use as unique object key.
 *
 * @private
 * @param {*} value The value to check.
 * @returns {boolean} Returns `true` if `value` is suitable, else `false`.
 */
function isKeyable(value) {
  var type = typeof value;
  return (type == 'string' || type == 'number' || type == 'symbol' || type == 'boolean')
    ? (value !== '__proto__')
    : (value === null);
}

/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (isKeyable);


/***/ }),

/***/ 66836:
/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {

"use strict";
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "Z": () => (__WEBPACK_DEFAULT_EXPORT__)
/* harmony export */ });
/* harmony import */ var _coreJsData_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(38633);


/** Used to detect methods masquerading as native. */
var maskSrcKey = (function() {
  var uid = /[^.]+$/.exec(_coreJsData_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"] */ .Z && _coreJsData_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"].keys */ .Z.keys && _coreJsData_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"].keys.IE_PROTO */ .Z.keys.IE_PROTO || '');
  return uid ? ('Symbol(src)_1.' + uid) : '';
}());

/**
 * Checks if `func` has its source masked.
 *
 * @private
 * @param {Function} func The function to check.
 * @returns {boolean} Returns `true` if `func` is masked, else `false`.
 */
function isMasked(func) {
  return !!maskSrcKey && (maskSrcKey in func);
}

/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (isMasked);


/***/ }),

/***/ 41040:
/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {

"use strict";
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "Z": () => (__WEBPACK_DEFAULT_EXPORT__)
/* harmony export */ });
/** Used for built-in method references. */
var objectProto = Object.prototype;

/**
 * Checks if `value` is likely a prototype object.
 *
 * @private
 * @param {*} value The value to check.
 * @returns {boolean} Returns `true` if `value` is a prototype, else `false`.
 */
function isPrototype(value) {
  var Ctor = value && value.constructor,
      proto = (typeof Ctor == 'function' && Ctor.prototype) || objectProto;

  return value === proto;
}

/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (isPrototype);


/***/ }),

/***/ 22737:
/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {

"use strict";
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "Z": () => (__WEBPACK_DEFAULT_EXPORT__)
/* harmony export */ });
/**
 * Removes all key-value entries from the list cache.
 *
 * @private
 * @name clear
 * @memberOf ListCache
 */
function listCacheClear() {
  this.__data__ = [];
  this.size = 0;
}

/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (listCacheClear);


/***/ }),

/***/ 53229:
/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {

"use strict";
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "Z": () => (__WEBPACK_DEFAULT_EXPORT__)
/* harmony export */ });
/* harmony import */ var _assocIndexOf_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(54171);


/** Used for built-in method references. */
var arrayProto = Array.prototype;

/** Built-in value references. */
var splice = arrayProto.splice;

/**
 * Removes `key` and its value from the list cache.
 *
 * @private
 * @name delete
 * @memberOf ListCache
 * @param {string} key The key of the value to remove.
 * @returns {boolean} Returns `true` if the entry was removed, else `false`.
 */
function listCacheDelete(key) {
  var data = this.__data__,
      index = (0,_assocIndexOf_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"] */ .Z)(data, key);

  if (index < 0) {
    return false;
  }
  var lastIndex = data.length - 1;
  if (index == lastIndex) {
    data.pop();
  } else {
    splice.call(data, index, 1);
  }
  --this.size;
  return true;
}

/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (listCacheDelete);


/***/ }),

/***/ 80438:
/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {

"use strict";
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "Z": () => (__WEBPACK_DEFAULT_EXPORT__)
/* harmony export */ });
/* harmony import */ var _assocIndexOf_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(54171);


/**
 * Gets the list cache value for `key`.
 *
 * @private
 * @name get
 * @memberOf ListCache
 * @param {string} key The key of the value to get.
 * @returns {*} Returns the entry value.
 */
function listCacheGet(key) {
  var data = this.__data__,
      index = (0,_assocIndexOf_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"] */ .Z)(data, key);

  return index < 0 ? undefined : data[index][1];
}

/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (listCacheGet);


/***/ }),

/***/ 73375:
/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {

"use strict";
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "Z": () => (__WEBPACK_DEFAULT_EXPORT__)
/* harmony export */ });
/* harmony import */ var _assocIndexOf_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(54171);


/**
 * Checks if a list cache value for `key` exists.
 *
 * @private
 * @name has
 * @memberOf ListCache
 * @param {string} key The key of the entry to check.
 * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.
 */
function listCacheHas(key) {
  return (0,_assocIndexOf_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"] */ .Z)(this.__data__, key) > -1;
}

/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (listCacheHas);


/***/ }),

/***/ 24957:
/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {

"use strict";
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "Z": () => (__WEBPACK_DEFAULT_EXPORT__)
/* harmony export */ });
/* harmony import */ var _assocIndexOf_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(54171);


/**
 * Sets the list cache `key` to `value`.
 *
 * @private
 * @name set
 * @memberOf ListCache
 * @param {string} key The key of the value to set.
 * @param {*} value The value to set.
 * @returns {Object} Returns the list cache instance.
 */
function listCacheSet(key, value) {
  var data = this.__data__,
      index = (0,_assocIndexOf_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"] */ .Z)(data, key);

  if (index < 0) {
    ++this.size;
    data.push([key, value]);
  } else {
    data[index][1] = value;
  }
  return this;
}

/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (listCacheSet);


/***/ }),

/***/ 27697:
/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {

"use strict";
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "Z": () => (__WEBPACK_DEFAULT_EXPORT__)
/* harmony export */ });
/* harmony import */ var _Hash_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(7462);
/* harmony import */ var _ListCache_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(9932);
/* harmony import */ var _Map_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(3806);




/**
 * Removes all key-value entries from the map.
 *
 * @private
 * @name clear
 * @memberOf MapCache
 */
function mapCacheClear() {
  this.size = 0;
  this.__data__ = {
    'hash': new _Hash_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"] */ .Z,
    'map': new (_Map_js__WEBPACK_IMPORTED_MODULE_1__/* ["default"] */ .Z || _ListCache_js__WEBPACK_IMPORTED_MODULE_2__/* ["default"] */ .Z),
    'string': new _Hash_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"] */ .Z
  };
}

/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (mapCacheClear);


/***/ }),

/***/ 72633:
/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {

"use strict";
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "Z": () => (__WEBPACK_DEFAULT_EXPORT__)
/* harmony export */ });
/* harmony import */ var _getMapData_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(91357);


/**
 * Removes `key` and its value from the map.
 *
 * @private
 * @name delete
 * @memberOf MapCache
 * @param {string} key The key of the value to remove.
 * @returns {boolean} Returns `true` if the entry was removed, else `false`.
 */
function mapCacheDelete(key) {
  var result = (0,_getMapData_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"] */ .Z)(this, key)['delete'](key);
  this.size -= result ? 1 : 0;
  return result;
}

/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (mapCacheDelete);


/***/ }),

/***/ 59465:
/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {

"use strict";
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "Z": () => (__WEBPACK_DEFAULT_EXPORT__)
/* harmony export */ });
/* harmony import */ var _getMapData_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(91357);


/**
 * Gets the map value for `key`.
 *
 * @private
 * @name get
 * @memberOf MapCache
 * @param {string} key The key of the value to get.
 * @returns {*} Returns the entry value.
 */
function mapCacheGet(key) {
  return (0,_getMapData_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"] */ .Z)(this, key).get(key);
}

/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (mapCacheGet);


/***/ }),

/***/ 62117:
/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {

"use strict";
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "Z": () => (__WEBPACK_DEFAULT_EXPORT__)
/* harmony export */ });
/* harmony import */ var _getMapData_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(91357);


/**
 * Checks if a map value for `key` exists.
 *
 * @private
 * @name has
 * @memberOf MapCache
 * @param {string} key The key of the entry to check.
 * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.
 */
function mapCacheHas(key) {
  return (0,_getMapData_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"] */ .Z)(this, key).has(key);
}

/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (mapCacheHas);


/***/ }),

/***/ 69481:
/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {

"use strict";
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "Z": () => (__WEBPACK_DEFAULT_EXPORT__)
/* harmony export */ });
/* harmony import */ var _getMapData_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(91357);


/**
 * Sets the map `key` to `value`.
 *
 * @private
 * @name set
 * @memberOf MapCache
 * @param {string} key The key of the value to set.
 * @param {*} value The value to set.
 * @returns {Object} Returns the map cache instance.
 */
function mapCacheSet(key, value) {
  var data = (0,_getMapData_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"] */ .Z)(this, key),
      size = data.size;

  data.set(key, value);
  this.size += data.size == size ? 0 : 1;
  return this;
}

/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (mapCacheSet);


/***/ }),

/***/ 11065:
/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {

"use strict";
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "Z": () => (__WEBPACK_DEFAULT_EXPORT__)
/* harmony export */ });
/* harmony import */ var _memoize_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(82287);


/** Used as the maximum memoize cache size. */
var MAX_MEMOIZE_SIZE = 500;

/**
 * A specialized version of `_.memoize` which clears the memoized function's
 * cache when it exceeds `MAX_MEMOIZE_SIZE`.
 *
 * @private
 * @param {Function} func The function to have its output memoized.
 * @returns {Function} Returns the new memoized function.
 */
function memoizeCapped(func) {
  var result = (0,_memoize_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"] */ .Z)(func, function(key) {
    if (cache.size === MAX_MEMOIZE_SIZE) {
      cache.clear();
    }
    return key;
  });

  var cache = result.cache;
  return result;
}

/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (memoizeCapped);


/***/ }),

/***/ 54478:
/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {

"use strict";
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "Z": () => (__WEBPACK_DEFAULT_EXPORT__)
/* harmony export */ });
/* harmony import */ var _getNative_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(80156);


/* Built-in method references that are verified to be native. */
var nativeCreate = (0,_getNative_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"] */ .Z)(Object, 'create');

/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (nativeCreate);


/***/ }),

/***/ 76773:
/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {

"use strict";
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "Z": () => (__WEBPACK_DEFAULT_EXPORT__)
/* harmony export */ });
/* harmony import */ var _freeGlobal_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(45249);


/** Detect free variable `exports`. */
var freeExports = typeof exports == 'object' && exports && !exports.nodeType && exports;

/** Detect free variable `module`. */
var freeModule = freeExports && typeof module == 'object' && module && !module.nodeType && module;

/** Detect the popular CommonJS extension `module.exports`. */
var moduleExports = freeModule && freeModule.exports === freeExports;

/** Detect free variable `process` from Node.js. */
var freeProcess = moduleExports && _freeGlobal_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"].process */ .Z.process;

/** Used to access faster Node.js helpers. */
var nodeUtil = (function() {
  try {
    // Use `util.types` for Node.js 10+.
    var types = freeModule && freeModule.require && freeModule.require('util').types;

    if (types) {
      return types;
    }

    // Legacy `process.binding('util')` for Node.js < 10.
    return freeProcess && freeProcess.binding && freeProcess.binding('util');
  } catch (e) {}
}());

/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (nodeUtil);


/***/ }),

/***/ 31710:
/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {

"use strict";
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "Z": () => (__WEBPACK_DEFAULT_EXPORT__)
/* harmony export */ });
/** Used for built-in method references. */
var objectProto = Object.prototype;

/**
 * Used to resolve the
 * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring)
 * of values.
 */
var nativeObjectToString = objectProto.toString;

/**
 * Converts `value` to a string using `Object.prototype.toString`.
 *
 * @private
 * @param {*} value The value to convert.
 * @returns {string} Returns the converted string.
 */
function objectToString(value) {
  return nativeObjectToString.call(value);
}

/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (objectToString);


/***/ }),

/***/ 6438:
/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {

"use strict";
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "Z": () => (__WEBPACK_DEFAULT_EXPORT__)
/* harmony export */ });
/**
 * Creates a unary function that invokes `func` with its argument transformed.
 *
 * @private
 * @param {Function} func The function to wrap.
 * @param {Function} transform The argument transform.
 * @returns {Function} Returns the new function.
 */
function overArg(func, transform) {
  return function(arg) {
    return func(transform(arg));
  };
}

/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (overArg);


/***/ }),

/***/ 53281:
/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {

"use strict";

// EXPORTS
__webpack_require__.d(__webpack_exports__, {
  "Z": () => (/* binding */ _overRest)
});

;// CONCATENATED MODULE: ./node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/_apply.js
/**
 * A faster alternative to `Function#apply`, this function invokes `func`
 * with the `this` binding of `thisArg` and the arguments of `args`.
 *
 * @private
 * @param {Function} func The function to invoke.
 * @param {*} thisArg The `this` binding of `func`.
 * @param {Array} args The arguments to invoke `func` with.
 * @returns {*} Returns the result of `func`.
 */
function apply(func, thisArg, args) {
  switch (args.length) {
    case 0: return func.call(thisArg);
    case 1: return func.call(thisArg, args[0]);
    case 2: return func.call(thisArg, args[0], args[1]);
    case 3: return func.call(thisArg, args[0], args[1], args[2]);
  }
  return func.apply(thisArg, args);
}

/* harmony default export */ const _apply = (apply);

;// CONCATENATED MODULE: ./node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/_overRest.js


/* Built-in method references for those with the same name as other `lodash` methods. */
var nativeMax = Math.max;

/**
 * A specialized version of `baseRest` which transforms the rest array.
 *
 * @private
 * @param {Function} func The function to apply a rest parameter to.
 * @param {number} [start=func.length-1] The start position of the rest parameter.
 * @param {Function} transform The rest array transform.
 * @returns {Function} Returns the new function.
 */
function overRest(func, start, transform) {
  start = nativeMax(start === undefined ? (func.length - 1) : start, 0);
  return function() {
    var args = arguments,
        index = -1,
        length = nativeMax(args.length - start, 0),
        array = Array(length);

    while (++index < length) {
      array[index] = args[start + index];
    }
    index = -1;
    var otherArgs = Array(start + 1);
    while (++index < start) {
      otherArgs[index] = args[index];
    }
    otherArgs[start] = transform(array);
    return _apply(func, this, otherArgs);
  };
}

/* harmony default export */ const _overRest = (overRest);


/***/ }),

/***/ 5665:
/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {

"use strict";
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "Z": () => (__WEBPACK_DEFAULT_EXPORT__)
/* harmony export */ });
/* harmony import */ var _freeGlobal_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(45249);


/** Detect free variable `self`. */
var freeSelf = typeof self == 'object' && self && self.Object === Object && self;

/** Used as a reference to the global object. */
var root = _freeGlobal_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"] */ .Z || freeSelf || Function('return this')();

/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (root);


/***/ }),

/***/ 26826:
/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {

"use strict";

// EXPORTS
__webpack_require__.d(__webpack_exports__, {
  "Z": () => (/* binding */ _setToString)
});

;// CONCATENATED MODULE: ./node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/constant.js
/**
 * Creates a function that returns `value`.
 *
 * @static
 * @memberOf _
 * @since 2.4.0
 * @category Util
 * @param {*} value The value to return from the new function.
 * @returns {Function} Returns the new constant function.
 * @example
 *
 * var objects = _.times(2, _.constant({ 'a': 1 }));
 *
 * console.log(objects);
 * // => [{ 'a': 1 }, { 'a': 1 }]
 *
 * console.log(objects[0] === objects[1]);
 * // => true
 */
function constant(value) {
  return function() {
    return value;
  };
}

/* harmony default export */ const lodash_es_constant = (constant);

// EXTERNAL MODULE: ./node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/_defineProperty.js
var _defineProperty = __webpack_require__(97024);
// EXTERNAL MODULE: ./node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/identity.js
var identity = __webpack_require__(91130);
;// CONCATENATED MODULE: ./node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/_baseSetToString.js




/**
 * The base implementation of `setToString` without support for hot loop shorting.
 *
 * @private
 * @param {Function} func The function to modify.
 * @param {Function} string The `toString` result.
 * @returns {Function} Returns `func`.
 */
var baseSetToString = !_defineProperty/* default */.Z ? identity/* default */.Z : function(func, string) {
  return (0,_defineProperty/* default */.Z)(func, 'toString', {
    'configurable': true,
    'enumerable': false,
    'value': lodash_es_constant(string),
    'writable': true
  });
};

/* harmony default export */ const _baseSetToString = (baseSetToString);

;// CONCATENATED MODULE: ./node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/_shortOut.js
/** Used to detect hot functions by number of calls within a span of milliseconds. */
var HOT_COUNT = 800,
    HOT_SPAN = 16;

/* Built-in method references for those with the same name as other `lodash` methods. */
var nativeNow = Date.now;

/**
 * Creates a function that'll short out and invoke `identity` instead
 * of `func` when it's called `HOT_COUNT` or more times in `HOT_SPAN`
 * milliseconds.
 *
 * @private
 * @param {Function} func The function to restrict.
 * @returns {Function} Returns the new shortable function.
 */
function shortOut(func) {
  var count = 0,
      lastCalled = 0;

  return function() {
    var stamp = nativeNow(),
        remaining = HOT_SPAN - (stamp - lastCalled);

    lastCalled = stamp;
    if (remaining > 0) {
      if (++count >= HOT_COUNT) {
        return arguments[0];
      }
    } else {
      count = 0;
    }
    return func.apply(undefined, arguments);
  };
}

/* harmony default export */ const _shortOut = (shortOut);

;// CONCATENATED MODULE: ./node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/_setToString.js



/**
 * Sets the `toString` method of `func` to return `string`.
 *
 * @private
 * @param {Function} func The function to modify.
 * @param {Function} string The `toString` result.
 * @returns {Function} Returns `func`.
 */
var setToString = _shortOut(_baseSetToString);

/* harmony default export */ const _setToString = (setToString);


/***/ }),

/***/ 2826:
/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {

"use strict";
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "Z": () => (__WEBPACK_DEFAULT_EXPORT__)
/* harmony export */ });
/* harmony import */ var _memoizeCapped_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(11065);


/** Used to match property names within property paths. */
var rePropName = /[^.[\]]+|\[(?:(-?\d+(?:\.\d+)?)|(["'])((?:(?!\2)[^\\]|\\.)*?)\2)\]|(?=(?:\.|\[\])(?:\.|\[\]|$))/g;

/** Used to match backslashes in property paths. */
var reEscapeChar = /\\(\\)?/g;

/**
 * Converts `string` to a property path array.
 *
 * @private
 * @param {string} string The string to convert.
 * @returns {Array} Returns the property path array.
 */
var stringToPath = (0,_memoizeCapped_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"] */ .Z)(function(string) {
  var result = [];
  if (string.charCodeAt(0) === 46 /* . */) {
    result.push('');
  }
  string.replace(rePropName, function(match, number, quote, subString) {
    result.push(quote ? subString.replace(reEscapeChar, '$1') : (number || match));
  });
  return result;
});

/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (stringToPath);


/***/ }),

/***/ 53069:
/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {

"use strict";
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "Z": () => (__WEBPACK_DEFAULT_EXPORT__)
/* harmony export */ });
/* harmony import */ var _isSymbol_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(12281);


/** Used as references for various `Number` constants. */
var INFINITY = 1 / 0;

/**
 * Converts `value` to a string key if it's not a string or symbol.
 *
 * @private
 * @param {*} value The value to inspect.
 * @returns {string|symbol} Returns the key.
 */
function toKey(value) {
  if (typeof value == 'string' || (0,_isSymbol_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"] */ .Z)(value)) {
    return value;
  }
  var result = (value + '');
  return (result == '0' && (1 / value) == -INFINITY) ? '-0' : result;
}

/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (toKey);


/***/ }),

/***/ 55736:
/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {

"use strict";
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "Z": () => (__WEBPACK_DEFAULT_EXPORT__)
/* harmony export */ });
/** Used for built-in method references. */
var funcProto = Function.prototype;

/** Used to resolve the decompiled source of functions. */
var funcToString = funcProto.toString;

/**
 * Converts `func` to its source code.
 *
 * @private
 * @param {Function} func The function to convert.
 * @returns {string} Returns the source code.
 */
function toSource(func) {
  if (func != null) {
    try {
      return funcToString.call(func);
    } catch (e) {}
    try {
      return (func + '');
    } catch (e) {}
  }
  return '';
}

/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (toSource);


/***/ }),

/***/ 23254:
/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {

"use strict";
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "Z": () => (__WEBPACK_DEFAULT_EXPORT__)
/* harmony export */ });
/** Used to match a single whitespace character. */
var reWhitespace = /\s/;

/**
 * Used by `_.trim` and `_.trimEnd` to get the index of the last non-whitespace
 * character of `string`.
 *
 * @private
 * @param {string} string The string to inspect.
 * @returns {number} Returns the index of the last non-whitespace character.
 */
function trimmedEndIndex(string) {
  var index = string.length;

  while (index-- && reWhitespace.test(string.charAt(index))) {}
  return index;
}

/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (trimmedEndIndex);


/***/ }),

/***/ 72135:
/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {

"use strict";
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "Z": () => (__WEBPACK_DEFAULT_EXPORT__)
/* harmony export */ });
/* harmony import */ var _isObject_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(62893);
/* harmony import */ var _now_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(17937);
/* harmony import */ var _toNumber_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(97400);




/** Error message constants. */
var FUNC_ERROR_TEXT = 'Expected a function';

/* Built-in method references for those with the same name as other `lodash` methods. */
var nativeMax = Math.max,
    nativeMin = Math.min;

/**
 * Creates a debounced function that delays invoking `func` until after `wait`
 * milliseconds have elapsed since the last time the debounced function was
 * invoked. The debounced function comes with a `cancel` method to cancel
 * delayed `func` invocations and a `flush` method to immediately invoke them.
 * Provide `options` to indicate whether `func` should be invoked on the
 * leading and/or trailing edge of the `wait` timeout. The `func` is invoked
 * with the last arguments provided to the debounced function. Subsequent
 * calls to the debounced function return the result of the last `func`
 * invocation.
 *
 * **Note:** If `leading` and `trailing` options are `true`, `func` is
 * invoked on the trailing edge of the timeout only if the debounced function
 * is invoked more than once during the `wait` timeout.
 *
 * If `wait` is `0` and `leading` is `false`, `func` invocation is deferred
 * until to the next tick, similar to `setTimeout` with a timeout of `0`.
 *
 * See [David Corbacho's article](https://css-tricks.com/debouncing-throttling-explained-examples/)
 * for details over the differences between `_.debounce` and `_.throttle`.
 *
 * @static
 * @memberOf _
 * @since 0.1.0
 * @category Function
 * @param {Function} func The function to debounce.
 * @param {number} [wait=0] The number of milliseconds to delay.
 * @param {Object} [options={}] The options object.
 * @param {boolean} [options.leading=false]
 *  Specify invoking on the leading edge of the timeout.
 * @param {number} [options.maxWait]
 *  The maximum time `func` is allowed to be delayed before it's invoked.
 * @param {boolean} [options.trailing=true]
 *  Specify invoking on the trailing edge of the timeout.
 * @returns {Function} Returns the new debounced function.
 * @example
 *
 * // Avoid costly calculations while the window size is in flux.
 * jQuery(window).on('resize', _.debounce(calculateLayout, 150));
 *
 * // Invoke `sendMail` when clicked, debouncing subsequent calls.
 * jQuery(element).on('click', _.debounce(sendMail, 300, {
 *   'leading': true,
 *   'trailing': false
 * }));
 *
 * // Ensure `batchLog` is invoked once after 1 second of debounced calls.
 * var debounced = _.debounce(batchLog, 250, { 'maxWait': 1000 });
 * var source = new EventSource('/stream');
 * jQuery(source).on('message', debounced);
 *
 * // Cancel the trailing debounced invocation.
 * jQuery(window).on('popstate', debounced.cancel);
 */
function debounce(func, wait, options) {
  var lastArgs,
      lastThis,
      maxWait,
      result,
      timerId,
      lastCallTime,
      lastInvokeTime = 0,
      leading = false,
      maxing = false,
      trailing = true;

  if (typeof func != 'function') {
    throw new TypeError(FUNC_ERROR_TEXT);
  }
  wait = (0,_toNumber_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"] */ .Z)(wait) || 0;
  if ((0,_isObject_js__WEBPACK_IMPORTED_MODULE_1__/* ["default"] */ .Z)(options)) {
    leading = !!options.leading;
    maxing = 'maxWait' in options;
    maxWait = maxing ? nativeMax((0,_toNumber_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"] */ .Z)(options.maxWait) || 0, wait) : maxWait;
    trailing = 'trailing' in options ? !!options.trailing : trailing;
  }

  function invokeFunc(time) {
    var args = lastArgs,
        thisArg = lastThis;

    lastArgs = lastThis = undefined;
    lastInvokeTime = time;
    result = func.apply(thisArg, args);
    return result;
  }

  function leadingEdge(time) {
    // Reset any `maxWait` timer.
    lastInvokeTime = time;
    // Start the timer for the trailing edge.
    timerId = setTimeout(timerExpired, wait);
    // Invoke the leading edge.
    return leading ? invokeFunc(time) : result;
  }

  function remainingWait(time) {
    var timeSinceLastCall = time - lastCallTime,
        timeSinceLastInvoke = time - lastInvokeTime,
        timeWaiting = wait - timeSinceLastCall;

    return maxing
      ? nativeMin(timeWaiting, maxWait - timeSinceLastInvoke)
      : timeWaiting;
  }

  function shouldInvoke(time) {
    var timeSinceLastCall = time - lastCallTime,
        timeSinceLastInvoke = time - lastInvokeTime;

    // Either this is the first call, activity has stopped and we're at the
    // trailing edge, the system time has gone backwards and we're treating
    // it as the trailing edge, or we've hit the `maxWait` limit.
    return (lastCallTime === undefined || (timeSinceLastCall >= wait) ||
      (timeSinceLastCall < 0) || (maxing && timeSinceLastInvoke >= maxWait));
  }

  function timerExpired() {
    var time = (0,_now_js__WEBPACK_IMPORTED_MODULE_2__/* ["default"] */ .Z)();
    if (shouldInvoke(time)) {
      return trailingEdge(time);
    }
    // Restart the timer.
    timerId = setTimeout(timerExpired, remainingWait(time));
  }

  function trailingEdge(time) {
    timerId = undefined;

    // Only invoke if we have `lastArgs` which means `func` has been
    // debounced at least once.
    if (trailing && lastArgs) {
      return invokeFunc(time);
    }
    lastArgs = lastThis = undefined;
    return result;
  }

  function cancel() {
    if (timerId !== undefined) {
      clearTimeout(timerId);
    }
    lastInvokeTime = 0;
    lastArgs = lastCallTime = lastThis = timerId = undefined;
  }

  function flush() {
    return timerId === undefined ? result : trailingEdge((0,_now_js__WEBPACK_IMPORTED_MODULE_2__/* ["default"] */ .Z)());
  }

  function debounced() {
    var time = (0,_now_js__WEBPACK_IMPORTED_MODULE_2__/* ["default"] */ .Z)(),
        isInvoking = shouldInvoke(time);

    lastArgs = arguments;
    lastThis = this;
    lastCallTime = time;

    if (isInvoking) {
      if (timerId === undefined) {
        return leadingEdge(lastCallTime);
      }
      if (maxing) {
        // Handle invocations in a tight loop.
        clearTimeout(timerId);
        timerId = setTimeout(timerExpired, wait);
        return invokeFunc(lastCallTime);
      }
    }
    if (timerId === undefined) {
      timerId = setTimeout(timerExpired, wait);
    }
    return result;
  }
  debounced.cancel = cancel;
  debounced.flush = flush;
  return debounced;
}

/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (debounce);


/***/ }),

/***/ 99581:
/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {

"use strict";
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "Z": () => (__WEBPACK_DEFAULT_EXPORT__)
/* harmony export */ });
/**
 * Performs a
 * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)
 * comparison between two values to determine if they are equivalent.
 *
 * @static
 * @memberOf _
 * @since 4.0.0
 * @category Lang
 * @param {*} value The value to compare.
 * @param {*} other The other value to compare.
 * @returns {boolean} Returns `true` if the values are equivalent, else `false`.
 * @example
 *
 * var object = { 'a': 1 };
 * var other = { 'a': 1 };
 *
 * _.eq(object, object);
 * // => true
 *
 * _.eq(object, other);
 * // => false
 *
 * _.eq('a', 'a');
 * // => true
 *
 * _.eq('a', Object('a'));
 * // => false
 *
 * _.eq(NaN, NaN);
 * // => true
 */
function eq(value, other) {
  return value === other || (value !== value && other !== other);
}

/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (eq);


/***/ }),

/***/ 63784:
/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {

"use strict";
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "Z": () => (__WEBPACK_DEFAULT_EXPORT__)
/* harmony export */ });
/* harmony import */ var _baseGet_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(42043);


/**
 * Gets the value at `path` of `object`. If the resolved value is
 * `undefined`, the `defaultValue` is returned in its place.
 *
 * @static
 * @memberOf _
 * @since 3.7.0
 * @category Object
 * @param {Object} object The object to query.
 * @param {Array|string} path The path of the property to get.
 * @param {*} [defaultValue] The value returned for `undefined` resolved values.
 * @returns {*} Returns the resolved value.
 * @example
 *
 * var object = { 'a': [{ 'b': { 'c': 3 } }] };
 *
 * _.get(object, 'a[0].b.c');
 * // => 3
 *
 * _.get(object, ['a', '0', 'b', 'c']);
 * // => 3
 *
 * _.get(object, 'a.b.c', 'default');
 * // => 'default'
 */
function get(object, path, defaultValue) {
  var result = object == null ? undefined : (0,_baseGet_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"] */ .Z)(object, path);
  return result === undefined ? defaultValue : result;
}

/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (get);


/***/ }),

/***/ 94723:
/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {

"use strict";

// EXPORTS
__webpack_require__.d(__webpack_exports__, {
  "Z": () => (/* binding */ lodash_es_hasIn)
});

;// CONCATENATED MODULE: ./node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/_baseHasIn.js
/**
 * The base implementation of `_.hasIn` without support for deep paths.
 *
 * @private
 * @param {Object} [object] The object to query.
 * @param {Array|string} key The key to check.
 * @returns {boolean} Returns `true` if `key` exists, else `false`.
 */
function baseHasIn(object, key) {
  return object != null && key in Object(object);
}

/* harmony default export */ const _baseHasIn = (baseHasIn);

// EXTERNAL MODULE: ./node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/_castPath.js
var _castPath = __webpack_require__(70093);
// EXTERNAL MODULE: ./node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/isArguments.js
var isArguments = __webpack_require__(66161);
// EXTERNAL MODULE: ./node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/isArray.js
var isArray = __webpack_require__(24254);
// EXTERNAL MODULE: ./node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/_isIndex.js
var _isIndex = __webpack_require__(91661);
// EXTERNAL MODULE: ./node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/isLength.js
var isLength = __webpack_require__(55477);
// EXTERNAL MODULE: ./node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/_toKey.js
var _toKey = __webpack_require__(53069);
;// CONCATENATED MODULE: ./node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/_hasPath.js







/**
 * Checks if `path` exists on `object`.
 *
 * @private
 * @param {Object} object The object to query.
 * @param {Array|string} path The path to check.
 * @param {Function} hasFunc The function to check properties.
 * @returns {boolean} Returns `true` if `path` exists, else `false`.
 */
function hasPath(object, path, hasFunc) {
  path = (0,_castPath/* default */.Z)(path, object);

  var index = -1,
      length = path.length,
      result = false;

  while (++index < length) {
    var key = (0,_toKey/* default */.Z)(path[index]);
    if (!(result = object != null && hasFunc(object, key))) {
      break;
    }
    object = object[key];
  }
  if (result || ++index != length) {
    return result;
  }
  length = object == null ? 0 : object.length;
  return !!length && (0,isLength/* default */.Z)(length) && (0,_isIndex/* default */.Z)(key, length) &&
    ((0,isArray/* default */.Z)(object) || (0,isArguments/* default */.Z)(object));
}

/* harmony default export */ const _hasPath = (hasPath);

;// CONCATENATED MODULE: ./node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/hasIn.js



/**
 * Checks if `path` is a direct or inherited property of `object`.
 *
 * @static
 * @memberOf _
 * @since 4.0.0
 * @category Object
 * @param {Object} object The object to query.
 * @param {Array|string} path The path to check.
 * @returns {boolean} Returns `true` if `path` exists, else `false`.
 * @example
 *
 * var object = _.create({ 'a': _.create({ 'b': 2 }) });
 *
 * _.hasIn(object, 'a');
 * // => true
 *
 * _.hasIn(object, 'a.b');
 * // => true
 *
 * _.hasIn(object, ['a', 'b']);
 * // => true
 *
 * _.hasIn(object, 'b');
 * // => false
 */
function hasIn(object, path) {
  return object != null && _hasPath(object, path, _baseHasIn);
}

/* harmony default export */ const lodash_es_hasIn = (hasIn);


/***/ }),

/***/ 91130:
/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {

"use strict";
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "Z": () => (__WEBPACK_DEFAULT_EXPORT__)
/* harmony export */ });
/**
 * This method returns the first argument it receives.
 *
 * @static
 * @since 0.1.0
 * @memberOf _
 * @category Util
 * @param {*} value Any value.
 * @returns {*} Returns `value`.
 * @example
 *
 * var object = { 'a': 1 };
 *
 * console.log(_.identity(object) === object);
 * // => true
 */
function identity(value) {
  return value;
}

/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (identity);


/***/ }),

/***/ 66161:
/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {

"use strict";
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "Z": () => (__WEBPACK_DEFAULT_EXPORT__)
/* harmony export */ });
/* harmony import */ var _baseIsArguments_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(27166);
/* harmony import */ var _isObjectLike_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(95690);



/** Used for built-in method references. */
var objectProto = Object.prototype;

/** Used to check objects for own properties. */
var hasOwnProperty = objectProto.hasOwnProperty;

/** Built-in value references. */
var propertyIsEnumerable = objectProto.propertyIsEnumerable;

/**
 * Checks if `value` is likely an `arguments` object.
 *
 * @static
 * @memberOf _
 * @since 0.1.0
 * @category Lang
 * @param {*} value The value to check.
 * @returns {boolean} Returns `true` if `value` is an `arguments` object,
 *  else `false`.
 * @example
 *
 * _.isArguments(function() { return arguments; }());
 * // => true
 *
 * _.isArguments([1, 2, 3]);
 * // => false
 */
var isArguments = (0,_baseIsArguments_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"] */ .Z)(function() { return arguments; }()) ? _baseIsArguments_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"] */ .Z : function(value) {
  return (0,_isObjectLike_js__WEBPACK_IMPORTED_MODULE_1__/* ["default"] */ .Z)(value) && hasOwnProperty.call(value, 'callee') &&
    !propertyIsEnumerable.call(value, 'callee');
};

/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (isArguments);


/***/ }),

/***/ 24254:
/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {

"use strict";
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "Z": () => (__WEBPACK_DEFAULT_EXPORT__)
/* harmony export */ });
/**
 * Checks if `value` is classified as an `Array` object.
 *
 * @static
 * @memberOf _
 * @since 0.1.0
 * @category Lang
 * @param {*} value The value to check.
 * @returns {boolean} Returns `true` if `value` is an array, else `false`.
 * @example
 *
 * _.isArray([1, 2, 3]);
 * // => true
 *
 * _.isArray(document.body.children);
 * // => false
 *
 * _.isArray('abc');
 * // => false
 *
 * _.isArray(_.noop);
 * // => false
 */
var isArray = Array.isArray;

/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (isArray);


/***/ }),

/***/ 2762:
/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {

"use strict";
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "Z": () => (__WEBPACK_DEFAULT_EXPORT__)
/* harmony export */ });
/* harmony import */ var _isFunction_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(25827);
/* harmony import */ var _isLength_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(55477);



/**
 * Checks if `value` is array-like. A value is considered array-like if it's
 * not a function and has a `value.length` that's an integer greater than or
 * equal to `0` and less than or equal to `Number.MAX_SAFE_INTEGER`.
 *
 * @static
 * @memberOf _
 * @since 4.0.0
 * @category Lang
 * @param {*} value The value to check.
 * @returns {boolean} Returns `true` if `value` is array-like, else `false`.
 * @example
 *
 * _.isArrayLike([1, 2, 3]);
 * // => true
 *
 * _.isArrayLike(document.body.children);
 * // => true
 *
 * _.isArrayLike('abc');
 * // => true
 *
 * _.isArrayLike(_.noop);
 * // => false
 */
function isArrayLike(value) {
  return value != null && (0,_isLength_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"] */ .Z)(value.length) && !(0,_isFunction_js__WEBPACK_IMPORTED_MODULE_1__/* ["default"] */ .Z)(value);
}

/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (isArrayLike);


/***/ }),

/***/ 5950:
/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {

"use strict";
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "Z": () => (__WEBPACK_DEFAULT_EXPORT__)
/* harmony export */ });
/* harmony import */ var _root_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(5665);
/* harmony import */ var _stubFalse_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(69700);



/** Detect free variable `exports`. */
var freeExports = typeof exports == 'object' && exports && !exports.nodeType && exports;

/** Detect free variable `module`. */
var freeModule = freeExports && typeof module == 'object' && module && !module.nodeType && module;

/** Detect the popular CommonJS extension `module.exports`. */
var moduleExports = freeModule && freeModule.exports === freeExports;

/** Built-in value references. */
var Buffer = moduleExports ? _root_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"].Buffer */ .Z.Buffer : undefined;

/* Built-in method references for those with the same name as other `lodash` methods. */
var nativeIsBuffer = Buffer ? Buffer.isBuffer : undefined;

/**
 * Checks if `value` is a buffer.
 *
 * @static
 * @memberOf _
 * @since 4.3.0
 * @category Lang
 * @param {*} value The value to check.
 * @returns {boolean} Returns `true` if `value` is a buffer, else `false`.
 * @example
 *
 * _.isBuffer(new Buffer(2));
 * // => true
 *
 * _.isBuffer(new Uint8Array(2));
 * // => false
 */
var isBuffer = nativeIsBuffer || _stubFalse_js__WEBPACK_IMPORTED_MODULE_1__/* ["default"] */ .Z;

/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (isBuffer);


/***/ }),

/***/ 25827:
/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {

"use strict";
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "Z": () => (__WEBPACK_DEFAULT_EXPORT__)
/* harmony export */ });
/* harmony import */ var _baseGetTag_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(85086);
/* harmony import */ var _isObject_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(62893);



/** `Object#toString` result references. */
var asyncTag = '[object AsyncFunction]',
    funcTag = '[object Function]',
    genTag = '[object GeneratorFunction]',
    proxyTag = '[object Proxy]';

/**
 * Checks if `value` is classified as a `Function` object.
 *
 * @static
 * @memberOf _
 * @since 0.1.0
 * @category Lang
 * @param {*} value The value to check.
 * @returns {boolean} Returns `true` if `value` is a function, else `false`.
 * @example
 *
 * _.isFunction(_);
 * // => true
 *
 * _.isFunction(/abc/);
 * // => false
 */
function isFunction(value) {
  if (!(0,_isObject_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"] */ .Z)(value)) {
    return false;
  }
  // The use of `Object#toString` avoids issues with the `typeof` operator
  // in Safari 9 which returns 'object' for typed arrays and other constructors.
  var tag = (0,_baseGetTag_js__WEBPACK_IMPORTED_MODULE_1__/* ["default"] */ .Z)(value);
  return tag == funcTag || tag == genTag || tag == asyncTag || tag == proxyTag;
}

/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (isFunction);


/***/ }),

/***/ 55477:
/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {

"use strict";
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "Z": () => (__WEBPACK_DEFAULT_EXPORT__)
/* harmony export */ });
/** Used as references for various `Number` constants. */
var MAX_SAFE_INTEGER = 9007199254740991;

/**
 * Checks if `value` is a valid array-like length.
 *
 * **Note:** This method is loosely based on
 * [`ToLength`](http://ecma-international.org/ecma-262/7.0/#sec-tolength).
 *
 * @static
 * @memberOf _
 * @since 4.0.0
 * @category Lang
 * @param {*} value The value to check.
 * @returns {boolean} Returns `true` if `value` is a valid length, else `false`.
 * @example
 *
 * _.isLength(3);
 * // => true
 *
 * _.isLength(Number.MIN_VALUE);
 * // => false
 *
 * _.isLength(Infinity);
 * // => false
 *
 * _.isLength('3');
 * // => false
 */
function isLength(value) {
  return typeof value == 'number' &&
    value > -1 && value % 1 == 0 && value <= MAX_SAFE_INTEGER;
}

/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (isLength);


/***/ }),

/***/ 62893:
/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {

"use strict";
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "Z": () => (__WEBPACK_DEFAULT_EXPORT__)
/* harmony export */ });
/**
 * Checks if `value` is the
 * [language type](http://www.ecma-international.org/ecma-262/7.0/#sec-ecmascript-language-types)
 * of `Object`. (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`)
 *
 * @static
 * @memberOf _
 * @since 0.1.0
 * @category Lang
 * @param {*} value The value to check.
 * @returns {boolean} Returns `true` if `value` is an object, else `false`.
 * @example
 *
 * _.isObject({});
 * // => true
 *
 * _.isObject([1, 2, 3]);
 * // => true
 *
 * _.isObject(_.noop);
 * // => true
 *
 * _.isObject(null);
 * // => false
 */
function isObject(value) {
  var type = typeof value;
  return value != null && (type == 'object' || type == 'function');
}

/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (isObject);


/***/ }),

/***/ 95690:
/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {

"use strict";
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "Z": () => (__WEBPACK_DEFAULT_EXPORT__)
/* harmony export */ });
/**
 * Checks if `value` is object-like. A value is object-like if it's not `null`
 * and has a `typeof` result of "object".
 *
 * @static
 * @memberOf _
 * @since 4.0.0
 * @category Lang
 * @param {*} value The value to check.
 * @returns {boolean} Returns `true` if `value` is object-like, else `false`.
 * @example
 *
 * _.isObjectLike({});
 * // => true
 *
 * _.isObjectLike([1, 2, 3]);
 * // => true
 *
 * _.isObjectLike(_.noop);
 * // => false
 *
 * _.isObjectLike(null);
 * // => false
 */
function isObjectLike(value) {
  return value != null && typeof value == 'object';
}

/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (isObjectLike);


/***/ }),

/***/ 12281:
/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {

"use strict";
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "Z": () => (__WEBPACK_DEFAULT_EXPORT__)
/* harmony export */ });
/* harmony import */ var _baseGetTag_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(85086);
/* harmony import */ var _isObjectLike_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(95690);



/** `Object#toString` result references. */
var symbolTag = '[object Symbol]';

/**
 * Checks if `value` is classified as a `Symbol` primitive or object.
 *
 * @static
 * @memberOf _
 * @since 4.0.0
 * @category Lang
 * @param {*} value The value to check.
 * @returns {boolean} Returns `true` if `value` is a symbol, else `false`.
 * @example
 *
 * _.isSymbol(Symbol.iterator);
 * // => true
 *
 * _.isSymbol('abc');
 * // => false
 */
function isSymbol(value) {
  return typeof value == 'symbol' ||
    ((0,_isObjectLike_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"] */ .Z)(value) && (0,_baseGetTag_js__WEBPACK_IMPORTED_MODULE_1__/* ["default"] */ .Z)(value) == symbolTag);
}

/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (isSymbol);


/***/ }),

/***/ 90284:
/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {

"use strict";
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "Z": () => (__WEBPACK_DEFAULT_EXPORT__)
/* harmony export */ });
/* harmony import */ var _baseIsTypedArray_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(56896);
/* harmony import */ var _baseUnary_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(31862);
/* harmony import */ var _nodeUtil_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(76773);




/* Node.js helper references. */
var nodeIsTypedArray = _nodeUtil_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"] */ .Z && _nodeUtil_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"].isTypedArray */ .Z.isTypedArray;

/**
 * Checks if `value` is classified as a typed array.
 *
 * @static
 * @memberOf _
 * @since 3.0.0
 * @category Lang
 * @param {*} value The value to check.
 * @returns {boolean} Returns `true` if `value` is a typed array, else `false`.
 * @example
 *
 * _.isTypedArray(new Uint8Array);
 * // => true
 *
 * _.isTypedArray([]);
 * // => false
 */
var isTypedArray = nodeIsTypedArray ? (0,_baseUnary_js__WEBPACK_IMPORTED_MODULE_1__/* ["default"] */ .Z)(nodeIsTypedArray) : _baseIsTypedArray_js__WEBPACK_IMPORTED_MODULE_2__/* ["default"] */ .Z;

/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (isTypedArray);


/***/ }),

/***/ 12395:
/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {

"use strict";

// EXPORTS
__webpack_require__.d(__webpack_exports__, {
  "Z": () => (/* binding */ lodash_es_keys)
});

// EXTERNAL MODULE: ./node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/_arrayLikeKeys.js + 1 modules
var _arrayLikeKeys = __webpack_require__(68180);
// EXTERNAL MODULE: ./node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/_isPrototype.js
var _isPrototype = __webpack_require__(41040);
// EXTERNAL MODULE: ./node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/_overArg.js
var _overArg = __webpack_require__(6438);
;// CONCATENATED MODULE: ./node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/_nativeKeys.js


/* Built-in method references for those with the same name as other `lodash` methods. */
var nativeKeys = (0,_overArg/* default */.Z)(Object.keys, Object);

/* harmony default export */ const _nativeKeys = (nativeKeys);

;// CONCATENATED MODULE: ./node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/_baseKeys.js



/** Used for built-in method references. */
var objectProto = Object.prototype;

/** Used to check objects for own properties. */
var _baseKeys_hasOwnProperty = objectProto.hasOwnProperty;

/**
 * The base implementation of `_.keys` which doesn't treat sparse arrays as dense.
 *
 * @private
 * @param {Object} object The object to query.
 * @returns {Array} Returns the array of property names.
 */
function baseKeys(object) {
  if (!(0,_isPrototype/* default */.Z)(object)) {
    return _nativeKeys(object);
  }
  var result = [];
  for (var key in Object(object)) {
    if (_baseKeys_hasOwnProperty.call(object, key) && key != 'constructor') {
      result.push(key);
    }
  }
  return result;
}

/* harmony default export */ const _baseKeys = (baseKeys);

// EXTERNAL MODULE: ./node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/isArrayLike.js
var isArrayLike = __webpack_require__(2762);
;// CONCATENATED MODULE: ./node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/keys.js




/**
 * Creates an array of the own enumerable property names of `object`.
 *
 * **Note:** Non-object values are coerced to objects. See the
 * [ES spec](http://ecma-international.org/ecma-262/7.0/#sec-object.keys)
 * for more details.
 *
 * @static
 * @since 0.1.0
 * @memberOf _
 * @category Object
 * @param {Object} object The object to query.
 * @returns {Array} Returns the array of property names.
 * @example
 *
 * function Foo() {
 *   this.a = 1;
 *   this.b = 2;
 * }
 *
 * Foo.prototype.c = 3;
 *
 * _.keys(new Foo);
 * // => ['a', 'b'] (iteration order is not guaranteed)
 *
 * _.keys('hi');
 * // => ['0', '1']
 */
function keys(object) {
  return (0,isArrayLike/* default */.Z)(object) ? (0,_arrayLikeKeys/* default */.Z)(object) : _baseKeys(object);
}

/* harmony default export */ const lodash_es_keys = (keys);


/***/ }),

/***/ 82287:
/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {

"use strict";
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "Z": () => (__WEBPACK_DEFAULT_EXPORT__)
/* harmony export */ });
/* harmony import */ var _MapCache_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(14356);


/** Error message constants. */
var FUNC_ERROR_TEXT = 'Expected a function';

/**
 * Creates a function that memoizes the result of `func`. If `resolver` is
 * provided, it determines the cache key for storing the result based on the
 * arguments provided to the memoized function. By default, the first argument
 * provided to the memoized function is used as the map cache key. The `func`
 * is invoked with the `this` binding of the memoized function.
 *
 * **Note:** The cache is exposed as the `cache` property on the memoized
 * function. Its creation may be customized by replacing the `_.memoize.Cache`
 * constructor with one whose instances implement the
 * [`Map`](http://ecma-international.org/ecma-262/7.0/#sec-properties-of-the-map-prototype-object)
 * method interface of `clear`, `delete`, `get`, `has`, and `set`.
 *
 * @static
 * @memberOf _
 * @since 0.1.0
 * @category Function
 * @param {Function} func The function to have its output memoized.
 * @param {Function} [resolver] The function to resolve the cache key.
 * @returns {Function} Returns the new memoized function.
 * @example
 *
 * var object = { 'a': 1, 'b': 2 };
 * var other = { 'c': 3, 'd': 4 };
 *
 * var values = _.memoize(_.values);
 * values(object);
 * // => [1, 2]
 *
 * values(other);
 * // => [3, 4]
 *
 * object.a = 2;
 * values(object);
 * // => [1, 2]
 *
 * // Modify the result cache.
 * values.cache.set(object, ['a', 'b']);
 * values(object);
 * // => ['a', 'b']
 *
 * // Replace `_.memoize.Cache`.
 * _.memoize.Cache = WeakMap;
 */
function memoize(func, resolver) {
  if (typeof func != 'function' || (resolver != null && typeof resolver != 'function')) {
    throw new TypeError(FUNC_ERROR_TEXT);
  }
  var memoized = function() {
    var args = arguments,
        key = resolver ? resolver.apply(this, args) : args[0],
        cache = memoized.cache;

    if (cache.has(key)) {
      return cache.get(key);
    }
    var result = func.apply(this, args);
    memoized.cache = cache.set(key, result) || cache;
    return result;
  };
  memoized.cache = new (memoize.Cache || _MapCache_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"] */ .Z);
  return memoized;
}

// Expose `MapCache`.
memoize.Cache = _MapCache_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"] */ .Z;

/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (memoize);


/***/ }),

/***/ 17937:
/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {

"use strict";
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "Z": () => (__WEBPACK_DEFAULT_EXPORT__)
/* harmony export */ });
/* harmony import */ var _root_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(5665);


/**
 * Gets the timestamp of the number of milliseconds that have elapsed since
 * the Unix epoch (1 January 1970 00:00:00 UTC).
 *
 * @static
 * @memberOf _
 * @since 2.4.0
 * @category Date
 * @returns {number} Returns the timestamp.
 * @example
 *
 * _.defer(function(stamp) {
 *   console.log(_.now() - stamp);
 * }, _.now());
 * // => Logs the number of milliseconds it took for the deferred invocation.
 */
var now = function() {
  return _root_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"].Date.now */ .Z.Date.now();
};

/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (now);


/***/ }),

/***/ 69700:
/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {

"use strict";
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "Z": () => (__WEBPACK_DEFAULT_EXPORT__)
/* harmony export */ });
/**
 * This method returns `false`.
 *
 * @static
 * @memberOf _
 * @since 4.13.0
 * @category Util
 * @returns {boolean} Returns `false`.
 * @example
 *
 * _.times(2, _.stubFalse);
 * // => [false, false]
 */
function stubFalse() {
  return false;
}

/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (stubFalse);


/***/ }),

/***/ 97400:
/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {

"use strict";
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "Z": () => (__WEBPACK_DEFAULT_EXPORT__)
/* harmony export */ });
/* harmony import */ var _baseTrim_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(10451);
/* harmony import */ var _isObject_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(62893);
/* harmony import */ var _isSymbol_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(12281);




/** Used as references for various `Number` constants. */
var NAN = 0 / 0;

/** Used to detect bad signed hexadecimal string values. */
var reIsBadHex = /^[-+]0x[0-9a-f]+$/i;

/** Used to detect binary string values. */
var reIsBinary = /^0b[01]+$/i;

/** Used to detect octal string values. */
var reIsOctal = /^0o[0-7]+$/i;

/** Built-in method references without a dependency on `root`. */
var freeParseInt = parseInt;

/**
 * Converts `value` to a number.
 *
 * @static
 * @memberOf _
 * @since 4.0.0
 * @category Lang
 * @param {*} value The value to process.
 * @returns {number} Returns the number.
 * @example
 *
 * _.toNumber(3.2);
 * // => 3.2
 *
 * _.toNumber(Number.MIN_VALUE);
 * // => 5e-324
 *
 * _.toNumber(Infinity);
 * // => Infinity
 *
 * _.toNumber('3.2');
 * // => 3.2
 */
function toNumber(value) {
  if (typeof value == 'number') {
    return value;
  }
  if ((0,_isSymbol_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"] */ .Z)(value)) {
    return NAN;
  }
  if ((0,_isObject_js__WEBPACK_IMPORTED_MODULE_1__/* ["default"] */ .Z)(value)) {
    var other = typeof value.valueOf == 'function' ? value.valueOf() : value;
    value = (0,_isObject_js__WEBPACK_IMPORTED_MODULE_1__/* ["default"] */ .Z)(other) ? (other + '') : other;
  }
  if (typeof value != 'string') {
    return value === 0 ? value : +value;
  }
  value = (0,_baseTrim_js__WEBPACK_IMPORTED_MODULE_2__/* ["default"] */ .Z)(value);
  var isBinary = reIsBinary.test(value);
  return (isBinary || reIsOctal.test(value))
    ? freeParseInt(value.slice(2), isBinary ? 2 : 8)
    : (reIsBadHex.test(value) ? NAN : +value);
}

/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (toNumber);


/***/ }),

/***/ 18316:
/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {

"use strict";
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "Z": () => (__WEBPACK_DEFAULT_EXPORT__)
/* harmony export */ });
/* harmony import */ var _baseToString_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(43123);


/**
 * Converts `value` to a string. An empty string is returned for `null`
 * and `undefined` values. The sign of `-0` is preserved.
 *
 * @static
 * @memberOf _
 * @since 4.0.0
 * @category Lang
 * @param {*} value The value to convert.
 * @returns {string} Returns the converted string.
 * @example
 *
 * _.toString(null);
 * // => ''
 *
 * _.toString(-0);
 * // => '-0'
 *
 * _.toString([1, 2, 3]);
 * // => '1,2,3'
 */
function toString(value) {
  return value == null ? '' : (0,_baseToString_js__WEBPACK_IMPORTED_MODULE_0__/* ["default"] */ .Z)(value);
}

/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (toString);


/***/ })

},
/******/ __webpack_require__ => { // webpackRuntimeModules
/******/ var __webpack_exec__ = (moduleId) => (__webpack_require__(__webpack_require__.s = moduleId))
/******/ __webpack_require__.O(0, [870,645,974], () => (__webpack_exec__(28416)));
/******/ var __webpack_exports__ = __webpack_require__.O();
/******/ }
]);