"use strict"; (self["webpackChunkbrowser_extension"] = self["webpackChunkbrowser_extension"] || []).push([["272"], { 7596(__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) { __webpack_require__.d(__webpack_exports__, { H: () => (AbpSnippetInjectionBodyCommon) }); /* * AGTree v4.2.1 (build date: Wed, 12 Aug 2026 01:31:02 GMT) * (c) 2026 Adguard Software Ltd. * Released under the MIT license * https://github.com/AdguardTeam/tsurlfilter/tree/master/packages/agtree#readme */ /** * Common class for the ABP snippet injection body. * This class contains shared constants and utilities for handling ABP snippet injection bodies. */ class AbpSnippetInjectionBodyCommon { /** * Error messages used by the parser and generator. */ static ERROR_MESSAGES = { /** * Error message indicating that an ABP snippet call is empty. */ EMPTY_SCRIPTLET_CALL: 'Empty ABP snippet call', }; } }, 76466(__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) { __webpack_require__.d(__webpack_exports__, { l: () => (isUboResponseHeaderRemovalRuleBody) }); /* import */ var _utils_constants_js__rspack_import_0 = __webpack_require__(53097); /* * AGTree v4.2.1 (build date: Wed, 12 Aug 2026 01:31:02 GMT) * (c) 2026 Adguard Software Ltd. * Released under the MIT license * https://github.com/AdguardTeam/tsurlfilter/tree/master/packages/agtree#readme */ /** * Checks whether the given HTML filtering rule body represents a uBlock-style response header removal rule. * * @param node Potential response header removal rule node. * * @returns `true` if the node is a response header removal rule, `false` otherwise. * * @note This method checks `HtmlFilteringRuleBody` because, response header * removal rule syntax is same as uBlock-style HTML filtering rule syntax. */ function isUboResponseHeaderRemovalRuleBody(node) { const { selectorList } = node; // Must have exactly one complex selector if (selectorList.children.length !== 1) { return false; } const complexSelector = selectorList.children[0]; // Must have exactly one simple selector if (complexSelector.children.length !== 1) { return false; } const simpleSelector = complexSelector.children[0]; return ( // Should be a pseudo-class selector simpleSelector.type === 'PseudoClassSelector' // Pseudo-class selector name should match `UBO_RESPONSEHEADER_FN` && simpleSelector.name.value === _utils_constants_js__rspack_import_0/* .UBO_RESPONSEHEADER_FN */.Bt // Should have argument && simpleSelector.argument !== undefined); } }, 15862(__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) { __webpack_require__.d(__webpack_exports__, { S: () => (UboPseudoName) }); /* * AGTree v4.2.1 (build date: Wed, 12 Aug 2026 01:31:02 GMT) * (c) 2026 Adguard Software Ltd. * Released under the MIT license * https://github.com/AdguardTeam/tsurlfilter/tree/master/packages/agtree#readme */ /** * Known uBO-specific pseudo-class names. */ const UboPseudoName = { MatchesMedia: 'matches-media', MatchesPath: 'matches-path', Remove: 'remove', Style: 'style', }; }, 21565(__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) { // EXPORTS __webpack_require__.d(__webpack_exports__, { E: () => (/* binding */ CompatibilityTableBase) }); // EXTERNAL MODULE: ./node_modules/.pnpm/@adguard+agtree@4.2.1/node_modules/@adguard/agtree/dist/utils/adblockers.js var adblockers = __webpack_require__(22380); // EXTERNAL MODULE: ./node_modules/.pnpm/@adguard+agtree@4.2.1/node_modules/@adguard/agtree/dist/utils/type-guards.js var type_guards = __webpack_require__(64505); // EXTERNAL MODULE: ./node_modules/.pnpm/@adguard+agtree@4.2.1/node_modules/@adguard/agtree/dist/compatibility-tables/platforms.js var platforms = __webpack_require__(9257); ;// CONCATENATED MODULE: ./node_modules/.pnpm/@adguard+agtree@4.2.1/node_modules/@adguard/agtree/dist/compatibility-tables/utils/platform-helpers.js /* * AGTree v4.2.1 (build date: Wed, 12 Aug 2026 01:31:02 GMT) * (c) 2026 Adguard Software Ltd. * Released under the MIT license * https://github.com/AdguardTeam/tsurlfilter/tree/master/packages/agtree#readme */ /* eslint-disable no-bitwise */ /** * @file Provides platform mapping and helper functions. */ /** * Map of specific platforms string names to their corresponding enum values. */ const SPECIFIC_PLATFORM_MAP = new Map([ ['adg_os_windows', platforms/* .SpecificPlatform.AdgOsWindows */.c.AdgOsWindows], ['adg_os_mac', platforms/* .SpecificPlatform.AdgOsMac */.c.AdgOsMac], ['adg_os_android', platforms/* .SpecificPlatform.AdgOsAndroid */.c.AdgOsAndroid], ['adg_ext_chrome', platforms/* .SpecificPlatform.AdgExtChrome */.c.AdgExtChrome], ['adg_ext_opera', platforms/* .SpecificPlatform.AdgExtOpera */.c.AdgExtOpera], ['adg_ext_edge', platforms/* .SpecificPlatform.AdgExtEdge */.c.AdgExtEdge], ['adg_ext_firefox', platforms/* .SpecificPlatform.AdgExtFirefox */.c.AdgExtFirefox], ['adg_cb_android', platforms/* .SpecificPlatform.AdgCbAndroid */.c.AdgCbAndroid], ['adg_cb_ios', platforms/* .SpecificPlatform.AdgCbIos */.c.AdgCbIos], ['adg_cb_safari', platforms/* .SpecificPlatform.AdgCbSafari */.c.AdgCbSafari], ['ubo_ext_chrome', platforms/* .SpecificPlatform.UboExtChrome */.c.UboExtChrome], ['ubo_ext_opera', platforms/* .SpecificPlatform.UboExtOpera */.c.UboExtOpera], ['ubo_ext_edge', platforms/* .SpecificPlatform.UboExtEdge */.c.UboExtEdge], ['ubo_ext_firefox', platforms/* .SpecificPlatform.UboExtFirefox */.c.UboExtFirefox], ['abp_ext_chrome', platforms/* .SpecificPlatform.AbpExtChrome */.c.AbpExtChrome], ['abp_ext_opera', platforms/* .SpecificPlatform.AbpExtOpera */.c.AbpExtOpera], ['abp_ext_edge', platforms/* .SpecificPlatform.AbpExtEdge */.c.AbpExtEdge], ['abp_ext_firefox', platforms/* .SpecificPlatform.AbpExtFirefox */.c.AbpExtFirefox], ]); /** * Map of specific platforms enum values to their corresponding string names. * * @note Reverse of {@link SPECIFIC_PLATFORM_MAP}. */ const SPECIFIC_PLATFORM_MAP_REVERSE = new Map([...SPECIFIC_PLATFORM_MAP].map(([key, value]) => [value, key])); /** * Map of generic platforms string names to their corresponding enum values. */ const GENERIC_PLATFORM_MAP = new Map([ ['adg_os_any', platforms/* .GenericPlatform.AdgOsAny */.p.AdgOsAny], ['adg_safari_any', platforms/* .GenericPlatform.AdgSafariAny */.p.AdgSafariAny], ['adg_ext_chromium', platforms/* .GenericPlatform.AdgExtChromium */.p.AdgExtChromium], ['adg_ext_any', platforms/* .GenericPlatform.AdgExtAny */.p.AdgExtAny], ['adg_any', platforms/* .GenericPlatform.AdgAny */.p.AdgAny], ['ubo_ext_chromium', platforms/* .GenericPlatform.UboExtChromium */.p.UboExtChromium], ['ubo_ext_any', platforms/* .GenericPlatform.UboExtAny */.p.UboExtAny], ['ubo_any', platforms/* .GenericPlatform.UboAny */.p.UboAny], ['abp_ext_chromium', platforms/* .GenericPlatform.AbpExtChromium */.p.AbpExtChromium], ['abp_ext_any', platforms/* .GenericPlatform.AbpExtAny */.p.AbpExtAny], ['abp_any', platforms/* .GenericPlatform.AbpAny */.p.AbpAny], ['any', platforms/* .GenericPlatform.Any */.p.Any], ]); /** * Map of products to their platform name prefixes. * Used for filtering generic platforms by product. */ const PRODUCT_PREFIX_MAP = { [adblockers/* .AdblockProduct.Adg */.C6.Adg]: 'Adg', [adblockers/* .AdblockProduct.Ubo */.C6.Ubo]: 'Ubo', [adblockers/* .AdblockProduct.Abp */.C6.Abp]: 'Abp', }; const SPECIFIC_PLATFORM_HUMAN_READABLE_NAME_MAP = new Map([ [platforms/* .SpecificPlatform.AdgOsWindows */.c.AdgOsWindows, 'AdGuard App for Windows'], [platforms/* .SpecificPlatform.AdgOsMac */.c.AdgOsMac, 'AdGuard App for Mac'], [platforms/* .SpecificPlatform.AdgOsAndroid */.c.AdgOsAndroid, 'AdGuard App for Android'], [platforms/* .SpecificPlatform.AdgExtChrome */.c.AdgExtChrome, 'AdGuard Browser Extension for Chrome'], [platforms/* .SpecificPlatform.AdgExtOpera */.c.AdgExtOpera, 'AdGuard Browser Extension for Opera'], [platforms/* .SpecificPlatform.AdgExtEdge */.c.AdgExtEdge, 'AdGuard Browser Extension for Edge'], [platforms/* .SpecificPlatform.AdgExtFirefox */.c.AdgExtFirefox, 'AdGuard Browser Extension for Firefox'], [platforms/* .SpecificPlatform.AdgCbAndroid */.c.AdgCbAndroid, 'AdGuard Content Blocker for Android'], [platforms/* .SpecificPlatform.AdgCbIos */.c.AdgCbIos, 'AdGuard Content Blocker for iOS'], [platforms/* .SpecificPlatform.AdgCbSafari */.c.AdgCbSafari, 'AdGuard Content Blocker for Safari'], [platforms/* .SpecificPlatform.UboExtChrome */.c.UboExtChrome, 'uBlock Origin Browser Extension for Chrome'], [platforms/* .SpecificPlatform.UboExtOpera */.c.UboExtOpera, 'uBlock Origin Browser Extension for Opera'], [platforms/* .SpecificPlatform.UboExtEdge */.c.UboExtEdge, 'uBlock Origin Browser Extension for Edge'], [platforms/* .SpecificPlatform.UboExtFirefox */.c.UboExtFirefox, 'uBlock Origin Browser Extension for Firefox'], [platforms/* .SpecificPlatform.AbpExtChrome */.c.AbpExtChrome, 'AdBlock / Adblock Plus Browser Extension for Chrome'], [platforms/* .SpecificPlatform.AbpExtOpera */.c.AbpExtOpera, 'AdBlock / Adblock Plus Browser Extension for Opera'], [platforms/* .SpecificPlatform.AbpExtEdge */.c.AbpExtEdge, 'AdBlock / Adblock Plus Browser Extension for Edge'], [platforms/* .SpecificPlatform.AbpExtFirefox */.c.AbpExtFirefox, 'AdBlock / Adblock Plus Browser Extension for Firefox'], ]); const GENERIC_PLATFORM_HUMAN_READABLE_NAME_MAP = new Map([ [platforms/* .GenericPlatform.AdgOsAny */.p.AdgOsAny, 'Any System-level AdGuard App'], [platforms/* .GenericPlatform.AdgSafariAny */.p.AdgSafariAny, 'Any AdGuard Content Blocker for Safari'], [platforms/* .GenericPlatform.AdgExtChromium */.p.AdgExtChromium, 'Any AdGuard Browser Extension for Chromium'], [platforms/* .GenericPlatform.AdgExtAny */.p.AdgExtAny, 'Any AdGuard Browser Extension'], [platforms/* .GenericPlatform.AdgAny */.p.AdgAny, 'Any AdGuard product'], [platforms/* .GenericPlatform.UboExtChromium */.p.UboExtChromium, 'Any uBlock Origin Browser Extension for Chromium'], [platforms/* .GenericPlatform.UboExtAny */.p.UboExtAny, 'Any uBlock Origin Browser Extension'], [platforms/* .GenericPlatform.UboAny */.p.UboAny, 'Any uBlock Origin product'], [platforms/* .GenericPlatform.AbpExtChromium */.p.AbpExtChromium, 'Any AdBlock / Adblock Plus Browser Extension for Chromium'], [platforms/* .GenericPlatform.AbpExtAny */.p.AbpExtAny, 'Any AdBlock / Adblock Plus Browser Extension'], [platforms/* .GenericPlatform.AbpAny */.p.AbpAny, 'Any AdBlock / Adblock Plus product'], [platforms/* .GenericPlatform.Any */.p.Any, 'Any product'], ]); /** * Generic platforms for each product, ordered from most specific to least specific. * Computed lazily on first access. */ let PRODUCT_GENERIC_PLATFORMS = null; /** * Map of products to their specific platforms. * Cached after first call to avoid recomputing. */ let PRODUCT_SPECIFIC_PLATFORMS = null; /** * Initializes and returns the product generic platforms map. * Filters all generic platforms by product prefix and sorts by specificity (fewer bits = more specific). * * @returns Map of products to their generic platforms, ordered from most to least specific. */ const getProductGenericPlatforms = () => { if (PRODUCT_GENERIC_PLATFORMS !== null) { return PRODUCT_GENERIC_PLATFORMS; } const result = { [AdblockProduct.Adg]: [], [AdblockProduct.Ubo]: [], [AdblockProduct.Abp]: [], }; // Iterate over all generic platforms and group by product prefix const genericPlatformEntries = Object.entries(GenericPlatform); for (const [name, platform] of genericPlatformEntries) { // Check which product this platform belongs to for (const [product, prefix] of Object.entries(PRODUCT_PREFIX_MAP)) { if (name.startsWith(prefix)) { result[product].push(platform); break; } } } // Sort each product's platforms by specificity (fewer bits set = more specific) for (const product of Object.keys(result)) { result[product].sort((a, b) => { const bitsA = getBitCount(a); const bitsB = getBitCount(b); return bitsA - bitsB; // Ascending: fewer bits first (more specific) }); } // Cache the result as readonly PRODUCT_GENERIC_PLATFORMS = result; return PRODUCT_GENERIC_PLATFORMS; }; /** * Check if the platform is a generic platform (or a combination of platforms). * * @param platform Platform to check. * * @returns True if the platform is a generic platform or combined platforms, false if it's a specific platform. */ const isGenericPlatform = (platform) => { // if more than one bit is set, it's a generic platform or combined platforms // Cast to number for bitwise operations const num = platform; return !!(num & (num - 1)); }; /** * Check if the platform has multiple products specified. * Multiple products means at least 2 of: AdgAny, AbpAny, UboAny. * * @param platform Platform to check. * * @returns True if at least 2 products are specified, false otherwise. */ const hasPlatformMultipleProducts = (platform) => { const hasAdg = !!(platform & GenericPlatform.AdgAny); const hasAbp = !!(platform & GenericPlatform.AbpAny); const hasUbo = !!(platform & GenericPlatform.UboAny); return ((hasAdg && hasAbp) || (hasAdg && hasUbo) || (hasAbp && hasUbo)); }; /** * Converts a platform to its corresponding adblock products. * * Note: This conversion is less specific than the platform itself, as it only returns * which products (AdGuard/uBlock/Abp) are present, dropping specific platform information * (e.g., Windows vs Chrome extension). * * @param platform Platform to convert. * * @returns Array of AdblockProduct values: * - Empty array `[]` if platform is 0 or no products are found * - Array of specific products based on which products are present * (e.g., `['AdGuard', 'UblockOrigin']` if both AdGuard and uBlock Origin are specified) * - `['AdGuard', 'UblockOrigin', 'AdblockPlus']` for GenericPlatform.Any. */ const platformToAdblockProduct = (platform) => { const products = []; if (platform & GenericPlatform.AdgAny) { products.push(AdblockProduct.Adg); } if (platform & GenericPlatform.UboAny) { products.push(AdblockProduct.Ubo); } if (platform & GenericPlatform.AbpAny) { products.push(AdblockProduct.Abp); } return products; }; /** * Optimizes platform representation by combining specific platforms into generic ones. * Returns the minimal set of platforms needed to represent the input. * * @param extractedPlatforms Platform bits for a single product. * @param productGenericPlatforms Array of generic platforms for this product, ordered by specificity. * * @returns Optimized array of platforms. */ const optimizePlatformRepresentation = (extractedPlatforms, productGenericPlatforms) => { if (extractedPlatforms === 0) { return []; } // Check if the input exactly matches any single generic platform (already optimal) for (const genericPlatform of productGenericPlatforms) { if (extractedPlatforms === genericPlatform) { return [genericPlatform]; } } const result = []; let remainingBits = extractedPlatforms; // Try to match generic platforms from most specific to least specific for (const genericPlatform of productGenericPlatforms) { const genericBits = genericPlatform; // Check if all bits of this generic platform are present in remaining bits if ((remainingBits & genericBits) === genericBits) { result.push(genericPlatform); // Remove the matched bits from remaining remainingBits &= ~genericBits; // If no bits remain, we're done if (remainingBits === 0) { break; } } } // If there are remaining bits, we need to add them as specific platforms // This shouldn't normally happen if our generic platforms cover all combinations, // but we handle it for safety if (remainingBits !== 0) { result.push(remainingBits); } return result; }; /** * Splits a platform by products, returning a record mapping each product to its platforms. * This is useful for iterating over each product separately when validating or processing. * * The function optimizes the platform representation by combining specific platforms * into generic ones when possible, returning the minimal set needed. * * @param platform Platform to split (can be single or multi-product). * * @returns Record mapping products to optimized platform arrays: * - Empty object `{}` if platform is 0 or no products are found * - Object with single product key for single-product platforms * - Object with multiple product keys for multi-product platforms * - Each array contains the minimal representation using generic platforms where possible. * * @example * ```typescript * // Multi-product platform * const platforms = getPlatformsByProduct(GenericPlatform.AdgAny | GenericPlatform.UboAny); * // Returns: { * // 'AdGuard': [GenericPlatform.AdgAny], * // 'UblockOrigin': [GenericPlatform.UboAny] * // } * * // Mixed specific and generic * const mixed = SpecificPlatform.AdgExtChrome | SpecificPlatform.AdgExtFirefox | SpecificPlatform.AdgOsWindows; * const result = getPlatformsByProduct(mixed); * // Might return: { 'AdGuard': [GenericPlatform.AdgExtChromium, SpecificPlatform.AdgOsWindows] } * * // Iterate and validate for each product * for (const [product, platformList] of Object.entries(platforms)) { * for (const p of platformList) { * const result = modifierValidator.validate(p, modifier); * console.log(`${product}: ${result.valid}`); * } * } * ``` */ const getPlatformsByProduct = (platform) => { const result = {}; const productPlatforms = getProductGenericPlatforms(); if (platform & GenericPlatform.AdgAny) { const extracted = (platform & GenericPlatform.AdgAny); result[AdblockProduct.Adg] = optimizePlatformRepresentation(extracted, productPlatforms[AdblockProduct.Adg]); } if (platform & GenericPlatform.UboAny) { const extracted = (platform & GenericPlatform.UboAny); result[AdblockProduct.Ubo] = optimizePlatformRepresentation(extracted, productPlatforms[AdblockProduct.Ubo]); } if (platform & GenericPlatform.AbpAny) { const extracted = (platform & GenericPlatform.AbpAny); result[AdblockProduct.Abp] = optimizePlatformRepresentation(extracted, productPlatforms[AdblockProduct.Abp]); } return result; }; /** * Returns the platform enum value for the given platform string name. * * @param platform Platform string name, e.g., 'adg_os_windows'. * * @returns Specific or generic platform enum value. * * @throws Error if the platform is unknown. */ const getPlatformId = (platform) => { const specificPlatform = SPECIFIC_PLATFORM_MAP.get(platform); if (specificPlatform) { return specificPlatform; } const genericPlatform = GENERIC_PLATFORM_MAP.get(platform); if (genericPlatform) { return genericPlatform; } throw new Error(`Unknown platform: ${platform}`); }; /** * Returns the specific platform string name for the given platform enum value. * * @param platform Specific platform enum value. * * @returns Specific platform string name, e.g., 'adg_os_windows'. * * @throws Error if the platform is unknown. */ const getSpecificPlatformName = (platform) => { const specificPlatform = SPECIFIC_PLATFORM_MAP_REVERSE.get(platform); if (!specificPlatform) { throw new Error(`Unknown platform: ${platform}`); } return specificPlatform; }; /** * Returns the human-readable platform name for the given platform enum value. * * @param platform Platform enum value. * * @returns Human-readable platform name, e.g., 'AdGuard for Windows'. * * @throws Error if the platform is unknown. */ const getHumanReadablePlatformName = (platform) => { // Try specific platform first const specificPlatform = SPECIFIC_PLATFORM_HUMAN_READABLE_NAME_MAP.get(platform); if (specificPlatform) { return specificPlatform; } // Then try generic platform const genericPlatform = GENERIC_PLATFORM_HUMAN_READABLE_NAME_MAP.get(platform); if (genericPlatform) { return genericPlatform; } throw new Error(`Unknown platform: ${platform}`); }; /** * Gets all specific platforms for a given AdblockProduct. * Results are cached after the first call. * * @param product AdblockProduct to get specific platforms for. * * @returns Array of all specific platforms for the given product. * * @example * ```typescript * const adgPlatforms = getProductSpecificPlatforms(AdblockProduct.Adg); * // Returns: [AdgOsWindows, AdgOsMac, AdgOsAndroid, AdgExtChrome, ...] * ``` */ const getProductSpecificPlatforms = (product) => { // Initialize cache if needed if (PRODUCT_SPECIFIC_PLATFORMS === null) { const result = { [AdblockProduct.Adg]: [], [AdblockProduct.Ubo]: [], [AdblockProduct.Abp]: [], }; // Iterate over all specific platforms and group by product prefix const specificPlatformEntries = Object.entries(SpecificPlatform); for (const [name, platform] of specificPlatformEntries) { // Check which product this platform belongs to for (const [prod, prefix] of Object.entries(PRODUCT_PREFIX_MAP)) { if (name.startsWith(prefix)) { result[prod].push(platform); break; } } } // Cache the result as readonly PRODUCT_SPECIFIC_PLATFORMS = result; } return PRODUCT_SPECIFIC_PLATFORMS[product]; }; /** * Gets all available platform names from the platform maps. * * @returns Object containing arrays of all specific and generic platform names. * * @example * ```typescript * const { specificPlatformNames, genericPlatformNames } = getAllPlatformNames(); * // specificPlatformNames: ['adg_os_windows', 'adg_os_mac', 'adg_os_android', ...] * // genericPlatformNames: ['adg_os_any', 'adg_safari_any', 'adg_ext_chromium', ...] * ``` */ const getAllPlatformNames = () => { return { specificPlatformNames: Array.from(SPECIFIC_PLATFORM_MAP.keys()), genericPlatformNames: Array.from(GENERIC_PLATFORM_MAP.keys()), }; }; ;// CONCATENATED MODULE: ./node_modules/.pnpm/@adguard+agtree@4.2.1/node_modules/@adguard/agtree/dist/compatibility-tables/base.js /* * AGTree v4.2.1 (build date: Wed, 12 Aug 2026 01:31:02 GMT) * (c) 2026 Adguard Software Ltd. * Released under the MIT license * https://github.com/AdguardTeam/tsurlfilter/tree/master/packages/agtree#readme */ /* eslint-disable no-bitwise */ /** * @file Provides common compatibility table methods. */ /** * Base compatibility table class which provides common methods to work with compatibility data. * * @template T Compatibility data schema. */ class CompatibilityTableBase { /** * Compatibility table data. */ data; /** * Optional name transformer function. If provided, * it will be called in all methods before processing compatibility data names. */ nameTransformer; /** * Creates a new instance of the common compatibility table. * * @param data Compatibility table data. * @param nameTransformer Optional name transformer function. */ constructor(data, nameTransformer = null) { this.data = data; this.nameTransformer = nameTransformer; } /** * Helper method to get a 'row' from the compatibility table data by name. * * @param name Compatibility data name. * * @returns Compatibility table row storage or `null` if not found. */ getRowStorage(name) { const idx = this.data.map[name]; if ((0,type_guards/* .isUndefined */.b0)(idx)) { return null; } return this.data.shared[idx]; } /** * Checks whether a compatibility data `name` exists for any platform. * * @param name Compatibility data name. * * @returns True if the compatibility data exists, false otherwise. * * @note Technically, do the same as `exists()` method with generic platform _any_ * but it is faster because it does not apply complex logic. */ existsAny(name) { const normalizedName = this.nameTransformer ? this.nameTransformer(name) : name; return !(0,type_guards/* .isUndefined */.b0)(this.data.map[normalizedName]); } /** * Checks whether a compatibility data `name` exists for a specified platform. * * @param name Compatibility data name. * @param platform Specific or generic platform. * * @returns True if the compatibility data exists, false otherwise. */ exists(name, platform) { const normalizedName = this.nameTransformer ? this.nameTransformer(name) : name; const data = this.getRowStorage(normalizedName); if (!data) { return false; } const isMatch = (idx) => { const el = data.shared[idx]; return !(0,type_guards/* .isUndefined */.b0)(el) && (el.name === normalizedName || !!el.aliases?.includes(normalizedName)); }; if (isGenericPlatform(platform)) { // Since indexes are specific platforms in the compatibility table data, // we can't index them directly if the platform is generic (union of specific platforms). // In this case, we need to iterate over the keys and return true on the first match. const keys = Object.keys(data.map); for (let i = 0; i < keys.length; i += 1) { const key = Number(keys[i]); if (platform & key) { const idx = data.map[key]; if (isMatch(idx)) { return true; } } } return false; } const idx = data.map[platform]; return isMatch(idx); } /** * Returns a compatibility data by name and specific platform. * * @param name The name of the compatibility data. * @param platform The specific platform. * * @returns A single compatibility data or `null` if not found. */ getSingle(name, platform) { const normalizedName = this.nameTransformer ? this.nameTransformer(name) : name; const data = this.getRowStorage(normalizedName); if (!data) { return null; } const idx = data.map[platform]; return (0,type_guards/* .isUndefined */.b0)(idx) ? null : data.shared[idx]; } /** * Returns all compatibility data records for name and specified platform. * * @param name Compatibility data name. * @param platform Specific or generic platform. * * @returns Multiple records grouped by platforms. * Technically, it is an object where keys are platform enums values and values are compatibility data records. * * @note Platform enum values can be converted to string names using {@link getSpecificPlatformName} on demand. */ getMultiple(name, platform) { const normalizedName = this.nameTransformer ? this.nameTransformer(name) : name; const data = this.getRowStorage(normalizedName); if (!data) { return null; } if (isGenericPlatform(platform)) { const result = {}; const keys = Object.keys(data.map); for (let i = 0; i < keys.length; i += 1) { const key = Number(keys[i]); if (platform & key) { const idx = data.map[key]; if (!(0,type_guards/* .isUndefined */.b0)(idx)) { result[key] = data.shared[idx]; } } } return result; } const idx = data.map[platform]; if ((0,type_guards/* .isUndefined */.b0)(idx)) { return null; } return { key: data.shared[idx] }; } /** * Returns all compatibility data records for the specified platform. * * @param platform Specific or generic platform. * * @returns Array of multiple records grouped by platforms. */ getAllMultiple(platform) { const result = []; for (let i = 0; i < this.data.shared.length; i += 1) { const data = this.data.shared[i]; const names = new Set(data.shared.map(({ name }) => name)); names.forEach((name) => { const multipleRecords = this.getMultiple(name, platform); if (multipleRecords) { result.push(multipleRecords); } }); } return result; } /** * Returns the first compatibility data record for name and specified platform. * * @param name Compatibility data name. * @param platform Specific, generic, or combined platform. * * @returns First found compatibility data record or `null` if not found. */ getFirst(name, platform) { const normalizedName = this.nameTransformer ? this.nameTransformer(name) : name; const data = this.getRowStorage(normalizedName); if (!data) { return null; } if (isGenericPlatform(platform)) { const keys = Object.keys(data.map); for (let i = 0; i < keys.length; i += 1) { const key = Number(keys[i]); if (platform & key) { const idx = data.map[key]; if (!(0,type_guards/* .isUndefined */.b0)(idx)) { // return the first found record return data.shared[idx]; } } } return null; } const idx = data.map[platform]; if ((0,type_guards/* .isUndefined */.b0)(idx)) { return null; } return data.shared[idx]; } /** * Returns all compatibility data records for the specified name. * * @param name Compatibility data name. * * @returns Array of multiple records grouped by platforms. */ getRow(name) { const normalizedName = this.nameTransformer ? this.nameTransformer(name) : name; const data = this.getRowStorage(normalizedName); if (!data) { return []; } return data.shared; } /** * Returns all compatibility data grouped by products. * * @returns Array of multiple records grouped by products. */ getRowsByProduct() { const result = []; for (let i = 0; i < this.data.shared.length; i += 1) { const data = this.data.shared[i]; const keys = Object.keys(data.map); const row = { [adblockers/* .AdblockSyntax.Adg */.YG.Adg]: {}, [adblockers/* .AdblockSyntax.Ubo */.YG.Ubo]: {}, [adblockers/* .AdblockSyntax.Abp */.YG.Abp]: {}, }; for (let j = 0; j < keys.length; j += 1) { const key = Number(keys[j]); if (key & platforms/* .GenericPlatform.AdgAny */.p.AdgAny) { row[adblockers/* .AdblockSyntax.Adg */.YG.Adg][key] = data.shared[data.map[key]]; } else if (key & platforms/* .GenericPlatform.UboAny */.p.UboAny) { row[adblockers/* .AdblockSyntax.Ubo */.YG.Ubo][key] = data.shared[data.map[key]]; } else if (key & platforms/* .GenericPlatform.AbpAny */.p.AbpAny) { row[adblockers/* .AdblockSyntax.Abp */.YG.Abp][key] = data.shared[data.map[key]]; } } result.push(row); } return result; } } }, 33017(__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) { __webpack_require__.d(__webpack_exports__, { YJ: () => (scriptletsCompatibilityTableData), qL: () => (redirectsCompatibilityTableData), rd: () => (modifiersCompatibilityTableData) }); /* * AGTree v4.2.1 (build date: Wed, 12 Aug 2026 01:31:02 GMT) * (c) 2026 Adguard Software Ltd. * Released under the MIT license * https://github.com/AdguardTeam/tsurlfilter/tree/master/packages/agtree#readme */ const 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,valueOptionalExceptionOnly:false,valueFormat:null,valueFormatFlags: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,valueOptionalExceptionOnly:false,valueFormat:null,valueFormatFlags: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,valueOptionalExceptionOnly:false,valueFormat:'pipe_separated_apps',valueFormatFlags:null}],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,valueOptionalExceptionOnly:false,valueFormat:null,valueFormatFlags: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,valueOptionalExceptionOnly:false,valueFormat:null,valueFormatFlags: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,valueOptionalExceptionOnly:false,valueFormat:null,valueFormatFlags: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,valueOptionalExceptionOnly:false,valueFormat:null,valueFormatFlags: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,valueOptionalExceptionOnly:false,valueFormat:'^([^;=\\s]*?)((?:;(maxAge=\\d+;?)?|(sameSite=(lax|none|strict);?)?){1,3})(? (/* binding */ modifiersCompatibilityTable) }); // EXTERNAL MODULE: ./node_modules/.pnpm/@adguard+agtree@4.2.1/node_modules/@adguard/agtree/dist/utils/constants.js var constants = __webpack_require__(53097); // EXTERNAL MODULE: ./node_modules/.pnpm/@adguard+agtree@4.2.1/node_modules/@adguard/agtree/dist/utils/deep-freeze.js var deep_freeze = __webpack_require__(41666); ;// CONCATENATED MODULE: ./node_modules/.pnpm/@adguard+agtree@4.2.1/node_modules/@adguard/agtree/dist/utils/noop-modifier.js /* * AGTree v4.2.1 (build date: Wed, 12 Aug 2026 01:31:02 GMT) * (c) 2026 Adguard Software Ltd. * Released under the MIT license * https://github.com/AdguardTeam/tsurlfilter/tree/master/packages/agtree#readme */ /** * Validates the noop modifier (i.e. only underscores). * * @param value Value of the modifier. * * @returns True if the modifier is valid, false otherwise. */ const isValidNoopModifier = (value) => { const { length } = value; if (length === 0) { return false; } for (let i = 0; i < length; i += 1) { if (value[i] !== constants/* .UNDERSCORE */.fB) { return false; } } return true; }; // EXTERNAL MODULE: ./node_modules/.pnpm/@adguard+agtree@4.2.1/node_modules/@adguard/agtree/dist/compatibility-tables/base.js + 1 modules var base = __webpack_require__(21565); // EXTERNAL MODULE: ./node_modules/.pnpm/@adguard+agtree@4.2.1/node_modules/@adguard/agtree/dist/compatibility-tables/compatibility-table-data.js var compatibility_table_data = __webpack_require__(33017); ;// CONCATENATED MODULE: ./node_modules/.pnpm/@adguard+agtree@4.2.1/node_modules/@adguard/agtree/dist/compatibility-tables/modifiers.js /* * AGTree v4.2.1 (build date: Wed, 12 Aug 2026 01:31:02 GMT) * (c) 2026 Adguard Software Ltd. * Released under the MIT license * https://github.com/AdguardTeam/tsurlfilter/tree/master/packages/agtree#readme */ /** * @file Compatibility tables for modifiers. */ /** * Transforms the name of the modifier to a normalized form. * This is a special case: the noop modifier normally '_', but it can consist of any number of characters, * e.g. '____' is also valid. In this case, we need to normalize the name to '_'. * * @param name Modifier name to normalize. * * @returns Normalized modifier name. */ const noopModifierNameNormalizer = (name) => { if (name.startsWith(constants/* .UNDERSCORE */.fB)) { if (isValidNoopModifier(name)) { // in compatibility tables, we just store '_', so we need to reduce the number of underscores to 1 // before checking the existence of the noop modifier return constants/* .UNDERSCORE */.fB; } } return name; }; /** * Compatibility table for modifiers. */ class ModifiersCompatibilityTable extends base/* .CompatibilityTableBase */.E { /** * Creates a new instance of the compatibility table for modifiers. * * @param data Compatibility table data. */ constructor(data) { super(data, noopModifierNameNormalizer); } } /** * Deep freeze the compatibility table data to avoid accidental modifications. */ (0,deep_freeze/* .deepFreeze */.o)(compatibility_table_data/* .modifiersCompatibilityTableData */.rd); /** * Compatibility table instance for modifiers. */ const modifiersCompatibilityTable = new ModifiersCompatibilityTable(compatibility_table_data/* .modifiersCompatibilityTableData */.rd); }, 9257(__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) { __webpack_require__.d(__webpack_exports__, { c: () => (SpecificPlatform), p: () => (GenericPlatform) }); /* * AGTree v4.2.1 (build date: Wed, 12 Aug 2026 01:31:02 GMT) * (c) 2026 Adguard Software Ltd. * Released under the MIT license * https://github.com/AdguardTeam/tsurlfilter/tree/master/packages/agtree#readme */ /* eslint-disable no-bitwise */ /** * @file Provides platform enums. * The difference between specific and generic platforms is that specific platforms are individual platforms * (e.g. AdGuard for Windows, AdGuard for Android, etc.), * while generic platforms are groups of specific platforms * (e.g. AdGuard for any OS, AdGuard for any Chromium-based extension, etc.). */ /** * List of specific platforms. */ // eslint-disable-next-line @typescript-eslint/no-redeclare const SpecificPlatform = { AdgOsWindows: 1, AdgOsMac: (1 << 1), AdgOsAndroid: (1 << 2), AdgExtChrome: (1 << 3), AdgExtOpera: (1 << 4), AdgExtEdge: (1 << 5), AdgExtFirefox: (1 << 6), AdgCbAndroid: (1 << 7), AdgCbIos: (1 << 8), AdgCbSafari: (1 << 9), UboExtChrome: (1 << 10), UboExtOpera: (1 << 11), UboExtEdge: (1 << 12), UboExtFirefox: (1 << 13), AbpExtChrome: (1 << 14), AbpExtOpera: (1 << 15), AbpExtEdge: (1 << 16), AbpExtFirefox: (1 << 17), }; const AdgOsAny = SpecificPlatform.AdgOsWindows | SpecificPlatform.AdgOsMac | SpecificPlatform.AdgOsAndroid; const AdgSafariAny = SpecificPlatform.AdgCbSafari | SpecificPlatform.AdgCbIos; const AdgExtChromium = SpecificPlatform.AdgExtChrome | SpecificPlatform.AdgExtOpera | SpecificPlatform.AdgExtEdge; const AdgExtAny = AdgExtChromium | SpecificPlatform.AdgExtFirefox; const AdgAny = AdgExtAny | AdgOsAny | AdgSafariAny | SpecificPlatform.AdgCbAndroid; const UboExtChromium = SpecificPlatform.UboExtChrome | SpecificPlatform.UboExtOpera | SpecificPlatform.UboExtEdge; const UboExtAny = UboExtChromium | SpecificPlatform.UboExtFirefox; const UboAny = UboExtAny; const AbpExtChromium = SpecificPlatform.AbpExtChrome | SpecificPlatform.AbpExtOpera | SpecificPlatform.AbpExtEdge; const AbpExtAny = AbpExtChromium | SpecificPlatform.AbpExtFirefox; const AbpAny = AbpExtAny; const Any = AdgAny | UboAny | AbpAny; /** * List of generic platforms (combinations of specific platforms). */ // eslint-disable-next-line @typescript-eslint/no-redeclare const GenericPlatform = { AdgOsAny: AdgOsAny, AdgSafariAny: AdgSafariAny, AdgExtChromium: AdgExtChromium, AdgExtAny: AdgExtAny, AdgAny: AdgAny, UboExtChromium: UboExtChromium, UboExtAny: UboExtAny, UboAny: UboAny, AbpExtChromium: AbpExtChromium, AbpExtAny: AbpExtAny, AbpAny: AbpAny, Any: Any, }; }, 63780(__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) { __webpack_require__.d(__webpack_exports__, { S: () => (redirectsCompatibilityTable) }); /* import */ var _utils_constants_js__rspack_import_0 = __webpack_require__(53097); /* import */ var _utils_deep_freeze_js__rspack_import_4 = __webpack_require__(41666); /* import */ var _utils_type_guards_js__rspack_import_2 = __webpack_require__(64505); /* import */ var _base_js__rspack_import_1 = __webpack_require__(21565); /* import */ var _compatibility_table_data_js__rspack_import_5 = __webpack_require__(33017); /* import */ var _utils_resource_type_helpers_js__rspack_import_3 = __webpack_require__(95473); /* * AGTree v4.2.1 (build date: Wed, 12 Aug 2026 01:31:02 GMT) * (c) 2026 Adguard Software Ltd. * Released under the MIT license * https://github.com/AdguardTeam/tsurlfilter/tree/master/packages/agtree#readme */ /** * @file Compatibility tables for redirects. */ /** * Prefix for resource redirection names. */ const ABP_RESOURCE_PREFIX = 'abp-resource:'; const ABP_RESOURCE_PREFIX_LENGTH = ABP_RESOURCE_PREFIX.length; /** * Normalizes the redirect name. * * @param name Redirect name to normalize. * * @returns Normalized redirect name. * * @example * redirectNameNormalizer('abp-resource:my-resource') // => 'my-resource' * redirectNameNormalizer('noop.js:99') // => 'noop.js' */ const redirectNameNormalizer = (name) => { // Remove ABP resource prefix, if present if (name.startsWith(ABP_RESOURCE_PREFIX)) { return name.slice(ABP_RESOURCE_PREFIX_LENGTH); } /** * Remove :[integer] priority suffix from the name, if present. * * Note: negative values are also supported, see AG-48788. * * @see https://github.com/AdguardTeam/tsurlfilter/issues/59 * @see https://github.com/gorhill/uBlock/wiki/Static-filter-syntax#redirect */ const colonIndex = name.lastIndexOf(_utils_constants_js__rspack_import_0/* .COLON */.oH); if (colonIndex !== -1 && /^-?\d+$/.test(name.slice(colonIndex + 1))) { return name.slice(0, colonIndex); } return name; }; /** * Compatibility table for redirects. */ class RedirectsCompatibilityTable extends _base_js__rspack_import_1/* .CompatibilityTableBase */.E { /** * Creates a new instance of the compatibility table for redirects. * * @param data Compatibility table data. */ constructor(data) { super(data, redirectNameNormalizer); } /** * Gets the resource type adblock modifiers for the redirect for the given platform * based on the `resourceTypes` field. * * @param redirect Redirect name or redirect data. * @param platform Platform to get the modifiers for (can be specific, generic, or combined platforms). * * @returns Set of resource type modifiers or an empty set if the redirect is not found or has no resource types. */ getResourceTypeModifiers(redirect, platform) { let redirectData = null; if ((0,_utils_type_guards_js__rspack_import_2/* .isString */.Kg)(redirect)) { redirectData = this.getFirst(redirect, platform); } else { redirectData = redirect; } const modifierNames = new Set(); if ((0,_utils_type_guards_js__rspack_import_2/* .isNull */.kZ)(redirectData) || (0,_utils_type_guards_js__rspack_import_2/* .isUndefined */.b0)(redirectData.resourceTypes)) { return modifierNames; } for (const resourceType of redirectData.resourceTypes) { const modifierName = (0,_utils_resource_type_helpers_js__rspack_import_3/* .getResourceTypeModifier */.e)(resourceType, platform); if ((0,_utils_type_guards_js__rspack_import_2/* .isNull */.kZ)(modifierName)) { continue; } modifierNames.add(modifierName); } return modifierNames; } } /** * Deep freeze the compatibility table data to avoid accidental modifications. */ (0,_utils_deep_freeze_js__rspack_import_4/* .deepFreeze */.o)(_compatibility_table_data_js__rspack_import_5/* .redirectsCompatibilityTableData */.qL); /** * Compatibility table instance for redirects. */ const redirectsCompatibilityTable = new RedirectsCompatibilityTable(_compatibility_table_data_js__rspack_import_5/* .redirectsCompatibilityTableData */.qL); }, 95473(__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) { // EXPORTS __webpack_require__.d(__webpack_exports__, { x: () => (/* binding */ isValidResourceType), e: () => (/* binding */ getResourceTypeModifier) }); // EXTERNAL MODULE: ./node_modules/.pnpm/@adguard+agtree@4.2.1/node_modules/@adguard/agtree/dist/utils/type-guards.js var type_guards = __webpack_require__(64505); // EXTERNAL MODULE: ./node_modules/.pnpm/@adguard+agtree@4.2.1/node_modules/@adguard/agtree/dist/compatibility-tables/modifiers.js + 1 modules var modifiers = __webpack_require__(6674); // EXTERNAL MODULE: ./node_modules/.pnpm/zod@3.24.4/node_modules/zod/lib/index.mjs var lib = __webpack_require__(53034); ;// CONCATENATED MODULE: ./node_modules/.pnpm/@adguard+agtree@4.2.1/node_modules/@adguard/agtree/dist/compatibility-tables/schemas/resource-type.js /* * AGTree v4.2.1 (build date: Wed, 12 Aug 2026 01:31:02 GMT) * (c) 2026 Adguard Software Ltd. * Released under the MIT license * https://github.com/AdguardTeam/tsurlfilter/tree/master/packages/agtree#readme */ /** * @file Resource type schema. */ /** * Resource type. * * @see {@link https://developer.chrome.com/docs/extensions/reference/declarativeNetRequest/#type-ResourceType} */ const ResourceType = { MainFrame: 'main_frame', SubFrame: 'sub_frame', Stylesheet: 'stylesheet', Script: 'script', Image: 'image', Font: 'font', Object: 'object', XmlHttpRequest: 'xmlhttprequest', Ping: 'ping', Media: 'media', WebSocket: 'websocket', Other: 'other', }; /** * Resource type schema. */ const resourceTypeSchema = lib/* ["default"].nativeEnum */.Ay.nativeEnum(ResourceType); ;// CONCATENATED MODULE: ./node_modules/.pnpm/@adguard+agtree@4.2.1/node_modules/@adguard/agtree/dist/compatibility-tables/utils/resource-type-helpers.js /* * AGTree v4.2.1 (build date: Wed, 12 Aug 2026 01:31:02 GMT) * (c) 2026 Adguard Software Ltd. * Released under the MIT license * https://github.com/AdguardTeam/tsurlfilter/tree/master/packages/agtree#readme */ /** * Map of resource types to their corresponding adblock modifier names. * * @note Record type is used to ensure that all resource types are present in the map. */ const RESOURCE_TYPE_MODIFIER_MAP = Object.freeze({ [ResourceType.MainFrame]: 'document', [ResourceType.SubFrame]: 'subdocument', [ResourceType.Stylesheet]: 'stylesheet', [ResourceType.Script]: 'script', [ResourceType.Image]: 'image', [ResourceType.Font]: 'font', [ResourceType.Object]: 'object', [ResourceType.XmlHttpRequest]: 'xmlhttprequest', [ResourceType.Ping]: 'ping', [ResourceType.Media]: 'media', [ResourceType.WebSocket]: 'websocket', [ResourceType.Other]: 'other', }); /** * Gets the adblock modifier name for the given resource type. * * @param resourceType Resource type to get the modifier name for. * @param platform Platform to get the modifier for (can be specific, generic, or combined platforms). * * @returns A string containing the adblock modifier name for the given resource type * or `null` if the modifier could not be found. */ const getResourceTypeModifier = (resourceType, platform) => { const modifierName = RESOURCE_TYPE_MODIFIER_MAP[resourceType]; if (!modifierName) { return null; } const modifierData = modifiers/* .modifiersCompatibilityTable.getFirst */.Z.getFirst(modifierName, platform); if ((0,type_guards/* .isNull */.kZ)(modifierData)) { return null; } return modifierData.name; }; /** * Checks if the given resource type is valid. * * @param resourceType Resource type to check. * * @returns `true` if the resource type is valid, `false` otherwise. */ const isValidResourceType = (resourceType) => { return Object.values(ResourceType).includes(resourceType); }; }, 83956(__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) { __webpack_require__.d(__webpack_exports__, { I: () => (BaseConverter) }); /* import */ var _errors_not_implemented_error_js__rspack_import_0 = __webpack_require__(82535); /* * AGTree v4.2.1 (build date: Wed, 12 Aug 2026 01:31:02 GMT) * (c) 2026 Adguard Software Ltd. * Released under the MIT license * https://github.com/AdguardTeam/tsurlfilter/tree/master/packages/agtree#readme */ /** * @file Base class for converters. * * TS doesn't support abstract static methods, so we should use * a workaround and extend this class instead of implementing it. */ /* eslint-disable jsdoc/require-returns-check */ /* eslint-disable @typescript-eslint/no-unused-vars */ /** * Basic class for rule converters. */ class BaseConverter { /** * Converts some data to AdGuard format. * * @param data Data to convert. * * @returns An object which follows the {@link ConversionResult} interface. Its `result` property contains * the converted node, and its `isConverted` flag indicates whether the original node was converted. * If the node was not converted, the result will contain the original node with the same object reference. * * @throws If the data is invalid or incompatible. */ static convertToAdg(data) { throw new _errors_not_implemented_error_js__rspack_import_0/* .NotImplementedError */.E(); } /** * Converts some data to Adblock Plus format. * * @param data Data to convert. * * @returns An object which follows the {@link ConversionResult} interface. Its `result` property contains * the converted node, and its `isConverted` flag indicates whether the original node was converted. * If the node was not converted, the result will contain the original node with the same object reference. * * @throws If the data is invalid or incompatible. */ static convertToAbp(data) { throw new _errors_not_implemented_error_js__rspack_import_0/* .NotImplementedError */.E(); } /** * Converts some data to uBlock Origin format. * * @param data Data to convert. * * @returns An object which follows the {@link ConversionResult} interface. Its `result` property contains * the converted node, and its `isConverted` flag indicates whether the original node was converted. * If the node was not converted, the result will contain the original node with the same object reference. * * @throws If the data is invalid or incompatible. */ static convertToUbo(data) { throw new _errors_not_implemented_error_js__rspack_import_0/* .NotImplementedError */.E(); } } }, 51548(__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) { __webpack_require__.d(__webpack_exports__, { c: () => (createConversionResult), k: () => (createNodeConversionResult) }); /* * AGTree v4.2.1 (build date: Wed, 12 Aug 2026 01:31:02 GMT) * (c) 2026 Adguard Software Ltd. * Released under the MIT license * https://github.com/AdguardTeam/tsurlfilter/tree/master/packages/agtree#readme */ /** * @file Conversion result interface and helper functions. */ /** * Helper function to create a generic conversion result. * * @template T Type of the item to convert. * @template U Type of the conversion result (defaults to `T`, but can be `T[]` as well). * * @param result Conversion result. * @param isConverted Indicates whether the input item was converted. * * @returns Generic conversion result. */ // eslint-disable-next-line max-len function createConversionResult(result, isConverted) { return { result, isConverted, }; } /** * Helper function to create a node conversion result. * * @template T Type of the node (extends `Node`). * * @param nodes Array of nodes. * @param isConverted Indicates whether the input item was converted. * * @returns Node conversion result. */ function createNodeConversionResult(nodes, isConverted) { return createConversionResult(nodes, isConverted); } }, 63829(__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) { __webpack_require__.d(__webpack_exports__, { FH: () => (REMOVE_VALUE), JX: () => (REMOVE_PROPERTY), PY: () => (ABP_EXT_CSS_PREFIX), Ss: () => (EXT_CSS_PSEUDO_CLASSES), Y_: () => (NATIVE_CSS_PSEUDO_CLASSES), at: () => (LEGACY_EXT_CSS_ATTRIBUTE_PREFIX), ig: () => (EXT_CSS_PSEUDO_CLASSES_STRICT) }); /* * AGTree v4.2.1 (build date: Wed, 12 Aug 2026 01:31:02 GMT) * (c) 2026 Adguard Software Ltd. * Released under the MIT license * https://github.com/AdguardTeam/tsurlfilter/tree/master/packages/agtree#readme */ /** * @file Known CSS elements and attributes. * TODO: Implement a compatibility table for Extended CSS. */ /** * Legacy Extended CSS attribute prefix. * * @example * ```css * [-ext-=...] * ``` */ const LEGACY_EXT_CSS_ATTRIBUTE_PREFIX = '-ext-'; /** * ABP Extended CSS prefix. * * @example * ```css * [-abp-=...] * -abp-(...) * ``` */ const ABP_EXT_CSS_PREFIX = '-abp'; /** * Known CSS pseudo-classes that are supported by all browsers natively, * but can also be applied as extended. */ const NATIVE_CSS_PSEUDO_CLASSES = new Set([ /** * Https://developer.mozilla.org/en-US/docs/Web/CSS/:has * https://github.com/AdguardTeam/ExtendedCss#extended-css-has. */ 'has', /** * Https://developer.mozilla.org/en-US/docs/Web/CSS/:is * https://github.com/AdguardTeam/ExtendedCss#extended-css-is. */ 'is', /** * Https://developer.mozilla.org/en-US/docs/Web/CSS/:not * https://github.com/AdguardTeam/ExtendedCss#extended-css-not. */ 'not', ]); /** * Known _strict_ Extended CSS pseudo-classes. Please, keep this list sorted. * Strict means that these pseudo-classes are not supported by any browser natively, * and they always require Extended CSS libraries to work. */ const EXT_CSS_PSEUDO_CLASSES_STRICT = new Set([ // AdGuard // https://github.com/AdguardTeam/ExtendedCss 'contains', 'if-not', 'matches-attr', 'matches-css', 'matches-property', 'nth-ancestor', 'remove', 'upward', 'xpath', // uBlock Origin // https://github.com/gorhill/uBlock/wiki/Static-filter-syntax#procedural-cosmetic-filters 'has-text', 'matches-css-after', 'matches-css-before', 'matches-path', 'min-text-length', 'watch-attr', // Adblock Plus // https://help.eyeo.com/adblockplus/how-to-write-filters#elemhide-emulation '-abp-contains', '-abp-has', '-abp-properties', ]); /** * _ALL_ known Extended CSS pseudo-classes. Please, keep this list sorted. * It includes strict pseudo-classes and additional pseudo-classes that may be * supported by some browsers natively. */ const EXT_CSS_PSEUDO_CLASSES = new Set([ ...EXT_CSS_PSEUDO_CLASSES_STRICT, ...NATIVE_CSS_PSEUDO_CLASSES, ]); /** * Known extended CSS property that is used to remove elements. * * @see {@link https://github.com/AdguardTeam/ExtendedCss#remove-pseudos} */ const REMOVE_PROPERTY = 'remove'; /** * Known extended CSS value for {@link REMOVE_PROPERTY} property to remove elements. * * @see {@link https://github.com/AdguardTeam/ExtendedCss#remove-pseudos} */ const REMOVE_VALUE = 'true'; }, 26982(__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) { __webpack_require__.d(__webpack_exports__, { $: () => (RawRuleConverter) }); /* import */ var _parser_rule_parser_js__rspack_import_2 = __webpack_require__(53550); /* import */ var _base_interfaces_base_converter_js__rspack_import_0 = __webpack_require__(83956); /* import */ var _base_interfaces_conversion_result_js__rspack_import_3 = __webpack_require__(51548); /* import */ var _rule_js__rspack_import_1 = __webpack_require__(53026); /* import */ var _generator_rule_generator_js__rspack_import_4 = __webpack_require__(11598); /* * AGTree v4.2.1 (build date: Wed, 12 Aug 2026 01:31:02 GMT) * (c) 2026 Adguard Software Ltd. * Released under the MIT license * https://github.com/AdguardTeam/tsurlfilter/tree/master/packages/agtree#readme */ /** * @file Rule converter for raw rules. * * Technically, this is a wrapper around `RuleConverter` that works with nodes instead of strings. */ /** * Adblock filtering rule converter class. * * You can use this class to convert string-based adblock rules, since most of the converters work with nodes. * This class just provides an extra layer on top of the {@link RuleConverter} and calls the parser/serializer * before/after the conversion internally. * * @todo Implement `convertToUbo` and `convertToAbp`. */ class RawRuleConverter extends _base_interfaces_base_converter_js__rspack_import_0/* .BaseConverter */.I { /** * Converts an adblock filtering rule to AdGuard format, if possible. * * @param rawRule Raw rule text to convert. * * @returns An object which follows the {@link ConversionResult} interface. Its `result` property contains * the array of converted rule texts, and its `isConverted` flag indicates whether the original rule was converted. * If the rule was not converted, the original rule text will be returned. * * @throws If the rule is invalid or cannot be converted. */ static convertToAdg(rawRule) { const conversionResult = _rule_js__rspack_import_1/* .RuleConverter.convertToAdg */.b.convertToAdg(_parser_rule_parser_js__rspack_import_2/* .RuleParser.parse */.G.parse(rawRule)); // If the rule was not converted, return the original rule text if (!conversionResult.isConverted) { return (0,_base_interfaces_conversion_result_js__rspack_import_3/* .createConversionResult */.c)([rawRule], false); } // Otherwise, serialize the converted rule nodes return (0,_base_interfaces_conversion_result_js__rspack_import_3/* .createConversionResult */.c)(conversionResult.result.map(_generator_rule_generator_js__rspack_import_4/* .RuleGenerator.generate */.u.generate), true); } } }, 53026(__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) { // EXPORTS __webpack_require__.d(__webpack_exports__, { b: () => (/* binding */ RuleConverter) }); ;// CONCATENATED MODULE: ./node_modules/.pnpm/@adguard+agtree@4.2.1/node_modules/@adguard/agtree/dist/errors/rule-conversion-error.js /* * AGTree v4.2.1 (build date: Wed, 12 Aug 2026 01:31:02 GMT) * (c) 2026 Adguard Software Ltd. * Released under the MIT license * https://github.com/AdguardTeam/tsurlfilter/tree/master/packages/agtree#readme */ /** * @file Customized error class for conversion errors. */ const ERROR_NAME = 'RuleConversionError'; /** * Customized error class for conversion errors. */ class RuleConversionError extends Error { /** * Constructs a new `RuleConversionError` instance. * * @param message Error message. */ constructor(message) { super(message); this.name = ERROR_NAME; } } // EXTERNAL MODULE: ./node_modules/.pnpm/@adguard+agtree@4.2.1/node_modules/@adguard/agtree/dist/nodes/index.js var nodes = __webpack_require__(79864); // EXTERNAL MODULE: ./node_modules/.pnpm/@adguard+agtree@4.2.1/node_modules/@adguard/agtree/dist/converter/base-interfaces/conversion-result.js var conversion_result = __webpack_require__(51548); // EXTERNAL MODULE: ./node_modules/.pnpm/@adguard+agtree@4.2.1/node_modules/@adguard/agtree/dist/errors/not-implemented-error.js var not_implemented_error = __webpack_require__(82535); // EXTERNAL MODULE: ./node_modules/.pnpm/@adguard+agtree@4.2.1/node_modules/@adguard/agtree/dist/converter/base-interfaces/base-converter.js var base_converter = __webpack_require__(83956); ;// CONCATENATED MODULE: ./node_modules/.pnpm/@adguard+agtree@4.2.1/node_modules/@adguard/agtree/dist/converter/base-interfaces/rule-converter-base.js /* * AGTree v4.2.1 (build date: Wed, 12 Aug 2026 01:31:02 GMT) * (c) 2026 Adguard Software Ltd. * Released under the MIT license * https://github.com/AdguardTeam/tsurlfilter/tree/master/packages/agtree#readme */ /** * @file Base class for rule converters. * * TS doesn't support abstract static methods, so we should use * a workaround and extend this class instead of implementing it. */ /* eslint-disable jsdoc/require-returns-check */ /* eslint-disable @typescript-eslint/no-unused-vars */ /** * Basic class for rule converters. */ class RuleConverterBase extends base_converter/* .BaseConverter */.I { /** * Converts an adblock filtering rule to AdGuard format, if possible. * * @param rule Rule node to convert. * * @returns An object which follows the {@link NodeConversionResult} interface. Its `result` property contains * the array of converted rule nodes, and its `isConverted` flag indicates whether the original rule was converted. * If the rule was not converted, the result array will contain the original node with the same object reference. * * @throws If the rule is invalid or cannot be converted. */ static convertToAdg(rule) { throw new not_implemented_error/* .NotImplementedError */.E(); } /** * Converts an adblock filtering rule to Adblock Plus format, if possible. * * @param rule Rule node to convert. * * @returns An object which follows the {@link NodeConversionResult} interface. Its `result` property contains * the array of converted rule nodes, and its `isConverted` flag indicates whether the original rule was converted. * If the rule was not converted, the result array will contain the original node with the same object reference. * * @throws If the rule is invalid or cannot be converted. */ static convertToAbp(rule) { throw new not_implemented_error/* .NotImplementedError */.E(); } /** * Converts an adblock filtering rule to uBlock Origin format, if possible. * * @param rule Rule node to convert. * * @returns An object which follows the {@link NodeConversionResult} interface. Its `result` property contains * the array of converted rule nodes, and its `isConverted` flag indicates whether the original rule was converted. * If the rule was not converted, the result array will contain the original node with the same object reference. * * @throws If the rule is invalid or cannot be converted. */ static convertToUbo(rule) { throw new not_implemented_error/* .NotImplementedError */.E(); } } // EXTERNAL MODULE: ./node_modules/.pnpm/clone-deep@4.0.1/node_modules/clone-deep/index.js var clone_deep = __webpack_require__(98518); ;// CONCATENATED MODULE: ./node_modules/.pnpm/@adguard+agtree@4.2.1/node_modules/@adguard/agtree/dist/utils/clone.js /* * AGTree v4.2.1 (build date: Wed, 12 Aug 2026 01:31:02 GMT) * (c) 2026 Adguard Software Ltd. * Released under the MIT license * https://github.com/AdguardTeam/tsurlfilter/tree/master/packages/agtree#readme */ /** * @file Clone related utilities. * * We should keep clone related functions in this file. Thus, we just provide * a simple interface for cloning values, we use it across the AGTree project, * and the implementation "under the hood" can be improved later, if needed. */ /** * Clones an input value to avoid side effects. Use it only in justified cases, * because it can impact performance negatively. * * @param value Value to clone. * * @returns Cloned value. */ function clone(value) { // TODO: Replace cloneDeep with a more efficient implementation return clone_deep(value); } // EXTERNAL MODULE: ./node_modules/.pnpm/@adguard+agtree@4.2.1/node_modules/@adguard/agtree/dist/utils/constants.js var constants = __webpack_require__(53097); ;// CONCATENATED MODULE: ./node_modules/.pnpm/@adguard+agtree@4.2.1/node_modules/@adguard/agtree/dist/converter/comment/index.js /* * AGTree v4.2.1 (build date: Wed, 12 Aug 2026 01:31:02 GMT) * (c) 2026 Adguard Software Ltd. * Released under the MIT license * https://github.com/AdguardTeam/tsurlfilter/tree/master/packages/agtree#readme */ /** * @file Comment rule converter. */ /** * Comment rule converter class. * * @todo Implement `convertToUbo` and `convertToAbp`. */ class CommentRuleConverter extends RuleConverterBase { /** * Converts a comment rule to AdGuard format, if possible. * * @param rule Rule node to convert. * * @returns An object which follows the {@link NodeConversionResult} interface. Its `result` property contains * the array of converted rule nodes, and its `isConverted` flag indicates whether the original rule was converted. * If the rule was not converted, the result array will contain the original node with the same object reference. * * @throws If the rule is invalid or cannot be converted. */ static convertToAdg(rule) { // TODO: Add support for other comment types, if needed // Main task is # -> ! conversion switch (rule.type) { case nodes/* .CommentRuleType.CommentRule */.gV.CommentRule: // Check if the rule needs to be converted if (rule.type === nodes/* .CommentRuleType.CommentRule */.gV.CommentRule && rule.marker.value === nodes/* .CommentMarker.Hashmark */.yg.Hashmark) { // Add a ! to the beginning of the comment // TODO: Replace with custom clone method const ruleClone = clone(rule); ruleClone.marker.value = nodes/* .CommentMarker.Regular */.yg.Regular; // Add the hashmark to the beginning of the comment text ruleClone.text.value = `${constants/* .SPACE */.t6}${nodes/* .CommentMarker.Hashmark */.yg.Hashmark}${ruleClone.text.value}`; return (0,conversion_result/* .createNodeConversionResult */.k)([ruleClone], true); } return (0,conversion_result/* .createNodeConversionResult */.k)([rule], false); // Leave any other comment rule as is default: return (0,conversion_result/* .createNodeConversionResult */.k)([rule], false); } } } // EXTERNAL MODULE: ./node_modules/.pnpm/@adguard+agtree@4.2.1/node_modules/@adguard/agtree/dist/utils/adblockers.js var adblockers = __webpack_require__(22380); // EXTERNAL MODULE: ./node_modules/.pnpm/@adguard+agtree@4.2.1/node_modules/@adguard/agtree/dist/parser/css/css-token-stream.js var css_token_stream = __webpack_require__(44148); // EXTERNAL MODULE: ./node_modules/.pnpm/sprintf-js@1.1.3/node_modules/sprintf-js/src/sprintf.js var sprintf = __webpack_require__(37155); // EXTERNAL MODULE: ./node_modules/.pnpm/@adguard+css-tokenizer@1.2.0/node_modules/@adguard/css-tokenizer/dist/csstokenizer.mjs var csstokenizer = __webpack_require__(83747); // EXTERNAL MODULE: ./node_modules/.pnpm/@adguard+agtree@4.2.1/node_modules/@adguard/agtree/dist/converter/data/css.js var css = __webpack_require__(63829); // EXTERNAL MODULE: ./node_modules/.pnpm/@adguard+agtree@4.2.1/node_modules/@adguard/agtree/dist/utils/quotes.js var quotes = __webpack_require__(68999); ;// CONCATENATED MODULE: ./node_modules/.pnpm/@adguard+agtree@4.2.1/node_modules/@adguard/agtree/dist/converter/css/index.js /* * AGTree v4.2.1 (build date: Wed, 12 Aug 2026 01:31:02 GMT) * (c) 2026 Adguard Software Ltd. * Released under the MIT license * https://github.com/AdguardTeam/tsurlfilter/tree/master/packages/agtree#readme */ const ERROR_MESSAGES = { // eslint-disable-next-line max-len INVALID_ATTRIBUTE_VALUE: `Expected '${(0,csstokenizer/* .getFormattedTokenName */.bZ)(csstokenizer/* .TokenType.Ident */.ks.Ident)}' or '${(0,csstokenizer/* .getFormattedTokenName */.bZ)(csstokenizer/* .TokenType.String */.ks.String)}' as attribute value, but got '%s' with value '%s`, }; const PseudoClasses = { AbpContains: '-abp-contains', AbpHas: '-abp-has', Contains: 'contains', Has: 'has', HasText: 'has-text', MatchesCss: 'matches-css', MatchesCssAfter: 'matches-css-after', MatchesCssBefore: 'matches-css-before'}; const PseudoElements = { After: 'after', Before: 'before', }; const PSEUDO_ELEMENT_NAMES = new Set([ PseudoElements.After, PseudoElements.Before, ]); /** * CSS selector converter. * * @todo Implement `convertToUbo` and `convertToAbp`. */ class CssSelectorConverter extends base_converter/* .BaseConverter */.I { /** * Converts Extended CSS elements to AdGuard-compatible ones. * * @param selectorList Selector list to convert. * * @returns An object which follows the {@link ConversionResult} interface. Its `result` property contains * the converted node, and its `isConverted` flag indicates whether the original node was converted. * If the node was not converted, the result will contain the original node with the same object reference. * * @throws If the rule is invalid or incompatible. */ static convertToAdg(selectorList) { const stream = selectorList instanceof css_token_stream/* .CssTokenStream */.d ? selectorList : new css_token_stream/* .CssTokenStream */.d(selectorList); const converted = []; const convertAndPushPseudo = (pseudo) => { switch (pseudo) { case PseudoClasses.AbpContains: case PseudoClasses.HasText: converted.push(PseudoClasses.Contains); converted.push(constants/* .OPEN_PARENTHESIS */.Cx); break; case PseudoClasses.AbpHas: converted.push(PseudoClasses.Has); converted.push(constants/* .OPEN_PARENTHESIS */.Cx); break; // a bit special case: // - `:matches-css-before(...)` → `:matches-css(before, ...)` // - `:matches-css-after(...)` → `:matches-css(after, ...)` case PseudoClasses.MatchesCssBefore: case PseudoClasses.MatchesCssAfter: converted.push(PseudoClasses.MatchesCss); converted.push(constants/* .OPEN_PARENTHESIS */.Cx); converted.push(pseudo.substring(PseudoClasses.MatchesCss.length + 1)); converted.push(constants/* .COMMA */.KE); break; default: converted.push(pseudo); converted.push(constants/* .OPEN_PARENTHESIS */.Cx); break; } }; while (!stream.isEof()) { const token = stream.getOrFail(); if (token.type === csstokenizer/* .TokenType.Colon */.ks.Colon) { // Advance colon stream.advance(); converted.push(constants/* .COLON */.oH); const tempToken = stream.getOrFail(); // Double colon is a pseudo-element if (tempToken.type === csstokenizer/* .TokenType.Colon */.ks.Colon) { stream.advance(); converted.push(constants/* .COLON */.oH); continue; } if (tempToken.type === csstokenizer/* .TokenType.Ident */.ks.Ident) { const name = stream.source.slice(tempToken.start, tempToken.end); if (PSEUDO_ELEMENT_NAMES.has(name)) { // Add an extra colon to the name converted.push(constants/* .COLON */.oH); converted.push(name); } else { // Add the name as is converted.push(name); } // Advance the names stream.advance(); } else if (tempToken.type === csstokenizer/* .TokenType.Function */.ks.Function) { const name = stream.source.slice(tempToken.start, tempToken.end - 1); // omit the last parenthesis // :-abp-contains(...) → :contains(...) // :has-text(...) → :contains(...) // :-abp-has(...) → :has(...) convertAndPushPseudo(name); // Advance the function name stream.advance(); } } else if (token.type === csstokenizer/* .TokenType.OpenSquareBracket */.ks.OpenSquareBracket) { let tempToken; const { start } = token; stream.advance(); // Converts legacy Extended CSS selectors to the modern Extended CSS syntax. // For example: // - `[-ext-has=...]` → `:has(...)` // - `[-ext-contains=...]` → `:contains(...)` // - `[-ext-matches-css-before=...]` → `:matches-css(before, ...)` stream.skipWhitespace(); stream.expect(csstokenizer/* .TokenType.Ident */.ks.Ident); tempToken = stream.getOrFail(); let attr = stream.source.slice(tempToken.start, tempToken.end); // Skip if the attribute name is not a legacy Extended CSS one if (!(attr.startsWith(css/* .LEGACY_EXT_CSS_ATTRIBUTE_PREFIX */.at) || attr.startsWith(css/* .ABP_EXT_CSS_PREFIX */.PY))) { converted.push(stream.source.slice(start, tempToken.end)); stream.advance(); continue; } if (attr.startsWith(css/* .LEGACY_EXT_CSS_ATTRIBUTE_PREFIX */.at)) { attr = attr.slice(css/* .LEGACY_EXT_CSS_ATTRIBUTE_PREFIX.length */.at.length); } stream.advance(); stream.skipWhitespace(); // Next token should be an equality operator (=), because Extended CSS attribute selectors // do not support other operators stream.expect(csstokenizer/* .TokenType.Delim */.ks.Delim, { value: constants/* .EQUALS */.UT }); stream.advance(); // Skip optional whitespace after the operator stream.skipWhitespace(); // Parse attribute value tempToken = stream.getOrFail(); // According to the spec, attribute value should be an identifier or a string if (tempToken.type !== csstokenizer/* .TokenType.Ident */.ks.Ident && tempToken.type !== csstokenizer/* .TokenType.String */.ks.String) { throw new Error((0,sprintf.sprintf)(ERROR_MESSAGES.INVALID_ATTRIBUTE_VALUE, (0,csstokenizer/* .getFormattedTokenName */.bZ)(tempToken.type), stream.source.slice(tempToken.start, tempToken.end))); } const value = stream.source.slice(tempToken.start, tempToken.end); // Advance the attribute value stream.advance(); // Skip optional whitespace after the attribute value stream.skipWhitespace(); // Next character should be a closing square bracket // We don't allow flags for Extended CSS attribute selectors stream.expect(csstokenizer/* .TokenType.CloseSquareBracket */.ks.CloseSquareBracket); stream.advance(); converted.push(constants/* .COLON */.oH); convertAndPushPseudo(attr); let processedValue = quotes/* .QuoteUtils.removeQuotes */.Qj.removeQuotes(value); if (attr === PseudoClasses.Has) { // TODO: Optimize this to avoid double tokenization processedValue = CssSelectorConverter.convertToAdg(processedValue).result; } converted.push(processedValue); converted.push(constants/* .CLOSE_PARENTHESIS */.s1); } else { converted.push(stream.source.slice(token.start, token.end)); // Advance the token stream.advance(); } } const convertedSelectorList = converted.join(constants/* .EMPTY */.wg); return (0,conversion_result/* .createConversionResult */.c)(convertedSelectorList, stream.source !== convertedSelectorList); } } ;// CONCATENATED MODULE: ./node_modules/.pnpm/@adguard+agtree@4.2.1/node_modules/@adguard/agtree/dist/converter/cosmetic/css.js /* * AGTree v4.2.1 (build date: Wed, 12 Aug 2026 01:31:02 GMT) * (c) 2026 Adguard Software Ltd. * Released under the MIT license * https://github.com/AdguardTeam/tsurlfilter/tree/master/packages/agtree#readme */ /** * @file CSS injection rule converter. */ /** * CSS injection rule converter class. * * @todo Implement `convertToUbo` and `convertToAbp`. */ class CssInjectionRuleConverter extends RuleConverterBase { /** * Converts a CSS injection rule to AdGuard format, if possible. * * @param rule Rule node to convert. * * @returns An object which follows the {@link NodeConversionResult} interface. Its `result` property contains * the array of converted rule nodes, and its `isConverted` flag indicates whether the original rule was converted. * If the rule was not converted, the result array will contain the original node with the same object reference. * * @throws If the rule is invalid or cannot be converted. */ static convertToAdg(rule) { const separator = rule.separator.value; let convertedSeparator = separator; const stream = new css_token_stream/* .CssTokenStream */.d(rule.body.selectorList.value); const convertedSelectorList = CssSelectorConverter.convertToAdg(stream); // Change the separator if the rule contains ExtendedCSS elements, // but do not force non-extended CSS separator if the rule does not contain any ExtendedCSS selectors, // because sometimes we use it to force executing ExtendedCSS library. if (stream.hasAnySelectorExtendedCssNodeStrict() || rule.body.remove) { convertedSeparator = rule.exception ? nodes/* .CosmeticRuleSeparator.AdgExtendedCssInjectionException */.p5.AdgExtendedCssInjectionException : nodes/* .CosmeticRuleSeparator.AdgExtendedCssInjection */.p5.AdgExtendedCssInjection; } else if (rule.syntax !== adblockers/* .AdblockSyntax.Adg */.YG.Adg) { // If the original rule syntax is not AdGuard, use the default separator // e.g. if the input rule is from uBO, we need to convert ## to #$#. convertedSeparator = rule.exception ? nodes/* .CosmeticRuleSeparator.AdgCssInjectionException */.p5.AdgCssInjectionException : nodes/* .CosmeticRuleSeparator.AdgCssInjection */.p5.AdgCssInjection; } // Check if the rule needs to be converted if (!(rule.syntax === adblockers/* .AdblockSyntax.Common */.YG.Common || rule.syntax === adblockers/* .AdblockSyntax.Adg */.YG.Adg) || separator !== convertedSeparator || convertedSelectorList.isConverted) { // TODO: Replace with custom clone method const ruleClone = clone(rule); ruleClone.syntax = adblockers/* .AdblockSyntax.Adg */.YG.Adg; ruleClone.separator.value = convertedSeparator; ruleClone.body.selectorList.value = convertedSelectorList.result; return (0,conversion_result/* .createNodeConversionResult */.k)([ruleClone], true); } // Otherwise, return the original rule return (0,conversion_result/* .createNodeConversionResult */.k)([rule], false); } } ;// CONCATENATED MODULE: ./node_modules/.pnpm/@adguard+agtree@4.2.1/node_modules/@adguard/agtree/dist/converter/cosmetic/element-hiding.js /* * AGTree v4.2.1 (build date: Wed, 12 Aug 2026 01:31:02 GMT) * (c) 2026 Adguard Software Ltd. * Released under the MIT license * https://github.com/AdguardTeam/tsurlfilter/tree/master/packages/agtree#readme */ /** * @file Element hiding rule converter. */ /** * Element hiding rule converter class. * * @todo Implement `convertToUbo` and `convertToAbp`. */ class ElementHidingRuleConverter extends RuleConverterBase { /** * Converts an element hiding rule to AdGuard format, if possible. * * @param rule Rule node to convert. * * @returns An object which follows the {@link NodeConversionResult} interface. Its `result` property contains * the array of converted rule nodes, and its `isConverted` flag indicates whether the original rule was converted. * If the rule was not converted, the result array will contain the original node with the same object reference. * * @throws If the rule is invalid or cannot be converted. */ static convertToAdg(rule) { const separator = rule.separator.value; let convertedSeparator = separator; const stream = new css_token_stream/* .CssTokenStream */.d(rule.body.selectorList.value); const convertedSelectorList = CssSelectorConverter.convertToAdg(stream); // Change the separator if the rule contains ExtendedCSS elements, // but do not force non-extended CSS separator if the rule does not contain any ExtendedCSS selectors, // because sometimes we use it to force executing ExtendedCSS library. if (stream.hasAnySelectorExtendedCssNodeStrict()) { convertedSeparator = rule.exception ? nodes/* .CosmeticRuleSeparator.ExtendedElementHidingException */.p5.ExtendedElementHidingException : nodes/* .CosmeticRuleSeparator.ExtendedElementHiding */.p5.ExtendedElementHiding; } // Check if the rule needs to be converted if (!(rule.syntax === adblockers/* .AdblockSyntax.Common */.YG.Common || rule.syntax === adblockers/* .AdblockSyntax.Adg */.YG.Adg) || separator !== convertedSeparator || convertedSelectorList.isConverted) { // TODO: Replace with custom clone method const ruleClone = clone(rule); ruleClone.syntax = adblockers/* .AdblockSyntax.Adg */.YG.Adg; ruleClone.separator.value = convertedSeparator; ruleClone.body.selectorList.value = convertedSelectorList.result; return (0,conversion_result/* .createNodeConversionResult */.k)([ruleClone], true); } // Otherwise, return the original rule return (0,conversion_result/* .createNodeConversionResult */.k)([rule], false); } } // EXTERNAL MODULE: ./node_modules/.pnpm/@adguard+agtree@4.2.1/node_modules/@adguard/agtree/dist/utils/type-guards.js var type_guards = __webpack_require__(64505); ;// CONCATENATED MODULE: ./node_modules/.pnpm/@adguard+agtree@4.2.1/node_modules/@adguard/agtree/dist/ast-utils/modifiers.js /* * AGTree v4.2.1 (build date: Wed, 12 Aug 2026 01:31:02 GMT) * (c) 2026 Adguard Software Ltd. * Released under the MIT license * https://github.com/AdguardTeam/tsurlfilter/tree/master/packages/agtree#readme */ /** * @file Utility functions for working with modifier nodes. */ /** * Creates a modifier node. * * @param name Name of the modifier. * @param value Value of the modifier. * @param exception Whether the modifier is an exception. * * @returns Modifier node. */ function createModifierNode(name, value = undefined, exception = false) { const result = { type: 'Modifier', exception, name: { type: 'Value', value: name, }, }; if (!(0,type_guards/* .isUndefined */.b0)(value)) { result.value = { type: 'Value', value, }; } return result; } /** * Creates a modifier list node. * * @param modifiers Modifiers to put in the list (optional, defaults to an empty list). * * @returns Modifier list node. */ function createModifierListNode(modifiers = []) { const result = { type: 'ModifierList', // We need to clone the modifiers to avoid side effects children: modifiers.length ? clone(modifiers) : [], }; return result; } ;// CONCATENATED MODULE: ./node_modules/.pnpm/@adguard+agtree@4.2.1/node_modules/@adguard/agtree/dist/ast-utils/network-rules.js /* * AGTree v4.2.1 (build date: Wed, 12 Aug 2026 01:31:02 GMT) * (c) 2026 Adguard Software Ltd. * Released under the MIT license * https://github.com/AdguardTeam/tsurlfilter/tree/master/packages/agtree#readme */ /** * @file Utility functions for working with network rule nodes. */ /** * Creates a network rule node. * * @param pattern Rule pattern. * @param modifiers Rule modifiers (optional, default: undefined). * @param exception Exception rule flag (optional, default: false). * @param syntax Adblock syntax (optional, default: Common). * * @returns Network rule node. */ function createNetworkRuleNode(pattern, modifiers = undefined, exception = false, syntax = adblockers/* .AdblockSyntax.Common */.YG.Common) { const result = { category: nodes/* .RuleCategory.Network */.$O.Network, type: nodes/* .NetworkRuleType.NetworkRule */.vY.NetworkRule, syntax, exception, pattern: { type: 'Value', value: pattern, }, }; if (!(0,type_guards/* .isUndefined */.b0)(modifiers)) { result.modifiers = clone(modifiers); } return result; } // EXTERNAL MODULE: ./node_modules/.pnpm/@adguard+agtree@4.2.1/node_modules/@adguard/agtree/dist/common/ubo-html-filtering-body-common.js var ubo_html_filtering_body_common = __webpack_require__(76466); // EXTERNAL MODULE: ./node_modules/.pnpm/@adguard+agtree@4.2.1/node_modules/@adguard/agtree/dist/parser/cosmetic/html-filtering-body/ubo-html-filtering-body-parser.js var ubo_html_filtering_body_parser = __webpack_require__(91090); // EXTERNAL MODULE: ./node_modules/.pnpm/@adguard+agtree@4.2.1/node_modules/@adguard/agtree/dist/utils/regexp.js var regexp = __webpack_require__(64539); ;// CONCATENATED MODULE: ./node_modules/.pnpm/@adguard+agtree@4.2.1/node_modules/@adguard/agtree/dist/converter/cosmetic/header-removal.js /* * AGTree v4.2.1 (build date: Wed, 12 Aug 2026 01:31:02 GMT) * (c) 2026 Adguard Software Ltd. * Released under the MIT license * https://github.com/AdguardTeam/tsurlfilter/tree/master/packages/agtree#readme */ /** * @file Converter for request header removal rules. */ const ADG_REMOVEHEADER_MODIFIER = 'removeheader'; const header_removal_ERROR_MESSAGES = { MULTIPLE_DOMAINS_NOT_SUPPORTED: 'Multiple domains are not supported yet', }; /** * Converter for request header removal rules. * * @todo Implement `convertToUbo` (ABP currently doesn't support header removal rules). */ class HeaderRemovalRuleConverter extends RuleConverterBase { /** * Converts a header removal rule to AdGuard syntax, if possible. * * @param rule Rule node to convert. * * @returns An object which follows the {@link NodeConversionResult} interface. Its `result` property contains * the array of converted rule nodes, and its `isConverted` flag indicates whether the original rule was converted. * If the rule was not converted, the result array will contain the original node with the same object reference. * * @throws If the rule is invalid or cannot be converted. * * @example * If the input rule is: * ```adblock * example.com##^responseheader(header-name) * ``` * The output will be: * ```adblock * ||example.com^$removeheader=header-name * ``` */ static convertToAdg(rule) { // TODO: Add support for ABP syntax once it starts supporting header removal rules // Leave the rule as is if it's not a header removal rule if (rule.category !== nodes/* .RuleCategory.Cosmetic */.$O.Cosmetic || rule.type !== nodes/* .CosmeticRuleType.HtmlFilteringRule */.k9.HtmlFilteringRule) { return (0,conversion_result/* .createNodeConversionResult */.k)([rule], false); } // Handle case when body is raw value string. // If so, parse it first as we need to work with AST nodes. let body = null; if (rule.body.type === 'Value') { body = ubo_html_filtering_body_parser/* .UboHtmlFilteringBodyParser.parseResponseHeaderRule */.V.parseResponseHeaderRule(rule.body.value, { isLocIncluded: false, parseHtmlFilteringRuleBodies: true, }); } else { body = rule.body; } // Check if the rule body is a uBO responseheader(...) function if (!body || !(0,ubo_html_filtering_body_common/* .isUboResponseHeaderRemovalRuleBody */.l)(body)) { return (0,conversion_result/* .createNodeConversionResult */.k)([rule], false); } // Length of AST nodes, types of nodes, non-null argument // check are already done in `isUboResponseHeaderRemovalRuleBody()` const { selectorList } = body; const complexSelector = selectorList.children[0]; const pseudoClassSelector = complexSelector.children[0]; const headerName = pseudoClassSelector.argument.value; // Prepare network rule pattern const pattern = []; if (rule.domains.children.length === 1) { // If the rule has only one domain, we can use a simple network rule pattern: // ||single-domain-from-the-rule^ pattern.push(regexp/* .ADBLOCK_URL_START */.Cg, rule.domains.children[0].value, regexp/* .ADBLOCK_URL_SEPARATOR */.Fx); } else if (rule.domains.children.length > 1) { // TODO: Add support for multiple domains, for example: // example.com,example.org,example.net##^responseheader(header-name) // We should consider allowing $domain with $removeheader modifier, // for example: // $removeheader=header-name,domain=example.com|example.org|example.net throw new RuleConversionError(header_removal_ERROR_MESSAGES.MULTIPLE_DOMAINS_NOT_SUPPORTED); } // Prepare network rule modifiers const modifiers = createModifierListNode(); modifiers.children.push(createModifierNode(ADG_REMOVEHEADER_MODIFIER, headerName)); // Construct the network rule return (0,conversion_result/* .createNodeConversionResult */.k)([ createNetworkRuleNode(pattern.join(constants/* .EMPTY */.wg), modifiers, // Copy the exception flag rule.exception, adblockers/* .AdblockSyntax.Adg */.YG.Adg), ], true); } } ;// CONCATENATED MODULE: ./node_modules/.pnpm/@adguard+agtree@4.2.1/node_modules/@adguard/agtree/dist/ast-utils/clone.js /* * AGTree v4.2.1 (build date: Wed, 12 Aug 2026 01:31:02 GMT) * (c) 2026 Adguard Software Ltd. * Released under the MIT license * https://github.com/AdguardTeam/tsurlfilter/tree/master/packages/agtree#readme */ /** * @file Custom clone functions for AST nodes, this is probably the most efficient way to clone AST nodes. * * @todo Maybe move them to parser classes as 'clone' methods. */ /** * Clones a scriptlet rule node. * * @param node Node to clone. * * @returns Cloned node. */ function cloneScriptletRuleNode(node) { return { type: node.type, children: node.children.map((child) => ((0,type_guards/* .isNull */.kZ)(child) ? null : { ...child })), }; } /** * Clones a domain list node. * * @param node Node to clone. * * @returns Cloned node. */ function cloneDomainListNode(node) { return { type: node.type, separator: node.separator, children: node.children.map((domain) => ({ ...domain })), }; } /** * Clones a modifier list node. * * @param node Node to clone. * * @returns Cloned node. */ function cloneModifierListNode(node) { return { type: node.type, children: node.children.map((modifier) => { const res = { type: modifier.type, exception: modifier.exception, name: { ...modifier.name }, }; if (modifier.value) { res.value = { ...modifier.value }; } return res; }), }; } // EXTERNAL MODULE: ./node_modules/.pnpm/@adguard+agtree@4.2.1/node_modules/@adguard/agtree/dist/generator/cosmetic/html-filtering-body/adg-html-filtering-body-generator.js var adg_html_filtering_body_generator = __webpack_require__(60646); // EXTERNAL MODULE: ./node_modules/.pnpm/@adguard+agtree@4.2.1/node_modules/@adguard/agtree/dist/generator/cosmetic/html-filtering-body/ubo-html-filtering-body-generator.js var ubo_html_filtering_body_generator = __webpack_require__(63836); // EXTERNAL MODULE: ./node_modules/.pnpm/@adguard+agtree@4.2.1/node_modules/@adguard/agtree/dist/parser/cosmetic/html-filtering-body/adg-html-filtering-body-parser.js var adg_html_filtering_body_parser = __webpack_require__(55576); ;// CONCATENATED MODULE: ./node_modules/.pnpm/@adguard+agtree@4.2.1/node_modules/@adguard/agtree/dist/converter/cosmetic/html.js /* * AGTree v4.2.1 (build date: Wed, 12 Aug 2026 01:31:02 GMT) * (c) 2026 Adguard Software Ltd. * Released under the MIT license * https://github.com/AdguardTeam/tsurlfilter/tree/master/packages/agtree#readme */ /** * @file HTML filtering rule converter. */ /** * From the AdGuard docs: * Specifies the maximum length for content of HTML element. If this parameter is * set and the content length exceeds the value, a rule does not apply to the element. * If this parameter is not specified, the max-length is considered to be 8192 (8 KB). * When converting from other formats, we set the max-length to 262144 (256 KB). * * @see {@link https://adguard.com/kb/general/ad-filtering/create-own-filters/#html-filtering-rules} */ const ADG_HTML_DEFAULT_MAX_LENGTH = 8192; const ADG_HTML_CONVERSION_MAX_LENGTH = ADG_HTML_DEFAULT_MAX_LENGTH * 32; /** * Supported special pseudo-classes from uBlock. * * Note: If new pseudo-classes are added here, ensure to update * the set and logic in the converter methods accordingly. */ const UboPseudoClasses = { HasText: 'has-text', MinTextLength: 'min-text-length', }; /** * Supported special attribute selectors from AdGuard. * * Note: If new pseudo-classes are added here, ensure to update * the set and logic in the converter methods accordingly. */ const AdgAttributeSelectors = { MaxLength: 'max-length', MinLength: 'min-length', TagContent: 'tag-content', Wildcard: 'wildcard', }; /** * Supported special pseudo-classes from AdGuard. * * Note: If new pseudo-classes are added here, ensure to update * the set and logic in the converter methods accordingly. */ const AdgPseudoClasses = { Contains: 'contains', }; /** * Set of {@link UboPseudoClasses}. */ const SUPPORTED_UBO_PSEUDO_CLASSES = new Set([ UboPseudoClasses.HasText, UboPseudoClasses.MinTextLength, ]); /** * Set of {@link AdgAttributeSelectors}. */ const SUPPORTED_ADG_ATTRIBUTE_SELECTORS = new Set([ AdgAttributeSelectors.MaxLength, AdgAttributeSelectors.MinLength, AdgAttributeSelectors.TagContent, AdgAttributeSelectors.Wildcard, ]); /** * Set of {@link AdgPseudoClasses}. */ const SUPPORTED_ADG_PSEUDO_CLASSES = new Set([ AdgPseudoClasses.Contains, ]); /** * Error messages used in HTML filtering rule conversion. */ /* eslint-disable max-len */ const html_ERROR_MESSAGES = { ABP_NOT_SUPPORTED: 'Invalid rule, ABP does not support HTML filtering rules', INVALID_RULE: 'Invalid HTML filtering rule: %s', MIXED_SYNTAX_ADG_UBO: 'Mixed AdGuard and uBlock syntax', EMPTY_SELECTOR_LIST: 'Selector list of HTML filtering rule must not be empty', EMPTY_COMPLEX_SELECTOR: 'Complex selector of selector list must not be empty', INVALID_SELECTOR_COMBINATOR: "Invalid selector combinator '%s' used between selectors", UNKNOWN_SELECTOR_TYPE: "Unknown selector type '%s' found during conversion", SPECIAL_ATTRIBUTE_SELECTOR_OPERATOR_INVALID: "Special attribute selector '%s' has invalid operator '%s'", SPECIAL_ATTRIBUTE_SELECTOR_FLAG_NOT_SUPPORTED: "Special attribute selector '%s' does not support flags", SPECIAL_ATTRIBUTE_SELECTOR_VALUE_REQUIRED: "Special attribute selector '%s' requires a value", SPECIAL_ATTRIBUTE_SELECTOR_VALUE_INT: "Value of special attribute selector '%s' must be an integer, got '%s'", SPECIAL_ATTRIBUTE_SELECTOR_VALUE_POSITIVE: "Value of special attribute selector '%s' must be a positive integer, got '%s'", SPECIAL_ATTRIBUTE_SELECTOR_NOT_SUPPORTED: "Special attribute selector '%s' is not supported in conversion", SPECIAL_PSEUDO_CLASS_SELECTOR_ARGUMENT_REQUIRED: "Special pseudo-class selector '%s' requires an argument", SPECIAL_PSEUDO_CLASS_SELECTOR_ARGUMENT_INT: "Argument of special pseudo-class selector '%s' must be an integer, got '%s'", SPECIAL_PSEUDO_CLASS_SELECTOR_ARGUMENT_POSITIVE: "Argument of special pseudo-class selector '%s' must be a positive integer, got '%s'", SPECIAL_PSEUDO_CLASS_SELECTOR_NOT_SUPPORTED: "Special pseudo-class selector '%s' is not supported in conversion", }; /** * HTML filtering rule converter class. * * @todo Implement `convertToUbo` (ABP currently doesn't support HTML filtering rules). */ class HtmlRuleConverter extends RuleConverterBase { /** * Converts a HTML rule to AdGuard syntax, if possible. * Also can be used to convert AdGuard rules to AdGuard syntax to validate them. * * @param rule Rule node to convert. * * @returns An object which follows the {@link NodeConversionResult} interface. Its `result` property contains * the array of converted rule nodes, and its `isConverted` flag indicates whether the original rule was converted. * If the rule was not converted, the result array will contain the original node with the same object reference. * * @throws If the rule is invalid or cannot be converted. */ static convertToAdg(rule) { let parser; let onSpecialAttributeSelector; let onSpecialPseudoClassSelector; let isConverted = false; if (rule.syntax === adblockers/* .AdblockSyntax.Adg */.YG.Adg) { parser = adg_html_filtering_body_parser/* .AdgHtmlFilteringBodyParser */.h; onSpecialAttributeSelector = (name, value) => { /** * Mark rule as converted in ADG -> ADG conversion only if * special attribute selectors are present in the rule body, * because they are deprecated and will be removed soon, * so we convert them to pseudo-class selectors. */ isConverted = true; return HtmlRuleConverter.convertSpecialAttributeSelectorAdgToAdg(name, value); }; onSpecialPseudoClassSelector = HtmlRuleConverter.convertSpecialPseudoClassSelectorAdgToAdg; } else if (rule.syntax === adblockers/* .AdblockSyntax.Ubo */.YG.Ubo) { /** * Always mark rule as converted in UBO -> ADG conversion. */ isConverted = true; parser = ubo_html_filtering_body_parser/* .UboHtmlFilteringBodyParser */.V; onSpecialAttributeSelector = HtmlRuleConverter.convertSpecialAttributeSelectorUboToAdg; onSpecialPseudoClassSelector = HtmlRuleConverter.convertSpecialPseudoClassSelectorUboToAdg; } else { throw new RuleConversionError(html_ERROR_MESSAGES.ABP_NOT_SUPPORTED); } // Convert body const convertedBody = HtmlRuleConverter.convertBody(rule.body, parser, adg_html_filtering_body_generator/* .AdgHtmlFilteringBodyGenerator */.$, onSpecialAttributeSelector, onSpecialPseudoClassSelector, rule.syntax === adblockers/* .AdblockSyntax.Adg */.YG.Adg); if (!isConverted) { return (0,conversion_result/* .createNodeConversionResult */.k)([rule], false); } return (0,conversion_result/* .createNodeConversionResult */.k)([{ category: nodes/* .RuleCategory.Cosmetic */.$O.Cosmetic, type: nodes/* .CosmeticRuleType.HtmlFilteringRule */.k9.HtmlFilteringRule, syntax: adblockers/* .AdblockSyntax.Adg */.YG.Adg, exception: rule.exception, domains: cloneDomainListNode(rule.domains), // Convert the separator based on the exception status separator: { type: 'Value', value: rule.exception ? nodes/* .CosmeticRuleSeparator.AdgHtmlFilteringException */.p5.AdgHtmlFilteringException : nodes/* .CosmeticRuleSeparator.AdgHtmlFiltering */.p5.AdgHtmlFiltering, }, body: convertedBody, }], true); } /** * Converts a HTML rule to uBlock syntax, if possible. * Also can be used to convert uBlock rules to uBlock syntax to validate them. * * @param rule Rule node to convert. * * @returns An object which follows the {@link NodeConversionResult} interface. Its `result` property contains * the array of converted rule nodes, and its `isConverted` flag indicates whether the original rule was converted. * If the rule was not converted, the result array will contain the original node with the same object reference. * * @throws Error if the rule is invalid or cannot be converted. */ static convertToUbo(rule) { // Ignore uBlock rules if (rule.syntax === adblockers/* .AdblockSyntax.Ubo */.YG.Ubo) { return (0,conversion_result/* .createNodeConversionResult */.k)([rule], false); } if (rule.syntax === adblockers/* .AdblockSyntax.Abp */.YG.Abp) { throw new RuleConversionError(html_ERROR_MESSAGES.ABP_NOT_SUPPORTED); } // Convert body const convertedBody = HtmlRuleConverter.convertBody(rule.body, adg_html_filtering_body_parser/* .AdgHtmlFilteringBodyParser */.h, ubo_html_filtering_body_generator/* .UboHtmlFilteringBodyGenerator */.b, HtmlRuleConverter.convertSpecialAttributeSelectorAdgToUbo, HtmlRuleConverter.convertSpecialPseudoClassSelectorAdgToUbo); return (0,conversion_result/* .createNodeConversionResult */.k)([{ category: nodes/* .RuleCategory.Cosmetic */.$O.Cosmetic, type: nodes/* .CosmeticRuleType.HtmlFilteringRule */.k9.HtmlFilteringRule, syntax: adblockers/* .AdblockSyntax.Ubo */.YG.Ubo, exception: rule.exception, domains: cloneDomainListNode(rule.domains), separator: { type: 'Value', value: rule.exception ? nodes/* .CosmeticRuleSeparator.ElementHidingException */.p5.ElementHidingException : nodes/* .CosmeticRuleSeparator.ElementHiding */.p5.ElementHiding, }, body: convertedBody, }], true); } /** * Handles special attribute selectors during AdGuard to AdGuard conversion: * - `[tag-content="content"]` -> `:contains(content)` * direct conversion, no changes to value * - `[wildcard="*content*"]` -> `:contains(/*.content*./s)` * convert search pattern to regular expression * - `[min-length="min"]` -> `:contains(/^(?=.{min,}$).*\/s)` * converts to a length-matching regular expression. * - `[max-length="max"]` -> `:contains(/^(?=.{0,max}$).*\/s)` * converts to a length-matching regular expression. * * Note: This attribute selector to pseudo-class selector conversion * is needed because AdGuard special attribute selectors are going * to be deprecated and removed soon. * * @param name Name of the special attribute selector. * @param value Value of the special attribute selector. * * @returns A {@link SimpleSelector} to add to the current complex selector. */ static convertSpecialAttributeSelectorAdgToAdg(name, value) { switch (name) { // `[tag-content="content"]` -> `:contains(content)` // direct conversion, no changes to value case AdgAttributeSelectors.TagContent: { return HtmlRuleConverter.getPseudoClassSelectorNode(AdgPseudoClasses.Contains, value); } // `[wildcard="*content*"] -> `:contains(/*.content*./s)` // convert search pattern to regular expression case AdgAttributeSelectors.Wildcard: { return HtmlRuleConverter.getPseudoClassSelectorNode(AdgPseudoClasses.Contains, regexp/* .RegExpUtils.globToRegExp */.Lp.globToRegExp(value)); } // `[min-length="min"]` -> `:contains(/^(?=.{min,}$).*\/s)` // `[max-length="max"]` -> `:contains(/^(?=.{0,max}$).*\/s)` // converts to a length-matching regular expression case AdgAttributeSelectors.MinLength: case AdgAttributeSelectors.MaxLength: { // Validate length value HtmlRuleConverter.assertValidLengthValue(name, value, html_ERROR_MESSAGES.SPECIAL_ATTRIBUTE_SELECTOR_VALUE_INT, html_ERROR_MESSAGES.SPECIAL_ATTRIBUTE_SELECTOR_VALUE_POSITIVE); // It's safe to cast to number here after validation const length = Number(value); let min = null; let max = null; if (name === AdgAttributeSelectors.MinLength) { min = length; } else { max = length; } return HtmlRuleConverter.getPseudoClassSelectorNode(AdgPseudoClasses.Contains, regexp/* .RegExpUtils.getLengthRegexp */.Lp.getLengthRegexp(min, max)); } // This line is unreachable due to exhausted cases, but we keep it to satisfy TS default: { throw new RuleConversionError((0,sprintf.sprintf)(html_ERROR_MESSAGES.SPECIAL_ATTRIBUTE_SELECTOR_NOT_SUPPORTED, name)); } } } /** * Since special pseudo-class selectors do not need conversion * in AdGuard to AdGuard conversion, we simply return `true` to keep them as-is. * * @param name Name of the special pseudo-class selector. * * @returns `true` to keep the special pseudo-class selector as-is. * * @throws Rule conversion error for mixed syntax. */ static convertSpecialPseudoClassSelectorAdgToAdg(name) { if (SUPPORTED_UBO_PSEUDO_CLASSES.has(name)) { throw new RuleConversionError((0,sprintf.sprintf)(html_ERROR_MESSAGES.INVALID_RULE, html_ERROR_MESSAGES.MIXED_SYNTAX_ADG_UBO)); } return true; } /** * Since special attribute selectors only AdGuard-specific, * we should never encounter them in uBlock rules. * * @throws Rule conversion error for mixed syntax. */ static convertSpecialAttributeSelectorUboToAdg() { throw new RuleConversionError((0,sprintf.sprintf)(html_ERROR_MESSAGES.INVALID_RULE, html_ERROR_MESSAGES.MIXED_SYNTAX_ADG_UBO)); } /** * Handles special pseudo-class selectors during uBlock to AdGuard conversion: * - `:has-text(text)` -> `:contains(text)` * direct conversion, no changes to argument * - `:min-text-length(min)` -> `:contains(/^(?=.{min,MAX_CONVERSION_DEFAULT}$).*\/s)` * converts to a length-matching regular expression. * * @param name Name of the special pseudo-class selector. * @param argument Argument of the special pseudo-class selector. * * @returns A {@link SimpleSelector} to add to the current complex selector. * * @throws If AdGuard-specific pseudo-class selector is found in uBlock rule. */ static convertSpecialPseudoClassSelectorUboToAdg(name, argument) { switch (name) { // `:has-text(text)` -> `:contains(text)` // direct conversion, no changes to argument case UboPseudoClasses.HasText: { return HtmlRuleConverter.getPseudoClassSelectorNode(AdgPseudoClasses.Contains, argument); } // `:min-text-length(min)` -> `:contains(/^(?=.{min,MAX_CONVERSION_DEFAULT}$).*\/s)` // converts to a length-matching regular expression case UboPseudoClasses.MinTextLength: { // Validate length value HtmlRuleConverter.assertValidLengthValue(name, argument, html_ERROR_MESSAGES.SPECIAL_PSEUDO_CLASS_SELECTOR_ARGUMENT_INT, html_ERROR_MESSAGES.SPECIAL_PSEUDO_CLASS_SELECTOR_ARGUMENT_POSITIVE); // It's safe to cast to number here after validation const minLength = Number(argument); return HtmlRuleConverter.getPseudoClassSelectorNode(AdgPseudoClasses.Contains, regexp/* .RegExpUtils.getLengthRegexp */.Lp.getLengthRegexp(minLength, ADG_HTML_CONVERSION_MAX_LENGTH)); } // Throw an error if the AdGuard-specific pseudo-class selector found in uBlock rule case AdgPseudoClasses.Contains: { throw new RuleConversionError((0,sprintf.sprintf)(html_ERROR_MESSAGES.INVALID_RULE, html_ERROR_MESSAGES.MIXED_SYNTAX_ADG_UBO)); } // This line is unreachable due to exhausted cases, but we keep it to satisfy TS default: { throw new RuleConversionError((0,sprintf.sprintf)(html_ERROR_MESSAGES.SPECIAL_PSEUDO_CLASS_SELECTOR_NOT_SUPPORTED, name)); } } } /** * Handles special attribute selectors during AdGuard to uBlock conversion: * - `[tag-content="content"]` -> `:has-text(content)` * direct conversion, no changes to value * - `[wildcard="*content*"]` -> `:has-text(/*.content*./s)` * convert search pattern to regular expression * - `[min-length="min"]` -> `:min-text-length(min)` * direct conversion, no changes to value * - `[max-length]` is skipped. * * @param name Name of the special attribute selector. * @param value Value of the special attribute selector. * * @returns A {@link SimpleSelector} to add to the current complex selector, or `false` to skip it. */ static convertSpecialAttributeSelectorAdgToUbo(name, value) { switch (name) { // `[tag-content="content"]` -> `:has-text(content)` // direct conversion, no changes to value case AdgAttributeSelectors.TagContent: { return HtmlRuleConverter.getPseudoClassSelectorNode(UboPseudoClasses.HasText, value); } // `[wildcard="*content*"] -> `:has-text(/*.content*./s)` // convert search pattern to regular expression case AdgAttributeSelectors.Wildcard: { return HtmlRuleConverter.getPseudoClassSelectorNode(UboPseudoClasses.HasText, regexp/* .RegExpUtils.globToRegExp */.Lp.globToRegExp(value)); } // `[min-length="min"]` -> `:min-text-length(min)` // direct conversion, no changes to value case AdgAttributeSelectors.MinLength: { // Validate length value HtmlRuleConverter.assertValidLengthValue(name, value, html_ERROR_MESSAGES.SPECIAL_ATTRIBUTE_SELECTOR_VALUE_INT, html_ERROR_MESSAGES.SPECIAL_ATTRIBUTE_SELECTOR_VALUE_POSITIVE); return HtmlRuleConverter.getPseudoClassSelectorNode(UboPseudoClasses.MinTextLength, value); } // `[max-length]` is skipped case AdgAttributeSelectors.MaxLength: { return false; } // This line is unreachable due to exhausted cases, but we keep it to satisfy TS default: { throw new RuleConversionError((0,sprintf.sprintf)(html_ERROR_MESSAGES.SPECIAL_ATTRIBUTE_SELECTOR_NOT_SUPPORTED, name)); } } } /** * Handles special pseudo-class selectors during AdGuard to uBlock conversion: * - `:contains(text)` -> `:has-text(text)` * direct conversion, no changes to argument. * * @param name Name of the special pseudo-class selector. * @param argument Argument of the special pseudo-class selector. * * @returns A {@link SimpleSelector} to add to the current complex selector. * * @throws If uBlock-specific pseudo-class selector is found in AdGuard rule. */ static convertSpecialPseudoClassSelectorAdgToUbo(name, argument) { switch (name) { // `:contains(text)` -> `:has-text(text)` // direct conversion, no changes to argument case AdgPseudoClasses.Contains: { return HtmlRuleConverter.getPseudoClassSelectorNode(UboPseudoClasses.HasText, argument); } // Throw an error if the uBlock-specific pseudo-class selector found in AdGuard rule case UboPseudoClasses.HasText: case UboPseudoClasses.MinTextLength: { throw new RuleConversionError((0,sprintf.sprintf)(html_ERROR_MESSAGES.INVALID_RULE, html_ERROR_MESSAGES.MIXED_SYNTAX_ADG_UBO)); } // This line is unreachable due to exhausted cases, but we keep it to satisfy TS default: { throw new RuleConversionError((0,sprintf.sprintf)(html_ERROR_MESSAGES.SPECIAL_PSEUDO_CLASS_SELECTOR_NOT_SUPPORTED, name)); } } } /** * Pre-scans a complex selector's child selectors * for {@link AdgAttributeSelectors.MinLength} * and {@link AdgAttributeSelectors.MaxLength} attribute selectors. * * Resolves duplicates to the most *restrictive* value: * - for multiple `[min-length]` selectors, the largest value is selected; * - for multiple `[max-length]` selectors, the smallest value is selected. * * Logs a warning when duplicate length selectors are found. * * @param selectors Child selectors of a complex selector to scan. * * @returns Resolved length constraints, * or `null` if no length selectors were found. */ static collectLengthConstraints(selectors) { const minValues = []; const maxValues = []; for (let i = 0; i < selectors.length; i += 1) { const selector = selectors[i]; if (selector.type !== 'AttributeSelector') { continue; } const { value: name } = selector.name; if (name !== AdgAttributeSelectors.MinLength && name !== AdgAttributeSelectors.MaxLength) { continue; } if (!('value' in selector) || selector.value.value === constants/* .EMPTY */.wg) { continue; } const { value } = selector.value; HtmlRuleConverter.assertValidLengthValue(name, value, html_ERROR_MESSAGES.SPECIAL_ATTRIBUTE_SELECTOR_VALUE_INT, html_ERROR_MESSAGES.SPECIAL_ATTRIBUTE_SELECTOR_VALUE_POSITIVE); if (name === AdgAttributeSelectors.MinLength) { minValues.push(Number(value)); } else { maxValues.push(Number(value)); } } if (minValues.length === 0 && maxValues.length === 0) { return null; } let min = null; let max = null; if (minValues.length > 1) { min = Math.max(...minValues); // eslint-disable-next-line no-console console.warn(`Multiple [min-length] selectors found among: [${minValues.join(', ')}]. Selected largest: ${min}.`); } else if (minValues.length === 1) { [min] = minValues; } if (maxValues.length > 1) { max = Math.min(...maxValues); // eslint-disable-next-line no-console console.warn(`Multiple [max-length] selectors found among: [${maxValues.join(', ')}]. Selected smallest: ${max}.`); } else if (maxValues.length === 1) { [max] = maxValues; } return { min, max }; } /** * Converts a HTML filtering rule body by handling special simple selectors via callbacks. * Special simple selectors are skipped in the converted selector list and should be handled from callee. * * @param body HTML filtering rule body to convert. * @param parser HTML filtering rule body parser used for parsing raw value bodies. * @param generator HTML filtering rule body generator used for generating raw value bodies. * @param onSpecialAttributeSelector Callback invoked when a special attribute selector is found. * @param onSpecialPseudoClassSelector Callback invoked when a special pseudo-class selector is found. * @param shouldMergeLengthSelectors If true, `[min-length]` and `[max-length]` attribute * selectors within the same complex selector are merged into a single `:contains()` pseudo-class. * Defaults to `false`. * * @returns Converted selector list without special simple selectors. */ static convertBody(body, parser, generator, onSpecialAttributeSelector, onSpecialPseudoClassSelector, shouldMergeLengthSelectors = false) { // Handle case when body is raw value string. // If so, parse it first as we need to work with AST nodes. let processedBody; if (body.type === 'Value') { processedBody = parser.parse(body.value, { isLocIncluded: false, parseHtmlFilteringRuleBodies: true, }); } else { processedBody = body; } const { children: complexSelectors } = processedBody.selectorList; // Selector list node must not be empty HtmlRuleConverter.assertNotEmpty(complexSelectors, html_ERROR_MESSAGES.EMPTY_SELECTOR_LIST); // Convert each complex selector const convertedComplexSelectors = []; for (let i = 0; i < complexSelectors.length; i += 1) { const { children: selectors } = complexSelectors[i]; // Complex selector node must not be empty HtmlRuleConverter.assertNotEmpty(selectors, html_ERROR_MESSAGES.EMPTY_COMPLEX_SELECTOR); // Pre-scan for [min-length] / [max-length] constraints to merge them into one :contains() const lengthConstraints = shouldMergeLengthSelectors ? HtmlRuleConverter.collectLengthConstraints(selectors) : null; let lengthContainsEmitted = false; // Convert each selector const convertedSelectors = []; for (let j = 0; j < selectors.length; j += 1) { const selector = selectors[j]; switch (selector.type) { case 'SelectorCombinator': { // Throw if selector combinator used incorrectly if ( // If first selector in the complex selector (`> div`) j === 0 // If the previous selector is also a combinator (`div > + span`) || j === selectors.length - 1 // If the last selector in the complex selector (`div +`) || (j > 0 && selectors[j - 1].type === 'SelectorCombinator')) { throw new RuleConversionError((0,sprintf.sprintf)(html_ERROR_MESSAGES.INVALID_RULE, (0,sprintf.sprintf)(html_ERROR_MESSAGES.INVALID_SELECTOR_COMBINATOR, selector.value))); } break; } case 'AttributeSelector': { // Not a special attribute selector - clone as-is after the switch if (!SUPPORTED_ADG_ATTRIBUTE_SELECTORS.has(selector.name.value)) { break; } // Throw an error if value is missing if (!('value' in selector) || selector.value.value === constants/* .EMPTY */.wg) { throw new RuleConversionError((0,sprintf.sprintf)(html_ERROR_MESSAGES.SPECIAL_ATTRIBUTE_SELECTOR_VALUE_REQUIRED, selector.name.value)); } // Throw an error if operator is not '=' if (selector.operator.value !== constants/* .EQUALS */.UT) { throw new RuleConversionError((0,sprintf.sprintf)(html_ERROR_MESSAGES.SPECIAL_ATTRIBUTE_SELECTOR_OPERATOR_INVALID, selector.name.value, selector.operator.value)); } // Throw an error if flag is specified if (selector.flag) { throw new RuleConversionError((0,sprintf.sprintf)(html_ERROR_MESSAGES.SPECIAL_ATTRIBUTE_SELECTOR_FLAG_NOT_SUPPORTED, selector.name.value)); } const name = selector.name.value; const { value } = selector.value; // Merge [min-length] and [max-length] into a single :contains() (ADG→ADG) if (lengthConstraints !== null && (name === AdgAttributeSelectors.MinLength || name === AdgAttributeSelectors.MaxLength)) { if (!lengthContainsEmitted) { // Invoke the callback once to trigger its side effects // (e.g. the isConverted flag in convertToAdg), but discard // the individual :contains() it returns — we emit the // merged one instead. onSpecialAttributeSelector(name, value); convertedSelectors.push(HtmlRuleConverter.getPseudoClassSelectorNode(AdgPseudoClasses.Contains, regexp/* .RegExpUtils.getLengthRegexp */.Lp.getLengthRegexp(lengthConstraints.min, lengthConstraints.max))); lengthContainsEmitted = true; } continue; } // Invoke callback and: // - add returned simple selector if it's not boolean // - skip adding if returned value is false // - keep original simple selector if returned value is true const result = onSpecialAttributeSelector(name, value); if (typeof result !== 'boolean') { convertedSelectors.push(result); continue; } else if (result === false) { continue; } break; } case 'PseudoClassSelector': { // Not a special pseudo-class selector - clone as-is after the switch if (!SUPPORTED_ADG_PSEUDO_CLASSES.has(selector.name.value) && !SUPPORTED_UBO_PSEUDO_CLASSES.has(selector.name.value)) { break; } // Throw an error if argument is missing if (!selector.argument || selector.argument.value === constants/* .EMPTY */.wg) { throw new RuleConversionError((0,sprintf.sprintf)(html_ERROR_MESSAGES.SPECIAL_PSEUDO_CLASS_SELECTOR_ARGUMENT_REQUIRED, selector.name.value)); } const name = selector.name.value; const argument = selector.argument.value; // Invoke callback and: // - add returned simple selector if it's not boolean // - skip adding if returned value is false // - keep original simple selector if returned value is true const result = onSpecialPseudoClassSelector(name, argument); if (typeof result !== 'boolean') { convertedSelectors.push(result); continue; } else if (result === false) { continue; } break; } } // Clone selector if previous conditions are not met convertedSelectors.push(HtmlRuleConverter.cloneSelector(selector)); } convertedComplexSelectors.push({ type: 'ComplexSelector', children: convertedSelectors, }); } let convertedBody = { type: 'HtmlFilteringRuleBody', selectorList: { type: 'SelectorList', children: convertedComplexSelectors, }, }; // Convert back to Value if the original body was Value if (body.type === 'Value') { convertedBody = { type: 'Value', value: generator.generate(convertedBody), }; } return convertedBody; } /** * Clones a simple selector or selector combinator node. * * @param selector Simple selector or selector combinator node to clone. * * @returns Cloned simple selector or selector combinator node. */ static cloneSelector(selector) { const { type } = selector; switch (type) { case 'TypeSelector': case 'IdSelector': case 'ClassSelector': return { type: selector.type, value: selector.value, }; case 'SelectorCombinator': return { type: selector.type, value: selector.value, }; case 'AttributeSelector': { const attributeSelectorClone = { type: selector.type, name: { type: selector.name.type, value: selector.name.value, }, }; if ('value' in selector && selector.value) { attributeSelectorClone.operator = { type: selector.operator.type, value: selector.operator.value, }; attributeSelectorClone.value = { type: selector.value.type, value: selector.value.value, }; if (selector.flag) { attributeSelectorClone.flag = { type: selector.flag.type, value: selector.flag.value, }; } } return attributeSelectorClone; } case 'PseudoClassSelector': { const pseudoClassSelectorClone = { type: selector.type, name: { type: selector.name.type, value: selector.name.value, }, }; if (selector.argument) { pseudoClassSelectorClone.argument = { type: selector.argument.type, value: selector.argument.value, }; } return pseudoClassSelectorClone; } default: { throw new RuleConversionError((0,sprintf.sprintf)(html_ERROR_MESSAGES.INVALID_RULE, (0,sprintf.sprintf)(html_ERROR_MESSAGES.UNKNOWN_SELECTOR_TYPE, type))); } } } /** * Creates a CSS pseudo-class selector node. * * @param name The name of the pseudo-class selector. * @param argument Optional argument of the pseudo-class selector. * * @returns CSS pseudo-class selector node. */ static getPseudoClassSelectorNode(name, argument) { return { type: 'PseudoClassSelector', name: { type: 'Value', value: name, }, argument: argument ? { type: 'Value', value: argument, } : undefined, }; } /** * Asserts that the given array is not empty. * * @param array Array to check. * @param errorMessage Error message to use if the array is empty. * * @throws If the array is empty. */ static assertNotEmpty(array, errorMessage) { if (array.length === 0) { throw new RuleConversionError((0,sprintf.sprintf)(html_ERROR_MESSAGES.INVALID_RULE, errorMessage)); } } /** * Asserts that the given special attribute / pseudo-class length value is valid. * * @param name Name of the attribute or pseudo-class. * @param value Value to parse. * @param notIntErrorMessage Error message when the value is not an integer. * @param notPositiveErrorMessage Error message when the value is not positive. * * @throws If the value is not a valid number or not positive. */ static assertValidLengthValue(name, value, notIntErrorMessage, notPositiveErrorMessage) { const parsed = Number(value); if (Number.isNaN(parsed)) { throw new RuleConversionError((0,sprintf.sprintf)(notIntErrorMessage, name, value)); } if (parsed < 0) { throw new RuleConversionError((0,sprintf.sprintf)(notPositiveErrorMessage, name, value)); } } } ;// CONCATENATED MODULE: ./node_modules/.pnpm/@adguard+agtree@4.2.1/node_modules/@adguard/agtree/dist/converter/cosmetic/path-converter.js /* * AGTree v4.2.1 (build date: Wed, 12 Aug 2026 01:31:02 GMT) * (c) 2026 Adguard Software Ltd. * Released under the MIT license * https://github.com/AdguardTeam/tsurlfilter/tree/master/packages/agtree#readme */ /** * @file Path-in-domain converter helper. */ /** * Finds the index of the first escaped forward slash (`\/`) in a regex string, * skipping character classes (`[...]`). * * @param str Regex content without outer `/` delimiters. * * @returns Index of the backslash in the first `\/` sequence, or -1 if not found. */ function findFirstEscapedSlash(str) { let insideCharacterClass = false; for (let i = 0; i < str.length; i += 1) { if (str[i] === constants/* .OPEN_SQUARE_BRACKET */.cU && !insideCharacterClass) { insideCharacterClass = true; } else if (str[i] === constants/* .CLOSE_SQUARE_BRACKET */.A1 && insideCharacterClass) { insideCharacterClass = false; } else if (!insideCharacterClass && str[i] === constants/* .ESCAPE_CHARACTER */.Kx && i + 1 < str.length && str[i + 1] === constants/* .SLASH */.o) { return i; } } return -1; } /** * Converts path-in-domain syntax to $path modifier. * * Example: `example.org/path##.ad` → `[$path=/path]example.org##.ad`. * * @param rule Rule to check and convert. * * @returns Conversion result if path-in-domain syntax found, undefined otherwise. * * @throws RuleConversionError if conflicting $path modifier exists. */ function convertPathInDomainToModifier(rule) { // Only process rules with domains if (!rule.domains || rule.domains.children.length === 0) { return undefined; } // Quick check: return early if no domain contains a path indicator. // For non-regex domains, a path requires '/'. // For regex domains, a path requires '\/' (escaped slash). const hasAnyPath = rule.domains.children.some((domainItem) => { const { value } = domainItem; if (value.startsWith(constants/* .REGEX_MARKER */.Vb) && value.endsWith(constants/* .REGEX_MARKER */.Vb) && value.length > 1) { return value.includes(constants/* .ESCAPE_CHARACTER */.Kx + constants/* .SLASH */.o); } return value.includes(constants/* .SLASH */.o); }); if (!hasAnyPath) { return undefined; } const domainsWithPaths = []; const domainsWithoutPaths = []; rule.domains.children.forEach((domainItem) => { const domainValue = domainItem.value; // Check if domain is a regex pattern (starts and ends with /) if (domainValue.startsWith(constants/* .REGEX_MARKER */.Vb) && domainValue.endsWith(constants/* .REGEX_MARKER */.Vb) && domainValue.length > 1) { const inner = domainValue.slice(1, -1); const splitIndex = findFirstEscapedSlash(inner); if (splitIndex !== -1) { // splitIndex points to the backslash in `\/` // Domain part: everything before the backslash, wrapped in / // Path part: from the slash onward (keeping the slash), wrapped in / const domain = `${constants/* .REGEX_MARKER */.Vb}${inner.substring(0, splitIndex)}${constants/* .REGEX_MARKER */.Vb}`; const path = `${constants/* .REGEX_MARKER */.Vb}${inner.substring(splitIndex)}${constants/* .REGEX_MARKER */.Vb}`; domainsWithPaths.push({ domain, path, exception: domainItem.exception, }); } else { domainsWithoutPaths.push({ domain: domainValue, exception: domainItem.exception, }); } } else { // Non-regex domain const slashIndex = domainValue.indexOf(constants/* .SLASH */.o); if (slashIndex !== -1) { const domain = domainValue.substring(0, slashIndex); const path = domainValue.substring(slashIndex); // includes leading / // Skip empty paths if (path === '/') { domainsWithoutPaths.push({ domain, exception: domainItem.exception, }); } else { domainsWithPaths.push({ domain, path, exception: domainItem.exception, }); } } else { domainsWithoutPaths.push({ domain: domainValue, exception: domainItem.exception, }); } } }); if (domainsWithPaths.length === 0) { return undefined; } /* * Exception domains cannot be combined with path-in-domain syntax. * * For example example.org/foo1/bar2,~example.org/${WILDCARD}/bar2##h1 * This can’t be converted because [$path=/${WILDCARD}/bar2]example.org##h1 * may unblock unrelated rules like: "example.org/baz1/bar2##h1". */ const hasException = rule.domains.children.some((d) => d.exception); if (hasException) { // Single exception domain with path — just skip conversion if (rule.domains.children.length === 1) { return undefined; } // Domain list with both exception and path-in-domain — error throw new RuleConversionError('Path-in-domain syntax cannot be used with exception domains'); } // Check for conflicting $path modifier if (rule.modifiers) { const hasPathModifier = rule.modifiers.children.some((mod) => mod.name.value === constants/* .ADG_PATH_MODIFIER */.JD); if (hasPathModifier) { throw new RuleConversionError('Path specified both in domain and $path modifier'); } } // Group domains by path const pathGroups = new Map(); domainsWithPaths.forEach(({ domain, path, exception }) => { if (!pathGroups.has(path)) { pathGroups.set(path, []); } pathGroups.get(path).push({ domain, exception }); }); // If all domains have the same path and there are no domains without paths, // create a single rule with $path modifier if (pathGroups.size === 1 && domainsWithoutPaths.length === 0) { const [path, domains] = Array.from(pathGroups.entries())[0]; const convertedRule = clone(rule); // Set syntax to Adg since we're adding AdGuard modifiers convertedRule.syntax = adblockers/* .AdblockSyntax.Adg */.YG.Adg; // Update domains to remove paths convertedRule.domains = { type: nodes/* .ListNodeType.DomainList */.h6.DomainList, separator: rule.domains.separator, children: domains.map((d) => ({ type: nodes/* .ListItemNodeType.Domain */.WR.Domain, value: d.domain, exception: d.exception, })), }; // Add $path modifier const pathModifier = createModifierNode(constants/* .ADG_PATH_MODIFIER */.JD, path); if (convertedRule.modifiers) { convertedRule.modifiers = { ...convertedRule.modifiers, children: [...convertedRule.modifiers.children, pathModifier], }; } else { convertedRule.modifiers = { type: 'ModifierList', children: [pathModifier], }; } return (0,conversion_result/* .createNodeConversionResult */.k)([convertedRule], true); } // Multiple paths or mixed (with/without paths) - split into multiple rules const convertedRules = []; // Create rules for domains with paths pathGroups.forEach((domains, path) => { const convertedRule = clone(rule); // Set syntax to Adg since we're adding AdGuard modifiers convertedRule.syntax = adblockers/* .AdblockSyntax.Adg */.YG.Adg; // Set domains for this path convertedRule.domains = { type: 'DomainList', separator: rule.domains.separator, children: domains.map((d) => ({ type: 'Domain', value: d.domain, exception: d.exception, })), }; // Add $path modifier const pathModifier = createModifierNode(constants/* .ADG_PATH_MODIFIER */.JD, path); if (convertedRule.modifiers) { convertedRule.modifiers = { ...convertedRule.modifiers, children: [...convertedRule.modifiers.children, pathModifier], }; } else { convertedRule.modifiers = { type: 'ModifierList', children: [pathModifier], }; } convertedRules.push(convertedRule); }); // Create rule for domains without paths (if any) if (domainsWithoutPaths.length > 0) { const convertedRule = clone(rule); convertedRule.domains = { type: 'DomainList', separator: rule.domains.separator, children: domainsWithoutPaths.map((d) => ({ type: 'Domain', value: d.domain, exception: d.exception, })), }; convertedRules.push(convertedRule); } return (0,conversion_result/* .createNodeConversionResult */.k)(convertedRules, true); } ;// CONCATENATED MODULE: ./node_modules/.pnpm/@adguard+agtree@4.2.1/node_modules/@adguard/agtree/dist/utils/multi-value-map.js /* * AGTree v4.2.1 (build date: Wed, 12 Aug 2026 01:31:02 GMT) * (c) 2026 Adguard Software Ltd. * Released under the MIT license * https://github.com/AdguardTeam/tsurlfilter/tree/master/packages/agtree#readme */ /** * A very simple map extension that allows to store multiple values for the same key * by storing them in an array. * * @todo Add more methods if needed. */ class MultiValueMap extends Map { /** * Adds a value to the map. If the key already exists, the value will be appended to the existing array, * otherwise a new array will be created for the key. * * @param key Key to add. * @param values Value(s) to add. */ add(key, ...values) { let currentValues = super.get(key); if ((0,type_guards/* .isUndefined */.b0)(currentValues)) { currentValues = []; super.set(key, values); } currentValues.push(...values); } } // EXTERNAL MODULE: ./node_modules/.pnpm/@adguard+agtree@4.2.1/node_modules/@adguard/agtree/dist/utils/string.js var string = __webpack_require__(16875); ;// CONCATENATED MODULE: ./node_modules/.pnpm/@adguard+agtree@4.2.1/node_modules/@adguard/agtree/dist/converter/cosmetic/rule-modifiers/adg.js /* * AGTree v4.2.1 (build date: Wed, 12 Aug 2026 01:31:02 GMT) * (c) 2026 Adguard Software Ltd. * Released under the MIT license * https://github.com/AdguardTeam/tsurlfilter/tree/master/packages/agtree#readme */ /** * @file Cosmetic rule modifier converter from uBO to ADG. */ const UBO_MATCHES_PATH_OPERATOR = 'matches-path'; const ADG_PATH_MODIFIER = 'path'; /** * Special characters in modifier regexps that should be escaped. */ const SPECIAL_MODIFIER_REGEX_CHARS = new Set([ constants/* .OPEN_SQUARE_BRACKET */.cU, constants/* .CLOSE_SQUARE_BRACKET */.A1, constants/* .COMMA */.KE, constants/* .ESCAPE_CHARACTER */.Kx, ]); /** * Helper class for converting cosmetic rule modifiers from uBO to ADG. */ class AdgCosmeticRuleModifierConverter { /** * Converts a uBO cosmetic rule modifier list to ADG, if possible. * * @see {@link https://github.com/gorhill/uBlock/wiki/Procedural-cosmetic-filters#cosmetic-filter-operators} * * @param modifierList Cosmetic rule modifier list node to convert. * * @returns An object which follows the {@link ConversionResult} interface. Its `result` property contains * the converted node, and its `isConverted` flag indicates whether the original node was converted. * If the node was not converted, the result will contain the original node with the same object reference. * * @throws If the modifier list cannot be converted. */ static convertFromUbo(modifierList) { const conversionMap = new MultiValueMap(); modifierList.children.forEach((modifier, index) => { // :matches-path if (modifier.name.value === UBO_MATCHES_PATH_OPERATOR) { if (!modifier.value) { throw new RuleConversionError(`'${UBO_MATCHES_PATH_OPERATOR}' operator requires a value`); } const value = regexp/* .RegExpUtils.isRegexPattern */.Lp.isRegexPattern(modifier.value.value) ? string/* .StringUtils.escapeCharacters */.$x.escapeCharacters(modifier.value.value, SPECIAL_MODIFIER_REGEX_CHARS) : modifier.value.value; // Convert uBO's `:matches-path(...)` operator to ADG's `$path=...` modifier conversionMap.add(index, createModifierNode(ADG_PATH_MODIFIER, // We should negate the regexp if the modifier is an exception modifier.exception // eslint-disable-next-line max-len ? `${constants/* .REGEX_MARKER */.Vb}${regexp/* .RegExpUtils.negateRegexPattern */.Lp.negateRegexPattern(regexp/* .RegExpUtils.patternToRegexp */.Lp.patternToRegexp(value))}${constants/* .REGEX_MARKER */.Vb}` : value)); } }); // Check if we have any converted modifiers if (conversionMap.size) { const modifierListClone = clone(modifierList); // Replace the original modifiers with the converted ones modifierListClone.children = modifierListClone.children.map((modifier, index) => { const convertedModifier = conversionMap.get(index); return convertedModifier ?? modifier; }).flat(); return (0,conversion_result/* .createConversionResult */.c)(modifierListClone, true); } // Otherwise, just return the original modifier list return (0,conversion_result/* .createConversionResult */.c)(modifierList, false); } } // EXTERNAL MODULE: ./node_modules/.pnpm/@adguard+agtree@4.2.1/node_modules/@adguard/agtree/dist/parser/misc/domain-list-parser.js + 1 modules var domain_list_parser = __webpack_require__(70254); ;// CONCATENATED MODULE: ./node_modules/.pnpm/@adguard+agtree@4.2.1/node_modules/@adguard/agtree/dist/converter/cosmetic/rule-modifiers/ubo.js /* * AGTree v4.2.1 (build date: Wed, 12 Aug 2026 01:31:02 GMT) * (c) 2026 Adguard Software Ltd. * Released under the MIT license * https://github.com/AdguardTeam/tsurlfilter/tree/master/packages/agtree#readme */ /** * @file Cosmetic rule modifier converter from ADG to uBO. */ /** * Regular expression pattern for matching the main page * https://github.com/gorhill/uBlock/wiki/Procedural-cosmetic-filters#subjectmatches-patharg. */ const UBO_MAIN_PAGE_MATCHER = '/^/$/'; /** * Special characters in modifier regexps that should be escaped. */ const ubo_SPECIAL_MODIFIER_REGEX_CHARS = new Set([ constants/* .OPEN_SQUARE_BRACKET */.cU, constants/* .CLOSE_SQUARE_BRACKET */.A1, constants/* .COMMA_DOMAIN_LIST_SEPARATOR */.oo, constants/* .ESCAPE_CHARACTER */.Kx, ]); /** * Helper class for converting cosmetic rule modifiers from ADG to uBO. */ class UboCosmeticRuleModifierConverter { /** * Converts a ADG cosmetic rule modifier list to uBO, if possible. * * @see {@link https://github.com/gorhill/uBlock/wiki/Procedural-cosmetic-filters#cosmetic-filter-operators} * * @param modifierList Cosmetic rule modifier list node to convert. * * @returns An object which follows the {@link ConversionResult} interface. Its `result` property contains * the converted node, and its `isConverted` flag indicates whether the original node was converted. * If the node was not converted, the result will contain the original node with the same object reference. * * @throws If the modifier list cannot be converted. */ static convertFromAdg(modifierList) { const conversionMap = new MultiValueMap(); let domainList = null; let regexDomainValue; modifierList.children.forEach((modifier, index) => { let value; let { exception } = modifier; switch (modifier.name.value) { // Special case: ADG's $app modifier case constants/* .ADG_APP_MODIFIER */.Pe: throw new Error('The $app modifier is not supported by uBO'); // Special case: ADG's $domains modifier case constants/* .ADG_DOMAINS_MODIFIER */.NW: if (!domainList) { domainList = { type: nodes/* .ListNodeType.DomainList */.h6.DomainList, separator: constants/* .COMMA_DOMAIN_LIST_SEPARATOR */.oo, children: [], start: modifier.start, end: modifier.end, }; } if (!modifier?.value?.value) { return; } domainList = domain_list_parser/* .DomainListParser.parse */.y.parse(modifier.value.value, {}, modifier.start, constants/* .PIPE_MODIFIER_SEPARATOR */.fW); conversionMap.add(index, null); break; // Special case: ADG's $url modifier case constants/* .ADG_URL_MODIFIER */.Vw: if (!domainList) { domainList = { type: nodes/* .ListNodeType.DomainList */.h6.DomainList, separator: constants/* .COMMA_DOMAIN_LIST_SEPARATOR */.oo, children: [], start: modifier.start, end: modifier.end, }; } if (!modifier?.value?.value) { return; } regexDomainValue = regexp/* .RegExpUtils.patternToRegexp */.Lp.patternToRegexp(modifier.value.value); domainList = { type: nodes/* .ListNodeType.DomainList */.h6.DomainList, separator: constants/* .COMMA_DOMAIN_LIST_SEPARATOR */.oo, children: [ { type: nodes/* .ListItemNodeType.Domain */.WR.Domain, value: regexp/* .RegExpUtils.ensureSlashes */.Lp.ensureSlashes(regexDomainValue), exception: modifier?.exception ?? false, }, ], start: modifier.start, end: modifier.end, }; conversionMap.add(index, null); break; // Special case: ADG's $path modifier case constants/* .ADG_PATH_MODIFIER */.JD: if (!modifier.value) { value = UBO_MAIN_PAGE_MATCHER; } else if (regexp/* .RegExpUtils.isNegatedRegexPattern */.Lp.isNegatedRegexPattern(modifier.value.value)) { exception = true; value = string/* .StringUtils.escapeCharacters */.$x.escapeCharacters(regexp/* .RegExpUtils.removeNegationFromRegexPattern */.Lp.removeNegationFromRegexPattern(modifier.value.value), ubo_SPECIAL_MODIFIER_REGEX_CHARS); } else { value = regexp/* .RegExpUtils.isRegexPattern */.Lp.isRegexPattern(modifier.value.value) ? string/* .StringUtils.escapeCharacters */.$x.escapeCharacters(modifier.value.value, ubo_SPECIAL_MODIFIER_REGEX_CHARS) : modifier.value.value; } conversionMap.add(index, createModifierNode(constants/* .UBO_MATCHES_PATH_OPERATOR */.I6, value, exception)); break; } }); // Check if we have any converted modifiers if (conversionMap.size) { const modifierListClone = clone(modifierList); // Replace the original modifiers with the converted ones modifierListClone.children = modifierListClone.children .map((modifier, index) => { const convertedModifier = conversionMap.get(index); return convertedModifier ?? modifier; }) .flat() .filter((modifier) => modifier !== null); return (0,conversion_result/* .createConversionResult */.c)({ modifierList: modifierListClone, domains: domainList || undefined }, true); } // Otherwise, just return the original modifier list without any changes return (0,conversion_result/* .createConversionResult */.c)({ modifierList, domains: undefined }, false); } } ;// CONCATENATED MODULE: ./node_modules/.pnpm/@adguard+agtree@4.2.1/node_modules/@adguard/agtree/dist/ast-utils/scriptlets.js /* * AGTree v4.2.1 (build date: Wed, 12 Aug 2026 01:31:02 GMT) * (c) 2026 Adguard Software Ltd. * Released under the MIT license * https://github.com/AdguardTeam/tsurlfilter/tree/master/packages/agtree#readme */ /** * @file Utility functions for working with scriptlet nodes. */ /** * Get name of the scriptlet from the scriptlet node. * * @param scriptletNode Scriptlet node to get name of. * * @returns Name of the scriptlet. * * @throws If the scriptlet is empty. */ function getScriptletName(scriptletNode) { if (scriptletNode.children.length === 0) { throw new Error('Empty scriptlet'); } return scriptletNode.children[0]?.value ?? constants/* .EMPTY */.wg; } /** * Transform the nth argument of the scriptlet node. * * @param scriptletNode Scriptlet node to transform argument of. * @param index Index of the argument to transform (index 0 is the scriptlet name). * @param transform Function to transform the argument. */ function transformNthScriptletArgument(scriptletNode, index, transform) { const child = scriptletNode.children[index]; if (!(0,type_guards/* .isUndefined */.b0)(child)) { const transformed = transform(child?.value ?? null); if ((0,type_guards/* .isNull */.kZ)(transformed)) { // eslint-disable-next-line no-param-reassign scriptletNode.children[index] = null; return; } if ((0,type_guards/* .isNull */.kZ)(child)) { // eslint-disable-next-line no-param-reassign scriptletNode.children[index] = { type: 'Value', value: transformed, }; return; } child.value = transformed; } } /** * Transform all arguments of the scriptlet node. * * @param scriptletNode Scriptlet node to transform arguments of. * @param transform Function to transform the arguments. */ function transformAllScriptletArguments(scriptletNode, transform) { for (let i = 0; i < scriptletNode.children.length; i += 1) { transformNthScriptletArgument(scriptletNode, i, transform); } } /** * Set name of the scriptlet. * Modifies input `scriptletNode` if needed. * * @param scriptletNode Scriptlet node to set name of. * @param name Name to set. */ function setScriptletName(scriptletNode, name) { transformNthScriptletArgument(scriptletNode, 0, () => name); } /** * Set quote type of the scriptlet parameters. * * @param scriptletNode Scriptlet node to set quote type of. * @param quoteType Preferred quote type. */ function setScriptletQuoteType(scriptletNode, quoteType) { // null is a special value that means "no value", but we can't change its quote type, // so we need to convert it to empty string transformAllScriptletArguments(scriptletNode, (value) => quotes/* .QuoteUtils.setStringQuoteType */.Qj.setStringQuoteType(value ?? constants/* .EMPTY */.wg, quoteType)); } // EXTERNAL MODULE: ./node_modules/.pnpm/@adguard+agtree@4.2.1/node_modules/@adguard/agtree/dist/utils/deep-freeze.js var deep_freeze = __webpack_require__(41666); // EXTERNAL MODULE: ./node_modules/.pnpm/@adguard+agtree@4.2.1/node_modules/@adguard/agtree/dist/compatibility-tables/base.js + 1 modules var base = __webpack_require__(21565); // EXTERNAL MODULE: ./node_modules/.pnpm/@adguard+agtree@4.2.1/node_modules/@adguard/agtree/dist/compatibility-tables/compatibility-table-data.js var compatibility_table_data = __webpack_require__(33017); ;// CONCATENATED MODULE: ./node_modules/.pnpm/@adguard+agtree@4.2.1/node_modules/@adguard/agtree/dist/compatibility-tables/scriptlets.js /* * AGTree v4.2.1 (build date: Wed, 12 Aug 2026 01:31:02 GMT) * (c) 2026 Adguard Software Ltd. * Released under the MIT license * https://github.com/AdguardTeam/tsurlfilter/tree/master/packages/agtree#readme */ /** * @file Compatibility tables for scriptlets. */ /** * Compatibility table for scriptlets. */ class ScriptletsCompatibilityTable extends base/* .CompatibilityTableBase */.E { } /** * Deep freeze the compatibility table data to avoid accidental modifications. */ (0,deep_freeze/* .deepFreeze */.o)(compatibility_table_data/* .scriptletsCompatibilityTableData */.YJ); /** * Compatibility table instance for scriptlets. */ const scriptletsCompatibilityTable = new ScriptletsCompatibilityTable(compatibility_table_data/* .scriptletsCompatibilityTableData */.YJ); // EXTERNAL MODULE: ./node_modules/.pnpm/@adguard+agtree@4.2.1/node_modules/@adguard/agtree/dist/compatibility-tables/platforms.js var platforms = __webpack_require__(9257); ;// CONCATENATED MODULE: ./node_modules/.pnpm/@adguard+agtree@4.2.1/node_modules/@adguard/agtree/dist/converter/cosmetic/scriptlet.js /* * AGTree v4.2.1 (build date: Wed, 12 Aug 2026 01:31:02 GMT) * (c) 2026 Adguard Software Ltd. * Released under the MIT license * https://github.com/AdguardTeam/tsurlfilter/tree/master/packages/agtree#readme */ /** * @file Scriptlet injection rule converter. */ const ABP_SCRIPTLET_PREFIX = 'abp-'; const UBO_SCRIPTLET_PREFIX = 'ubo-'; const UBO_SCRIPTLET_PREFIX_LENGTH = UBO_SCRIPTLET_PREFIX.length; const UBO_SCRIPTLET_JS_SUFFIX = '.js'; const UBO_SCRIPTLET_JS_SUFFIX_LENGTH = UBO_SCRIPTLET_JS_SUFFIX.length; const COMMA_SEPARATOR = ','; const ADG_SET_CONSTANT_NAME = 'set-constant'; const ADG_SET_CONSTANT_EMPTY_STRING = ''; const ADG_SET_CONSTANT_EMPTY_ARRAY = 'emptyArr'; const ADG_SET_CONSTANT_EMPTY_OBJECT = 'emptyObj'; const UBO_SET_CONSTANT_EMPTY_STRING = '\'\''; const UBO_SET_CONSTANT_EMPTY_ARRAY = '[]'; const UBO_SET_CONSTANT_EMPTY_OBJECT = '{}'; const ADG_PREVENT_FETCH_NAME = 'prevent-fetch'; const ADG_PREVENT_FETCH_EMPTY_STRING = ''; const ADG_PREVENT_FETCH_WILDCARD = '*'; const UBO_NO_FETCH_IF_WILDCARD = '/^/'; const UBO_REMOVE_CLASS_NAME = 'remove-class.js'; const UBO_REMOVE_ATTR_NAME = 'remove-attr.js'; const UBO_JSON_PRUNE_FETCH_RESPONSE_NAME = 'json-prune-fetch-response.js'; const UBO_JSON_PRUNE_XHR_RESPONSE_NAME = 'json-prune-xhr-response.js'; const UBO_PRUNE_RESPONSE_PROPS_TO_MATCH_KEY = 'propsToMatch'; const UBO_PRUNE_RESPONSE_STACK_TO_MATCH_KEY = 'stackToMatch'; const ADG_PRUNE_FETCH_RESPONSE_NAME = UBO_JSON_PRUNE_FETCH_RESPONSE_NAME.slice(0, -UBO_SCRIPTLET_JS_SUFFIX_LENGTH); const ADG_PRUNE_XHR_RESPONSE_NAME = UBO_JSON_PRUNE_XHR_RESPONSE_NAME.slice(0, -UBO_SCRIPTLET_JS_SUFFIX_LENGTH); const setConstantAdgToUboMap = { [ADG_SET_CONSTANT_EMPTY_STRING]: UBO_SET_CONSTANT_EMPTY_STRING, [ADG_SET_CONSTANT_EMPTY_ARRAY]: UBO_SET_CONSTANT_EMPTY_ARRAY, [ADG_SET_CONSTANT_EMPTY_OBJECT]: UBO_SET_CONSTANT_EMPTY_OBJECT, }; const REMOVE_ATTR_CLASS_APPLYING = new Set([ 'asap', 'stay', 'complete', ]); /** * Scriptlet injection rule converter class. * * @todo Implement `convertToUbo` and `convertToAbp`. */ class ScriptletRuleConverter extends RuleConverterBase { /** * Converts a scriptlet injection rule to AdGuard format, if possible. * * @param rule Rule node to convert. * * @returns An object which follows the {@link NodeConversionResult} interface. Its `result` property contains * the array of converted rule nodes, and its `isConverted` flag indicates whether the original rule was converted. * If the rule was not converted, the result array will contain the original node with the same object reference. * * @throws If the rule is invalid or cannot be converted. */ static convertToAdg(rule) { // Ignore AdGuard rules if (rule.syntax === adblockers/* .AdblockSyntax.Adg */.YG.Adg) { return (0,conversion_result/* .createNodeConversionResult */.k)([rule], false); } const separator = rule.separator.value; let convertedSeparator = separator; convertedSeparator = rule.exception ? nodes/* .CosmeticRuleSeparator.AdgJsInjectionException */.p5.AdgJsInjectionException : nodes/* .CosmeticRuleSeparator.AdgJsInjection */.p5.AdgJsInjection; const convertedScriptlets = []; for (const scriptlet of rule.body.children) { // Clone the node to avoid any side effects const scriptletClone = cloneScriptletRuleNode(scriptlet); // Remove possible quotes just to make it easier to work with the scriptlet name const scriptletName = quotes/* .QuoteUtils.setStringQuoteType */.Qj.setStringQuoteType(getScriptletName(scriptletClone), quotes/* .QuoteType.None */.XA.None); // Add prefix if it's not already there let prefix; // In uBO / ABP syntax, if a parameter contains the separator character, it should be escaped, // but during the conversion, we need to unescape them, because AdGuard syntax uses quotes to // distinguish between parameters. let charToUnescape; switch (rule.syntax) { case adblockers/* .AdblockSyntax.Abp */.YG.Abp: prefix = ABP_SCRIPTLET_PREFIX; charToUnescape = constants/* .SPACE */.t6; break; case adblockers/* .AdblockSyntax.Ubo */.YG.Ubo: prefix = UBO_SCRIPTLET_PREFIX; charToUnescape = COMMA_SEPARATOR; break; default: prefix = constants/* .EMPTY */.wg; } if (!scriptletName.startsWith(prefix)) { setScriptletName(scriptletClone, `${prefix}${scriptletName}`); } if (!(0,type_guards/* .isUndefined */.b0)(charToUnescape)) { transformAllScriptletArguments(scriptletClone, (value) => { if (!(0,type_guards/* .isNull */.kZ)(value)) { return quotes/* .QuoteUtils.unescapeSingleEscapedOccurrences */.Qj.unescapeSingleEscapedOccurrences(value, charToUnescape); } return value; }); } if (rule.syntax === adblockers/* .AdblockSyntax.Ubo */.YG.Ubo) { const scriptletData = scriptletsCompatibilityTable.getFirst(scriptletName, platforms/* .GenericPlatform.UboAny */.p.UboAny); // Some scriptlets have special values that need to be converted if (scriptletData && (scriptletData.name === UBO_REMOVE_CLASS_NAME || scriptletData.name === UBO_REMOVE_ATTR_NAME) && scriptletClone.children.length > 2) { const selectors = []; let applying = null; let lastArg = scriptletClone.children.pop(); // The very last argument might be the 'applying' parameter if (lastArg) { if (REMOVE_ATTR_CLASS_APPLYING.has(lastArg.value)) { applying = lastArg.value; } else { selectors.push(lastArg.value); } } while (scriptletClone.children.length > 2) { lastArg = scriptletClone.children.pop(); if (lastArg) { selectors.push(lastArg.value.trim()); } } // Set last arg to be the combined selectors (in reverse order, because we popped them) if (selectors.length > 0) { scriptletClone.children.push({ type: 'Value', value: selectors.reverse().join(', '), }); } // Push back the 'applying' parameter if it was found previously if (!(0,type_guards/* .isNull */.kZ)(applying)) { // If we don't have any selectors, // we need to add an empty parameter before the 'applying' one if (selectors.length === 0) { scriptletClone.children.push({ type: 'Value', value: constants/* .EMPTY */.wg, }); } scriptletClone.children.push({ type: 'Value', value: applying, }); } } // Remap uBO prune-response scriptlet key/value args into ADG positional slots. // https://github.com/AdguardTeam/FiltersCompiler/issues/250 if (scriptletData) { ScriptletRuleConverter.remapUboPruneResponseArgs(scriptletClone, scriptletData); } } // ADG scriptlet parameters should be quoted, and single quoted are preferred setScriptletQuoteType(scriptletClone, quotes/* .QuoteType.Single */.XA.Single); convertedScriptlets.push(scriptletClone); } if (rule.body.children.length === 0) { const convertedScriptletNode = { category: rule.category, type: rule.type, syntax: adblockers/* .AdblockSyntax.Adg */.YG.Adg, exception: rule.exception, domains: cloneDomainListNode(rule.domains), separator: { type: 'Value', value: convertedSeparator, }, body: { type: rule.body.type, children: [], }, }; if (rule.modifiers) { convertedScriptletNode.modifiers = cloneModifierListNode(rule.modifiers); } return (0,conversion_result/* .createNodeConversionResult */.k)([convertedScriptletNode], true); } return (0,conversion_result/* .createNodeConversionResult */.k)(convertedScriptlets.map((scriptlet) => { const res = { category: rule.category, type: rule.type, syntax: adblockers/* .AdblockSyntax.Adg */.YG.Adg, exception: rule.exception, domains: cloneDomainListNode(rule.domains), separator: { type: 'Value', value: convertedSeparator, }, body: { type: rule.body.type, children: [scriptlet], }, }; if (rule.modifiers) { res.modifiers = cloneModifierListNode(rule.modifiers); } return res; }), true); } /** * Converts a scriptlet injection rule to uBlock format, if possible. * * @param rule Rule node to convert. * * @returns An object which follows the {@link NodeConversionResult} interface. Its `result` property contains * the array of converted rule nodes, and its `isConverted` flag indicates whether the original rule was converted. * If the rule was not converted, the result array will contain the original node with the same object reference. * * @throws If the rule is invalid or cannot be converted. */ static convertToUbo(rule) { // Ignore uBlock rules if (rule.syntax === adblockers/* .AdblockSyntax.Ubo */.YG.Ubo) { return (0,conversion_result/* .createNodeConversionResult */.k)([rule], false); } let ruleDomainsList = cloneDomainListNode(rule.domains); if (rule.syntax === adblockers/* .AdblockSyntax.Adg */.YG.Adg && rule.modifiers?.children.length) { const { modifiers } = rule; // Validate modifiers structure if (!modifiers || !modifiers.children || modifiers.children.length === 0) { throw new RuleConversionError('Invalid modifiers in AdGuard rule.'); } // Check for single domain modifier const [domainModifier] = modifiers.children; const hasSingleDomainModifier = (modifiers.children.length === 1 && domainModifier.name?.value === constants/* .ADG_DOMAINS_MODIFIER */.NW && domainModifier.value?.value); if (!hasSingleDomainModifier) { throw new RuleConversionError('uBlock Origin scriptlet injection rules do not support cosmetic rule modifiers.'); } // Validate domain modifier if (!domainModifier.value?.value) { throw new RuleConversionError('Invalid domain modifier in AdGuard rule.'); } // Parse domain list const parsedDomainList = domain_list_parser/* .DomainListParser.parse */.y.parse(domainModifier.value.value, {}, domainModifier.start, constants/* .PIPE_MODIFIER_SEPARATOR */.fW); // Merge domain lists if (ruleDomainsList) { ruleDomainsList.children.push(...parsedDomainList.children); } else { ruleDomainsList = parsedDomainList; } } const separator = rule.separator.value; let convertedSeparator = separator; convertedSeparator = rule.exception ? nodes/* .CosmeticRuleSeparator.ElementHidingException */.p5.ElementHidingException : nodes/* .CosmeticRuleSeparator.ElementHiding */.p5.ElementHiding; const convertedScriptlets = []; for (const scriptlet of rule.body.children) { // Clone the node to avoid any side effects const scriptletClone = cloneScriptletRuleNode(scriptlet); // Remove possible quotes just to make it easier to work with the scriptlet name const scriptletName = quotes/* .QuoteUtils.setStringQuoteType */.Qj.setStringQuoteType(getScriptletName(scriptletClone), quotes/* .QuoteType.None */.XA.None); let uboScriptletName; if (rule.syntax === adblockers/* .AdblockSyntax.Adg */.YG.Adg && scriptletName.startsWith(UBO_SCRIPTLET_PREFIX)) { // Special case: AdGuard syntax 'preserves' the original scriptlet name, // so we need to convert it back by removing the uBO prefix uboScriptletName = scriptletName.slice(UBO_SCRIPTLET_PREFIX_LENGTH); } else { // Otherwise, try to find the corresponding uBO scriptlet name, or use the original one if not found const uboScriptlet = scriptletsCompatibilityTable.getFirst(scriptletName, platforms/* .GenericPlatform.UboAny */.p.UboAny); if (!uboScriptlet) { throw new RuleConversionError(`Scriptlet "${scriptletName}" is not supported in uBlock Origin.`); } uboScriptletName = uboScriptlet.name; } // Remove the '.js' suffix if it's there - its presence is not mandatory if (uboScriptletName.endsWith(UBO_SCRIPTLET_JS_SUFFIX)) { uboScriptletName = uboScriptletName.slice(0, -UBO_SCRIPTLET_JS_SUFFIX_LENGTH); } setScriptletName(scriptletClone, uboScriptletName); setScriptletQuoteType(scriptletClone, quotes/* .QuoteType.None */.XA.None); // Escape unescaped commas in parameters, because uBlock Origin uses them as separators. // For example, the following AdGuard rule: // // example.com#%#//scriptlet('spoof-css', '.adsbygoogle, #ads', 'visibility', 'visible') // // ↓↓ should be converted to ↓↓ // // example.com##+js(spoof-css.js, .adsbygoogle\, #ads, visibility, visible) // ------------ ------------------- ---------- ------- // arg 0 arg 1 arg 2 arg 3 // // and we need to escape the comma in the second argument to prevent it from being treated // as two separate arguments. transformAllScriptletArguments(scriptletClone, (value) => { if (!(0,type_guards/* .isNull */.kZ)(value)) { return quotes/* .QuoteUtils.escapeUnescapedOccurrences */.Qj.escapeUnescapedOccurrences(value, COMMA_SEPARATOR); } return value; }); // Unescape spaces in parameters, because uBlock Origin doesn't treat them as separators. if (rule.syntax === adblockers/* .AdblockSyntax.Abp */.YG.Abp) { transformAllScriptletArguments(scriptletClone, (value) => { if (!(0,type_guards/* .isNull */.kZ)(value)) { return quotes/* .QuoteUtils.unescapeSingleEscapedOccurrences */.Qj.unescapeSingleEscapedOccurrences(value, constants/* .SPACE */.t6); } return value; }); } // Some scriptlets have special values that need to be converted switch (scriptletName) { case ADG_SET_CONSTANT_NAME: transformNthScriptletArgument(scriptletClone, 2, (value) => { if (!(0,type_guards/* .isNull */.kZ)(value)) { return setConstantAdgToUboMap[value] ?? value; } return value; }); break; case ADG_PREVENT_FETCH_NAME: transformNthScriptletArgument(scriptletClone, 1, (value) => { if (value === ADG_PREVENT_FETCH_EMPTY_STRING || value === ADG_PREVENT_FETCH_WILDCARD) { return UBO_NO_FETCH_IF_WILDCARD; } return value; }); break; case ADG_PRUNE_FETCH_RESPONSE_NAME: case ADG_PRUNE_XHR_RESPONSE_NAME: ScriptletRuleConverter.remapAdgToUboPruneResponseArgs(scriptletClone); break; } convertedScriptlets.push(scriptletClone); } // TODO: Refactor redundant code if (rule.body.children.length === 0) { const convertedScriptletNode = { category: rule.category, type: rule.type, syntax: adblockers/* .AdblockSyntax.Ubo */.YG.Ubo, exception: rule.exception, domains: cloneDomainListNode(rule.domains), separator: { type: 'Value', value: convertedSeparator, }, body: { type: rule.body.type, children: [], }, }; if (rule.modifiers) { convertedScriptletNode.modifiers = cloneModifierListNode(rule.modifiers); } return (0,conversion_result/* .createNodeConversionResult */.k)([convertedScriptletNode], true); } return (0,conversion_result/* .createNodeConversionResult */.k)(convertedScriptlets.map((scriptlet) => { const res = { category: rule.category, type: rule.type, syntax: adblockers/* .AdblockSyntax.Ubo */.YG.Ubo, exception: rule.exception, domains: ruleDomainsList, separator: { type: 'Value', value: convertedSeparator, }, body: { type: rule.body.type, children: [scriptlet], }, }; return res; }), true); } /** * Remaps uBO key/value args of `json-prune-fetch-response` and * `json-prune-xhr-response` into AdGuard positional argument slots. * * These uBO variants accept only two positional args (`propsToRemove`, * `obligatoryProps`); args 3+ are key/value pairs parsed by uBO's * `getExtraArgs` (even index = key, odd index = value). Recognized keys: * `propsToMatch`, `stackToMatch`. ADG's equivalents use positional * `propsToMatch` (arg 3) and `stack` (arg 4), so the pairs are remapped into * positional slots. Unknown keys are dropped, because uBO ignores keys it * does not read and they cannot be mapped to an ADG positional slot. When a * recognized key repeats, the last value wins. * * Besides remapping arguments, this method also sets the scriptlet node's * name to the AdGuard native name (the uBO canonical name without the * `.js` suffix). This overrides the `ubo-` prefix that `convertToAdg` * adds earlier in its main flow for these two scriptlets, so the final * output uses the native AdGuard name with positional argument semantics. * * @see https://github.com/AdguardTeam/FiltersCompiler/issues/250 * * @param scriptletClone Cloned scriptlet node to remap in place. * @param scriptletData Compatibility data for the matched uBO scriptlet. */ static remapUboPruneResponseArgs(scriptletClone, scriptletData) { // Only the two prune-response scriptlets need key/value → positional remapping. if (scriptletData.name !== UBO_JSON_PRUNE_FETCH_RESPONSE_NAME && scriptletData.name !== UBO_JSON_PRUNE_XHR_RESPONSE_NAME) { return; } const propsToRemove = scriptletClone.children[1]?.value ?? constants/* .EMPTY */.wg; const obligatoryProps = scriptletClone.children[2]?.value ?? constants/* .EMPTY */.wg; // Whether the source had an explicit 2nd positional arg (children[2]). const hadObligatoryProps = scriptletClone.children.length > 2; let propsToMatch = constants/* .EMPTY */.wg; let stack = constants/* .EMPTY */.wg; const unknownKeys = []; // Varargs start at index 3 (children[0] is the scriptlet name). for (let i = 3; i < scriptletClone.children.length; i += 2) { const key = scriptletClone.children[i]?.value ?? constants/* .EMPTY */.wg; const val = scriptletClone.children[i + 1]?.value ?? constants/* .EMPTY */.wg; if (key === UBO_PRUNE_RESPONSE_PROPS_TO_MATCH_KEY) { propsToMatch = val; } else if (key === UBO_PRUNE_RESPONSE_STACK_TO_MATCH_KEY) { stack = val; } else if (key !== constants/* .EMPTY */.wg) { // Unknown keys are dropped: uBO ignores keys it does not read, // and they cannot be mapped to an ADG positional slot. unknownKeys.push(key); } } if (unknownKeys.length > 0) { // eslint-disable-next-line no-console console.warn(`[agtree] Dropped unknown extra args for ${scriptletData.name}: ${unknownKeys.join(', ')}`); } // Translate to the ADG native name (uBO canonical name without the // `.js` suffix): the arguments are now in ADG positional semantics. const adgName = scriptletData.name.slice(0, -UBO_SCRIPTLET_JS_SUFFIX_LENGTH); setScriptletName(scriptletClone, adgName); // Rebuild children: name, propsToRemove, then the obligatoryProps, // propsToMatch and stack slots. `obligatoryProps` is emitted only when // it was present in the source or when a positional propsToMatch/stack // slot follows, so the output never gains a trailing empty arg the // source never had. // eslint-disable-next-line no-param-reassign scriptletClone.children = [ scriptletClone.children[0], { type: 'Value', value: propsToRemove }, ]; if (hadObligatoryProps || propsToMatch !== constants/* .EMPTY */.wg || stack !== constants/* .EMPTY */.wg) { scriptletClone.children.push({ type: 'Value', value: obligatoryProps }); } if (propsToMatch !== constants/* .EMPTY */.wg || stack !== constants/* .EMPTY */.wg) { scriptletClone.children.push({ type: 'Value', value: propsToMatch }); } if (stack !== constants/* .EMPTY */.wg) { scriptletClone.children.push({ type: 'Value', value: stack }); } } /** * Inverse of {@link ScriptletRuleConverter.remapUboPruneResponseArgs}: * remaps AdGuard positional `propsToMatch`/`stack` args of * `json-prune-fetch-response` / `json-prune-xhr-response` back into uBO * key/value pairs (`propsToMatch`, `stackToMatch`). * * `children` layout (AdGuard, before this method): `[name, propsToRemove, * obligatoryProps, propsToMatch, stack]`. `propsToMatch` and `stack` are * optional; empty values are not re-emitted, so the output never has * trailing empty key/value pairs. ADG rules that already use the * `ubo-`-prefixed name keep key/value args and are not handled here (they * take the `ubo-` prefix branch in `convertToUbo`, not this `switch`). * * @param scriptletClone Cloned scriptlet node to remap in place. */ static remapAdgToUboPruneResponseArgs(scriptletClone) { // Read the positional propsToMatch/stack before truncating children. const propsToMatchVal = scriptletClone.children[3]?.value; const stackVal = scriptletClone.children[4]?.value; // Keep the name and the two positional args; drop the positional // propsToMatch/stack slots — they are re-emitted as uBO key/value pairs. // eslint-disable-next-line no-param-reassign scriptletClone.children = scriptletClone.children.slice(0, Math.min(3, scriptletClone.children.length)); if (propsToMatchVal && propsToMatchVal !== constants/* .EMPTY */.wg) { scriptletClone.children.push({ type: 'Value', value: UBO_PRUNE_RESPONSE_PROPS_TO_MATCH_KEY }); scriptletClone.children.push({ type: 'Value', value: propsToMatchVal }); } if (stackVal && stackVal !== constants/* .EMPTY */.wg) { scriptletClone.children.push({ type: 'Value', value: UBO_PRUNE_RESPONSE_STACK_TO_MATCH_KEY }); scriptletClone.children.push({ type: 'Value', value: stackVal }); } } } ;// CONCATENATED MODULE: ./node_modules/.pnpm/@adguard+agtree@4.2.1/node_modules/@adguard/agtree/dist/converter/cosmetic/index.js /* * AGTree v4.2.1 (build date: Wed, 12 Aug 2026 01:31:02 GMT) * (c) 2026 Adguard Software Ltd. * Released under the MIT license * https://github.com/AdguardTeam/tsurlfilter/tree/master/packages/agtree#readme */ /** * @file Cosmetic rule converter. */ /** * Cosmetic rule converter class (also known as "non-basic rule converter"). * * @todo Implement `convertToUbo` and `convertToAbp`. */ class CosmeticRuleConverter extends RuleConverterBase { /** * Converts a cosmetic rule to AdGuard syntax, if possible. * * @param rule Rule node to convert. * * @returns An object which follows the {@link NodeConversionResult} interface. Its `result` property contains * the array of converted rule nodes, and its `isConverted` flag indicates whether the original rule was converted. * If the rule was not converted, the result array will contain the original node with the same object reference. * * @throws If the rule is invalid or cannot be converted. */ static convertToAdg(rule) { let subconverterResult; // Convert cosmetic rule based on its type switch (rule.type) { case nodes/* .CosmeticRuleType.ElementHidingRule */.k9.ElementHidingRule: subconverterResult = ElementHidingRuleConverter.convertToAdg(rule); break; case nodes/* .CosmeticRuleType.ScriptletInjectionRule */.k9.ScriptletInjectionRule: subconverterResult = ScriptletRuleConverter.convertToAdg(rule); break; case nodes/* .CosmeticRuleType.CssInjectionRule */.k9.CssInjectionRule: subconverterResult = CssInjectionRuleConverter.convertToAdg(rule); break; case nodes/* .CosmeticRuleType.HtmlFilteringRule */.k9.HtmlFilteringRule: // Handle special case: uBO response header filtering rule // TODO: Optimize double CSS tokenization here subconverterResult = HeaderRemovalRuleConverter.convertToAdg(rule); if (subconverterResult.isConverted) { break; } subconverterResult = HtmlRuleConverter.convertToAdg(rule); break; // Note: Currently, only ADG supports JS injection rules, so we don't need to convert them case nodes/* .CosmeticRuleType.JsInjectionRule */.k9.JsInjectionRule: subconverterResult = (0,conversion_result/* .createNodeConversionResult */.k)([rule], false); break; default: throw new RuleConversionError('Unsupported cosmetic rule type'); } let convertedModifiers; // Convert cosmetic rule modifiers, if any if (rule.modifiers) { if (rule.syntax === adblockers/* .AdblockSyntax.Ubo */.YG.Ubo) { // uBO doesn't support this rule: // example.com##+js(set-constant.js, foo, bar):matches-path(/baz) if (rule.type === nodes/* .CosmeticRuleType.ScriptletInjectionRule */.k9.ScriptletInjectionRule) { throw new RuleConversionError('uBO scriptlet injection rules don\'t support cosmetic rule modifiers'); } convertedModifiers = AdgCosmeticRuleModifierConverter.convertFromUbo(rule.modifiers); } else if (rule.syntax === adblockers/* .AdblockSyntax.Abp */.YG.Abp) { // TODO: Implement once ABP starts supporting cosmetic rule modifiers throw new RuleConversionError('ABP don\'t support cosmetic rule modifiers'); } } // Track if any conversion happened const wasConverted = subconverterResult.result.length > 1 || subconverterResult.isConverted || (convertedModifiers && convertedModifiers.isConverted); if (wasConverted) { // Add modifier list to the subconverter result rules subconverterResult.result.forEach((subconverterRule) => { if (convertedModifiers && subconverterRule.category === nodes/* .RuleCategory.Cosmetic */.$O.Cosmetic) { // eslint-disable-next-line no-param-reassign subconverterRule.modifiers = convertedModifiers.result; } }); } // Apply path-in-domain conversion to all rules const rulesToProcess = wasConverted ? subconverterResult.result : [rule]; const finalRules = []; let pathConversionHappened = false; for (const ruleToProcess of rulesToProcess) { if (ruleToProcess.category === nodes/* .RuleCategory.Cosmetic */.$O.Cosmetic) { const pathConversionResult = convertPathInDomainToModifier(ruleToProcess); if (pathConversionResult) { finalRules.push(...pathConversionResult.result); pathConversionHappened = true; } else { finalRules.push(ruleToProcess); } } else { finalRules.push(ruleToProcess); } } // Return result with combined conversion status if (wasConverted || pathConversionHappened) { return (0,conversion_result/* .createNodeConversionResult */.k)(finalRules, true); } return (0,conversion_result/* .createNodeConversionResult */.k)([rule], false); } /** * Converts a cosmetic rule to uBlock Origin syntax, if possible. * * @param rule Rule node to convert. * * @returns An object which follows the {@link NodeConversionResult} interface. Its `result` property contains * the array of converted rule nodes, and its `isConverted` flag indicates whether the original rule was converted. * If the rule was not converted, the result array will contain the original node with the same object reference. * * @throws If the rule is invalid or cannot be converted. */ static convertToUbo(rule) { // Skip conversation if the rule is already in uBO format if (rule.syntax === adblockers/* .AdblockSyntax.Ubo */.YG.Ubo) { return (0,conversion_result/* .createNodeConversionResult */.k)([rule], false); } // TODO: Add support for other cosmetic rule types switch (rule.type) { case nodes/* .CosmeticRuleType.HtmlFilteringRule */.k9.HtmlFilteringRule: return HtmlRuleConverter.convertToUbo(rule); case nodes/* .CosmeticRuleType.ElementHidingRule */.k9.ElementHidingRule: { // Check if the rule is a simple hiding rule // TODO: Handle elemhide rules with extended CSS pseudos even if type is not marked explicitly const isElementHidingRule = (rule.separator.value === nodes/* .CosmeticRuleSeparator.ElementHidingException */.p5.ElementHidingException || rule.separator.value === nodes/* .CosmeticRuleSeparator.ElementHiding */.p5.ElementHiding); if (isElementHidingRule && !rule.modifiers) { return (0,conversion_result/* .createNodeConversionResult */.k)([rule], false); } break; } case nodes/* .CosmeticRuleType.ScriptletInjectionRule */.k9.ScriptletInjectionRule: return ScriptletRuleConverter.convertToUbo(rule); case nodes/* .CosmeticRuleType.JsInjectionRule */.k9.JsInjectionRule: throw new RuleConversionError('uBO does not support JS injection rules'); } let convertedModifiers; // Convert cosmetic rule modifiers, if any if (rule.modifiers) { if (rule.syntax === adblockers/* .AdblockSyntax.Abp */.YG.Abp) { // TODO: Implement once ABP starts supporting cosmetic rule modifiers throw new RuleConversionError('ABP does not support cosmetic rule modifiers'); } else if (rule.syntax === adblockers/* .AdblockSyntax.Adg */.YG.Adg) { convertedModifiers = UboCosmeticRuleModifierConverter.convertFromAdg(rule.modifiers); } } const result = clone(rule); result.syntax = adblockers/* .AdblockSyntax.Ubo */.YG.Ubo; if (convertedModifiers && convertedModifiers.isConverted) { result.modifiers = convertedModifiers.result.modifierList; if (convertedModifiers.result.domains) { result.domains = convertedModifiers.result.domains; result.domains.separator = constants/* .COMMA */.KE; } } // Handle separator to uBO format let convertedSeparator = result.separator.value; convertedSeparator = rule.exception ? nodes/* .CosmeticRuleSeparator.ElementHidingException */.p5.ElementHidingException : nodes/* .CosmeticRuleSeparator.ElementHiding */.p5.ElementHiding; result.separator.value = convertedSeparator; return (0,conversion_result/* .createNodeConversionResult */.k)([result], true); } } // EXTERNAL MODULE: ./node_modules/.pnpm/@adguard+agtree@4.2.1/node_modules/@adguard/agtree/dist/compatibility-tables/modifiers.js + 1 modules var compatibility_tables_modifiers = __webpack_require__(6674); // EXTERNAL MODULE: ./node_modules/.pnpm/@adguard+agtree@4.2.1/node_modules/@adguard/agtree/dist/compatibility-tables/redirects.js var redirects = __webpack_require__(63780); // EXTERNAL MODULE: ./node_modules/.pnpm/@adguard+agtree@4.2.1/node_modules/@adguard/agtree/dist/compatibility-tables/utils/resource-type-helpers.js + 1 modules var resource_type_helpers = __webpack_require__(95473); ;// CONCATENATED MODULE: ./node_modules/.pnpm/@adguard+agtree@4.2.1/node_modules/@adguard/agtree/dist/converter/misc/network-rule-modifier.js /* * AGTree v4.2.1 (build date: Wed, 12 Aug 2026 01:31:02 GMT) * (c) 2026 Adguard Software Ltd. * Released under the MIT license * https://github.com/AdguardTeam/tsurlfilter/tree/master/packages/agtree#readme */ /** * @file Network rule modifier list converter. */ /** * @see {@link https://adguard.com/kb/general/ad-filtering/create-own-filters/#csp-modifier} */ const CSP_MODIFIER = 'csp'; const CSP_SEPARATOR = constants/* .SEMICOLON */.I8 + constants/* .SPACE */.t6; /** * @see {@link https://adguard.com/kb/general/ad-filtering/create-own-filters/#csp-modifier} * @see {@link https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy} */ const COMMON_CSP_PARAMS = '\'self\' \'unsafe-eval\' http: https: data: blob: mediastream: filesystem:'; /** * @see {@link https://help.adblockplus.org/hc/en-us/articles/360062733293#rewrite} */ const ABP_REWRITE_MODIFIER = 'rewrite'; /** * @see {@link https://adguard.com/kb/general/ad-filtering/create-own-filters/#redirect-modifier} */ const REDIRECT_MODIFIER = 'redirect'; /** * @see {@link https://adguard.com/kb/general/ad-filtering/create-own-filters/#redirect-rule-modifier} */ const REDIRECT_RULE_MODIFIER = 'redirect-rule'; /** * @see {@link https://github.com/gorhill/uBlock/wiki/Resources-Library#empty-redirect-resources} */ const UBO_NOOP_TEXT_RESOURCE = 'noop.txt'; /** * Redirect-related modifiers. */ const REDIRECT_MODIFIERS = new Set([ ABP_REWRITE_MODIFIER, REDIRECT_MODIFIER, REDIRECT_RULE_MODIFIER, ]); /** * Conversion map for ADG network rule modifiers. */ const ADG_CONVERSION_MAP = new Map([ ['1p', [{ name: () => 'third-party', exception: (actual) => !actual }]], ['3p', [{ name: () => 'third-party' }]], ['css', [{ name: () => 'stylesheet' }]], ['doc', [{ name: () => 'document' }]], ['ehide', [{ name: () => 'elemhide' }]], ['empty', [{ name: () => 'redirect', value: () => 'nooptext' }]], ['first-party', [{ name: () => 'third-party', exception: (actual) => !actual }]], ['frame', [{ name: () => 'subdocument' }]], ['ghide', [{ name: () => 'generichide' }]], ['inline-font', [{ name: () => CSP_MODIFIER, value: () => `font-src ${COMMON_CSP_PARAMS}` }]], ['inline-script', [{ name: () => CSP_MODIFIER, value: () => `script-src ${COMMON_CSP_PARAMS}` }]], ['mp4', [{ name: () => 'redirect', value: () => 'noopmp4-1s' }, { name: () => 'media', value: () => undefined }]], ['queryprune', [{ name: () => 'removeparam' }]], ['shide', [{ name: () => 'specifichide' }]], ['xhr', [{ name: () => 'xmlhttprequest' }]], ]); /** * Helper class for converting network rule modifier lists. * * @todo Implement `convertToUbo` and `convertToAbp`. */ class NetworkRuleModifierListConverter extends base_converter/* .BaseConverter */.I { /** * Converts a network rule modifier list to AdGuard format, if possible. * * @param modifierList Network rule modifier list node to convert. * @param isException If `true`, the rule is an exception rule. * * @returns An object which follows the {@link ConversionResult} interface. Its `result` property contains * the converted node, and its `isConverted` flag indicates whether the original node was converted. * If the node was not converted, the result will contain the original node with the same object reference. * * @throws If the conversion is not possible. */ static convertToAdg(modifierList, isException = false) { const conversionMap = new MultiValueMap(); // Special case: $csp modifier let cspCount = 0; modifierList.children.forEach((modifierNode, index) => { const modifierConversions = ADG_CONVERSION_MAP.get(modifierNode.name.value); if (modifierConversions) { for (const modifierConversion of modifierConversions) { const name = modifierConversion.name(modifierNode.name.value); const exception = modifierConversion.exception // If the exception value is undefined in the original modifier, it // means that the modifier isn't negated ? modifierConversion.exception(modifierNode.exception || false) : modifierNode.exception; const value = modifierConversion.value ? modifierConversion.value(modifierNode.value?.value) : modifierNode.value?.value; // Check if the name or the value is different from the original modifier // If so, add the converted modifier to the list if (name !== modifierNode.name.value || value !== modifierNode.value?.value) { conversionMap.add(index, createModifierNode(name, value, exception)); } // Special case: $csp modifier if (name === CSP_MODIFIER) { cspCount += 1; } } return; } // Handle special case: resource redirection modifiers if (REDIRECT_MODIFIERS.has(modifierNode.name.value)) { // Redirect modifiers can't be negated if (modifierNode.exception === true) { throw new RuleConversionError(`Modifier '${modifierNode.name.value}' cannot be negated`); } // Convert the redirect resource name to ADG format const redirectResource = modifierNode.value?.value; // Special case: for exception rules, $redirect without value is allowed, // and in this case it means an exception for all redirects if (!redirectResource && !isException) { throw new RuleConversionError(`No redirect resource specified for '${modifierNode.name.value}' modifier`); } // Leave $redirect and $redirect-rule modifiers as is, but convert $rewrite to $redirect const modifierName = modifierNode.name.value === ABP_REWRITE_MODIFIER ? REDIRECT_MODIFIER : modifierNode.name.value; const convertedRedirectResource = redirectResource ? redirects/* .redirectsCompatibilityTable */.S.getFirst(redirectResource, platforms/* .GenericPlatform.AdgAny */.p.AdgAny)?.name : undefined; // Check if the modifier name or the redirect resource name is different from the original modifier. // If so, add the converted modifier to the list if (modifierName !== modifierNode.name.value || (convertedRedirectResource !== undefined && convertedRedirectResource !== redirectResource)) { conversionMap.add(index, createModifierNode(modifierName, // If the redirect resource name is unknown, fall back to the original one // Later, the validator will throw an error if the resource name is invalid convertedRedirectResource || redirectResource, modifierNode.exception)); } } }); // Prepare the result if there are any converted modifiers or $csp modifiers if (conversionMap.size || cspCount) { const modifierListClone = cloneModifierListNode(modifierList); // Replace the original modifiers with the converted ones // One modifier may be replaced with multiple modifiers, so we need to flatten the array modifierListClone.children = modifierListClone.children.map((modifierNode, index) => { const conversionRecord = conversionMap.get(index); if (conversionRecord) { return conversionRecord; } return modifierNode; }).flat(); // Special case: $csp modifier: merge multiple $csp modifiers into one // and put it at the end of the modifier list if (cspCount) { const cspValues = []; modifierListClone.children = modifierListClone.children.filter((modifierNode) => { if (modifierNode.name.value === CSP_MODIFIER) { if (!modifierNode.value?.value) { throw new RuleConversionError('$csp modifier value is missing'); } cspValues.push(modifierNode.value?.value); return false; } return true; }); modifierListClone.children.push(createModifierNode(CSP_MODIFIER, cspValues.join(CSP_SEPARATOR))); } // Before returning the result, remove duplicated modifiers modifierListClone.children = modifierListClone.children.filter((modifierNode, index, self) => self.findIndex((m) => m.name.value === modifierNode.name.value && m.exception === modifierNode.exception && m.value?.value === modifierNode.value?.value) === index); return (0,conversion_result/* .createConversionResult */.c)(modifierListClone, true); } return (0,conversion_result/* .createConversionResult */.c)(modifierList, false); } /** * Converts a network rule modifier list to uBlock format, if possible. * * @param modifierList Network rule modifier list node to convert. * @param isException If `true`, the rule is an exception rule. * * @returns An object which follows the {@link ConversionResult} interface. Its `result` property contains * the converted node, and its `isConverted` flag indicates whether the original node was converted. * If the node was not converted, the result will contain the original node with the same object reference. * * @throws If the conversion is not possible. */ // TODO: Optimize static convertToUbo(modifierList, isException = false) { const conversionMap = new MultiValueMap(); const resourceTypeModifiersToAdd = new Set(); modifierList.children.forEach((modifierNode, index) => { const originalModifierName = modifierNode.name.value; const modifierData = compatibility_tables_modifiers/* .modifiersCompatibilityTable.getFirst */.Z.getFirst(originalModifierName, platforms/* .GenericPlatform.UboAny */.p.UboAny); // Handle special case: resource redirection modifiers if (REDIRECT_MODIFIERS.has(originalModifierName)) { // Redirect modifiers cannot be negated if (modifierNode.exception === true) { throw new RuleConversionError(`Modifier '${modifierNode.name.value}' cannot be negated`); } // Convert the redirect resource name to uBO format const redirectResourceName = modifierNode.value?.value; // Special case: for exception rules, $redirect without value is allowed, // and in this case it means an exception for all redirects if (!redirectResourceName && !isException) { throw new RuleConversionError(`No redirect resource specified for '${modifierNode.name.value}' modifier`); } if (!redirectResourceName) { // Jump to the next modifier if the redirect resource is not specified return; } // Leave $redirect and $redirect-rule modifiers as is, but convert $rewrite to $redirect const modifierName = modifierNode.name.value === ABP_REWRITE_MODIFIER ? REDIRECT_MODIFIER : modifierNode.name.value; const convertedRedirectResourceData = redirects/* .redirectsCompatibilityTable.getFirst */.S.getFirst(redirectResourceName, platforms/* .GenericPlatform.UboAny */.p.UboAny); const convertedRedirectResourceName = convertedRedirectResourceData?.name ?? redirectResourceName; // uBlock requires the $redirect modifier to have a resource type // https://github.com/AdguardTeam/Scriptlets/issues/101 if (convertedRedirectResourceData?.resourceTypes?.length) { // Convert the resource types to uBO modifiers const uboResourceTypeModifiers = redirects/* .redirectsCompatibilityTable.getResourceTypeModifiers */.S.getResourceTypeModifiers(convertedRedirectResourceData, platforms/* .GenericPlatform.UboAny */.p.UboAny); // Special case: noop text resource // If any of resource type is already present, we don't need to add other resource types, // otherwise, add all resource types // TODO: Optimize this logic // Check if the current resource is the noop text resource const isNoopTextResource = convertedRedirectResourceName === UBO_NOOP_TEXT_RESOURCE; // Determine if there are any valid resource types already present const hasValidResourceType = modifierList.children.some((modifier) => { const name = modifier.name.value; if (!(0,resource_type_helpers/* .isValidResourceType */.x)(name)) { return false; } const convertedModifierData = compatibility_tables_modifiers/* .modifiersCompatibilityTable.getFirst */.Z.getFirst(name, platforms/* .GenericPlatform.UboAny */.p.UboAny); return uboResourceTypeModifiers.has(convertedModifierData?.name ?? name); }); // If it's not the noop text resource or if no valid resource types are present if (!isNoopTextResource || !hasValidResourceType) { uboResourceTypeModifiers.forEach((resourceType) => { resourceTypeModifiersToAdd.add(resourceType); }); } } // Check if the modifier name or the redirect resource name is different from the original modifier. // If so, add the converted modifier to the list if (modifierName !== originalModifierName || (!(0,type_guards/* .isUndefined */.b0)(convertedRedirectResourceName) && convertedRedirectResourceName !== redirectResourceName)) { conversionMap.add(index, createModifierNode(modifierName, // If the redirect resource name is unknown, fall back to the original one // Later, the validator will throw an error if the resource name is invalid convertedRedirectResourceName || redirectResourceName, modifierNode.exception)); } return; } // Generic modifier conversion if (modifierData && modifierData.name !== originalModifierName) { conversionMap.add(index, createModifierNode(modifierData.name, modifierNode.value?.value, modifierNode.exception)); } }); // Prepare the result if there are any converted modifiers or $csp modifiers if (conversionMap.size || resourceTypeModifiersToAdd.size) { const modifierListClone = cloneModifierListNode(modifierList); // Replace the original modifiers with the converted ones // One modifier may be replaced with multiple modifiers, so we need to flatten the array modifierListClone.children = modifierListClone.children.map((modifierNode, index) => { const conversionRecord = conversionMap.get(index); if (conversionRecord) { return conversionRecord; } return modifierNode; }).flat(); // Before returning the result, remove duplicated modifiers modifierListClone.children = modifierListClone.children.filter((modifierNode, index, self) => self.findIndex((m) => m.name.value === modifierNode.name.value && m.exception === modifierNode.exception && m.value?.value === modifierNode.value?.value) === index); if (resourceTypeModifiersToAdd.size) { const modifierNameSet = new Set(modifierList.children.map((m) => m.name.value)); resourceTypeModifiersToAdd.forEach((resourceType) => { if (!modifierNameSet.has(resourceType)) { modifierListClone.children.push(createModifierNode(resourceType)); } }); } return (0,conversion_result/* .createConversionResult */.c)(modifierListClone, true); } return (0,conversion_result/* .createConversionResult */.c)(modifierList, false); } } ;// CONCATENATED MODULE: ./node_modules/.pnpm/@adguard+agtree@4.2.1/node_modules/@adguard/agtree/dist/converter/network/index.js /* * AGTree v4.2.1 (build date: Wed, 12 Aug 2026 01:31:02 GMT) * (c) 2026 Adguard Software Ltd. * Released under the MIT license * https://github.com/AdguardTeam/tsurlfilter/tree/master/packages/agtree#readme */ /** * @file Network rule converter. */ /** * Network rule converter class (also known as "basic rule converter"). * * @todo Implement `convertToUbo` and `convertToAbp`. */ class NetworkRuleConverter extends RuleConverterBase { /** * Converts a network rule to AdGuard format, if possible. * * @param rule Rule node to convert. * * @returns An object which follows the {@link NodeConversionResult} interface. Its `result` property contains * the array of converted rule nodes, and its `isConverted` flag indicates whether the original rule was converted. * If the rule was not converted, the result array will contain the original node with the same object reference. * * @throws If the rule is invalid or cannot be converted. */ static convertToAdg(rule) { // TODO: add support for host rules if (rule.type !== nodes/* .NetworkRuleType.NetworkRule */.vY.NetworkRule) { throw new Error(`Invalid rule type: ${rule.type}`); } if (rule.modifiers) { const modifiers = NetworkRuleModifierListConverter.convertToAdg(rule.modifiers, rule.exception); // If the object reference is different, it means that the modifiers were converted // In this case, we should clone the entire rule and replace the modifiers with the converted ones if (modifiers.isConverted) { return { result: [{ category: nodes/* .RuleCategory.Network */.$O.Network, type: nodes/* .NetworkRuleType.NetworkRule */.vY.NetworkRule, syntax: rule.syntax, exception: rule.exception, pattern: { type: 'Value', value: rule.pattern.value, }, modifiers: modifiers.result, }], isConverted: true, }; } } // If the modifiers were not converted, return the original rule return (0,conversion_result/* .createNodeConversionResult */.k)([rule], false); } /** * Converts a network rule to uBlock format, if possible. * * @param rule Rule node to convert. * * @returns An object which follows the {@link NodeConversionResult} interface. Its `result` property contains * the array of converted rule nodes, and its `isConverted` flag indicates whether the original rule was converted. * If the rule was not converted, the result array will contain the original node with the same object reference. * * @throws If the rule is invalid or cannot be converted. */ static convertToUbo(rule) { // TODO: add support for host rules if (rule.type !== nodes/* .NetworkRuleType.NetworkRule */.vY.NetworkRule) { throw new Error(`Invalid rule type: ${rule.type}`); } if (rule.modifiers) { const modifiers = NetworkRuleModifierListConverter.convertToUbo(rule.modifiers, rule.exception); // If the object reference is different, it means that the modifiers were converted // In this case, we should clone the entire rule and replace the modifiers with the converted ones if (modifiers.isConverted) { return { result: [{ category: nodes/* .RuleCategory.Network */.$O.Network, type: nodes/* .NetworkRuleType.NetworkRule */.vY.NetworkRule, syntax: rule.syntax, exception: rule.exception, pattern: { type: 'Value', value: rule.pattern.value, }, modifiers: modifiers.result, }], isConverted: true, }; } } // If the modifiers were not converted, return the original rule return (0,conversion_result/* .createNodeConversionResult */.k)([rule], false); } } ;// CONCATENATED MODULE: ./node_modules/.pnpm/@adguard+agtree@4.2.1/node_modules/@adguard/agtree/dist/converter/rule.js /* * AGTree v4.2.1 (build date: Wed, 12 Aug 2026 01:31:02 GMT) * (c) 2026 Adguard Software Ltd. * Released under the MIT license * https://github.com/AdguardTeam/tsurlfilter/tree/master/packages/agtree#readme */ /** * @file Adblock rule converter. * * This file is the entry point for all rule converters * which automatically detects the rule type and calls * the corresponding "sub-converter". */ /** * Adblock filtering rule converter class. * * @todo Implement `convertToUbo` and `convertToAbp`. */ class RuleConverter extends RuleConverterBase { /** * Converts an adblock filtering rule to AdGuard format, if possible. * * @param rule Rule node to convert. * * @returns An object which follows the {@link NodeConversionResult} interface. Its `result` property contains * the array of converted rule nodes, and its `isConverted` flag indicates whether the original rule was converted. * If the rule was not converted, the result array will contain the original node with the same object reference. * * @throws If the rule is invalid or cannot be converted. */ static convertToAdg(rule) { // Delegate conversion to the corresponding sub-converter // based on the rule category switch (rule.category) { case nodes/* .RuleCategory.Comment */.$O.Comment: return CommentRuleConverter.convertToAdg(rule); case nodes/* .RuleCategory.Cosmetic */.$O.Cosmetic: return CosmeticRuleConverter.convertToAdg(rule); case nodes/* .RuleCategory.Network */.$O.Network: // TODO: Handle hosts rules later if (rule.type === nodes/* .NetworkRuleType.HostRule */.vY.HostRule) { return (0,conversion_result/* .createConversionResult */.c)([rule], false); } return NetworkRuleConverter.convertToAdg(rule); case nodes/* .RuleCategory.Invalid */.$O.Invalid: case nodes/* .RuleCategory.Empty */.$O.Empty: // Just forward the rule as is return (0,conversion_result/* .createConversionResult */.c)([rule], false); default: // Never happens during normal operation throw new RuleConversionError('Unknown rule category'); } } /** * Converts an adblock filtering rule to uBlock Origin format, if possible. * * @param rule Rule node to convert. * * @returns An object which follows the {@link NodeConversionResult} interface. Its `result` property contains * the array of converted rule nodes, and its `isConverted` flag indicates whether the original rule was converted. * If the rule was not converted, the result array will contain the original node with the same object reference. * * @throws If the rule is invalid or cannot be converted. */ // TODO: Add support for other rule types static convertToUbo(rule) { if (rule.category === nodes/* .RuleCategory.Cosmetic */.$O.Cosmetic) { return CosmeticRuleConverter.convertToUbo(rule); } if (rule.category === nodes/* .RuleCategory.Network */.$O.Network) { return NetworkRuleConverter.convertToUbo(rule); } return (0,conversion_result/* .createConversionResult */.c)([rule], false); } } }, 10631(__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) { __webpack_require__.d(__webpack_exports__, { q: () => (AdblockSyntaxError) }); /* * AGTree v4.2.1 (build date: Wed, 12 Aug 2026 01:31:02 GMT) * (c) 2026 Adguard Software Ltd. * Released under the MIT license * https://github.com/AdguardTeam/tsurlfilter/tree/master/packages/agtree#readme */ /** * @file Customized syntax error class for Adblock Filter Parser. */ const ERROR_NAME = 'AdblockSyntaxError'; /** * Customized syntax error class for Adblock Filter Parser, * which contains the location range of the error. */ class AdblockSyntaxError extends SyntaxError { /** * Start offset of the error. */ start; /** * End offset of the error. */ end; /** * Constructs a new `AdblockSyntaxError` instance. * * @param message Error message. * @param start Start offset of the error. * @param end End offset of the error. */ constructor(message, start, end) { super(message); this.name = ERROR_NAME; this.start = start; this.end = end; } } }, 82535(__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) { __webpack_require__.d(__webpack_exports__, { E: () => (NotImplementedError) }); /* * AGTree v4.2.1 (build date: Wed, 12 Aug 2026 01:31:02 GMT) * (c) 2026 Adguard Software Ltd. * Released under the MIT license * https://github.com/AdguardTeam/tsurlfilter/tree/master/packages/agtree#readme */ /** * @file Customized error class for not implemented features. */ const ERROR_NAME = 'NotImplementedError'; const BASE_MESSAGE = 'Not implemented'; /** * Customized error class for not implemented features. */ class NotImplementedError extends Error { /** * Constructs a new `NotImplementedError` instance. * * @param message Additional error message (optional). */ constructor(message = undefined) { // Prepare the full error message const fullMessage = message ? `${BASE_MESSAGE}: ${message}` : BASE_MESSAGE; super(fullMessage); this.name = ERROR_NAME; } } }, 15987(__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) { __webpack_require__.d(__webpack_exports__, { t: () => (BaseGenerator) }); /* import */ var _errors_not_implemented_error_js__rspack_import_0 = __webpack_require__(82535); /* * AGTree v4.2.1 (build date: Wed, 12 Aug 2026 01:31:02 GMT) * (c) 2026 Adguard Software Ltd. * Released under the MIT license * https://github.com/AdguardTeam/tsurlfilter/tree/master/packages/agtree#readme */ /* eslint-disable @typescript-eslint/no-unused-vars */ /** * @file Base generator class. */ /** * Base class for generators. Each generator should extend this class. */ class BaseGenerator { /** * Generates a string from the AST node. * * @param node AST node to generate a string from. */ static generate(node) { throw new _errors_not_implemented_error_js__rspack_import_0/* .NotImplementedError */.E(); } } }, 82605(__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) { // EXPORTS __webpack_require__.d(__webpack_exports__, { H: () => (/* binding */ CosmeticRuleBodyGenerator) }); // EXTERNAL MODULE: ./node_modules/.pnpm/@adguard+agtree@4.2.1/node_modules/@adguard/agtree/dist/common/ubo-selector-common.js var ubo_selector_common = __webpack_require__(15862); // EXTERNAL MODULE: ./node_modules/.pnpm/@adguard+agtree@4.2.1/node_modules/@adguard/agtree/dist/nodes/index.js var nodes = __webpack_require__(79864); // EXTERNAL MODULE: ./node_modules/.pnpm/@adguard+agtree@4.2.1/node_modules/@adguard/agtree/dist/utils/adblockers.js var adblockers = __webpack_require__(22380); // EXTERNAL MODULE: ./node_modules/.pnpm/@adguard+agtree@4.2.1/node_modules/@adguard/agtree/dist/utils/constants.js var constants = __webpack_require__(53097); // EXTERNAL MODULE: ./node_modules/.pnpm/@adguard+agtree@4.2.1/node_modules/@adguard/agtree/dist/generator/base-generator.js var base_generator = __webpack_require__(15987); ;// CONCATENATED MODULE: ./node_modules/.pnpm/@adguard+agtree@4.2.1/node_modules/@adguard/agtree/dist/generator/css/adg-css-injection-generator.js /* * AGTree v4.2.1 (build date: Wed, 12 Aug 2026 01:31:02 GMT) * (c) 2026 Adguard Software Ltd. * Released under the MIT license * https://github.com/AdguardTeam/tsurlfilter/tree/master/packages/agtree#readme */ /** * AdGuard CSS injection generator. */ class AdgCssInjectionGenerator extends base_generator/* .BaseGenerator */.t { /** * CSS declaration for removing elements. */ static REMOVE_DECLARATION = 'remove: true;'; /** * Serializes an AdGuard CSS injection node into a raw string. * * @param node Node to serialize. * * @returns Raw string. */ static generate(node) { const result = []; if (node.mediaQueryList) { result.push(constants/* .CSS_MEDIA_MARKER */.Ae, constants/* .SPACE */.t6, node.mediaQueryList.value, constants/* .SPACE */.t6, constants/* .OPEN_CURLY_BRACKET */.sV, constants/* .SPACE */.t6); } result.push(node.selectorList.value, constants/* .SPACE */.t6, constants/* .OPEN_CURLY_BRACKET */.sV, constants/* .SPACE */.t6); if (node.remove) { result.push(AdgCssInjectionGenerator.REMOVE_DECLARATION); } else if (node.declarationList?.value) { result.push(node.declarationList.value); } result.push(constants/* .SPACE */.t6, constants/* .CLOSE_CURLY_BRACKET */.wU); if (node.mediaQueryList) { result.push(constants/* .SPACE */.t6, constants/* .CLOSE_CURLY_BRACKET */.wU); } return result.join(constants/* .EMPTY */.wg); } } // EXTERNAL MODULE: ./node_modules/.pnpm/@adguard+agtree@4.2.1/node_modules/@adguard/agtree/dist/generator/cosmetic/html-filtering-body/adg-html-filtering-body-generator.js var adg_html_filtering_body_generator = __webpack_require__(60646); // EXTERNAL MODULE: ./node_modules/.pnpm/@adguard+agtree@4.2.1/node_modules/@adguard/agtree/dist/generator/cosmetic/html-filtering-body/ubo-html-filtering-body-generator.js var ubo_html_filtering_body_generator = __webpack_require__(63836); // EXTERNAL MODULE: ./node_modules/.pnpm/@adguard+agtree@4.2.1/node_modules/@adguard/agtree/dist/common/abp-snippet-injection-body-common.js var abp_snippet_injection_body_common = __webpack_require__(7596); // EXTERNAL MODULE: ./node_modules/.pnpm/@adguard+agtree@4.2.1/node_modules/@adguard/agtree/dist/generator/misc/parameter-list-generator.js var parameter_list_generator = __webpack_require__(92835); ;// CONCATENATED MODULE: ./node_modules/.pnpm/@adguard+agtree@4.2.1/node_modules/@adguard/agtree/dist/generator/cosmetic/scriptlet-body/abp-snippet-injection-body-generator.js /* * AGTree v4.2.1 (build date: Wed, 12 Aug 2026 01:31:02 GMT) * (c) 2026 Adguard Software Ltd. * Released under the MIT license * https://github.com/AdguardTeam/tsurlfilter/tree/master/packages/agtree#readme */ /** * Adblock Plus snippet injection body generator. */ class AbpSnippetInjectionBodyGenerator extends base_generator/* .BaseGenerator */.t { /** * Generates a string representation of the Adblock Plus-style snippet call body. * * @param node Scriptlet injection rule body. * * @returns String representation of the rule body. * * @throws Error if the scriptlet call is empty. */ static generate(node) { const result = []; if (node.children.length === 0) { throw new Error(abp_snippet_injection_body_common/* .AbpSnippetInjectionBodyCommon.ERROR_MESSAGES.EMPTY_SCRIPTLET_CALL */.H.ERROR_MESSAGES.EMPTY_SCRIPTLET_CALL); } for (const scriptletCall of node.children) { if (scriptletCall.children.length === 0) { throw new Error(abp_snippet_injection_body_common/* .AbpSnippetInjectionBodyCommon.ERROR_MESSAGES.EMPTY_SCRIPTLET_CALL */.H.ERROR_MESSAGES.EMPTY_SCRIPTLET_CALL); } result.push(parameter_list_generator/* .ParameterListGenerator.generate */.H.generate(scriptletCall, constants/* .SPACE */.t6)); } return result.join(constants/* .SEMICOLON */.I8 + constants/* .SPACE */.t6); } } ;// CONCATENATED MODULE: ./node_modules/.pnpm/@adguard+agtree@4.2.1/node_modules/@adguard/agtree/dist/generator/cosmetic/scriptlet-body/adg-scriptlet-injection-body-generator.js /* * AGTree v4.2.1 (build date: Wed, 12 Aug 2026 01:31:02 GMT) * (c) 2026 Adguard Software Ltd. * Released under the MIT license * https://github.com/AdguardTeam/tsurlfilter/tree/master/packages/agtree#readme */ /** * AdGuard scriptlet injection body generator. */ class AdgScriptletInjectionBodyGenerator extends base_generator/* .BaseGenerator */.t { /** * Error messages used by the generator. */ static ERROR_MESSAGES = { NO_MULTIPLE_SCRIPTLET_CALLS: 'ADG syntaxes does not support multiple scriptlet calls within one single rule', }; /** * Generates a string representation of the AdGuard scriptlet call body. * * @param node Scriptlet injection rule body. * * @returns String representation of the rule body. * * @throws Error if the scriptlet call has multiple parameters. */ static generate(node) { const result = []; if (node.children.length > 1) { throw new Error(AdgScriptletInjectionBodyGenerator.ERROR_MESSAGES.NO_MULTIPLE_SCRIPTLET_CALLS); } result.push(constants/* .ADG_SCRIPTLET_MASK */.x$); result.push(constants/* .OPEN_PARENTHESIS */.Cx); if (node.children.length > 0) { result.push(parameter_list_generator/* .ParameterListGenerator.generate */.H.generate(node.children[0])); } result.push(constants/* .CLOSE_PARENTHESIS */.s1); return result.join(constants/* .EMPTY */.wg); } } ;// CONCATENATED MODULE: ./node_modules/.pnpm/@adguard+agtree@4.2.1/node_modules/@adguard/agtree/dist/generator/cosmetic/scriptlet-body/ubo-scriptlet-injection-body-generator.js /* * AGTree v4.2.1 (build date: Wed, 12 Aug 2026 01:31:02 GMT) * (c) 2026 Adguard Software Ltd. * Released under the MIT license * https://github.com/AdguardTeam/tsurlfilter/tree/master/packages/agtree#readme */ /** * UBlock scriptlet injection body generator. */ class UboScriptletInjectionBodyGenerator extends base_generator/* .BaseGenerator */.t { /** * Error messages used by the generator. */ static ERROR_MESSAGES = { NO_MULTIPLE_SCRIPTLET_CALLS: 'uBO syntaxes does not support multiple scriptlet calls within one single rule', }; /** * Generates a string representation of the uBlock scriptlet call body. * * @param node Scriptlet injection rule body. * * @returns String representation of the rule body. * * @throws Error if the scriptlet call has multiple parameters. */ static generate(node) { const result = []; if (node.children.length > 1) { throw new Error(UboScriptletInjectionBodyGenerator.ERROR_MESSAGES.NO_MULTIPLE_SCRIPTLET_CALLS); } // During generation, we only support the modern scriptlet mask result.push(constants/* .UBO_SCRIPTLET_MASK */.Rq); result.push(constants/* .OPEN_PARENTHESIS */.Cx); if (node.children.length > 0) { const [parameterListNode] = node.children; result.push(parameter_list_generator/* .ParameterListGenerator.generate */.H.generate(parameterListNode)); } result.push(constants/* .CLOSE_PARENTHESIS */.s1); return result.join(constants/* .EMPTY */.wg); } } ;// CONCATENATED MODULE: ./node_modules/.pnpm/@adguard+agtree@4.2.1/node_modules/@adguard/agtree/dist/generator/cosmetic/cosmetic-rule-body-generator.js /* * AGTree v4.2.1 (build date: Wed, 12 Aug 2026 01:31:02 GMT) * (c) 2026 Adguard Software Ltd. * Released under the MIT license * https://github.com/AdguardTeam/tsurlfilter/tree/master/packages/agtree#readme */ /** * Cosmetic rule body generator. */ class CosmeticRuleBodyGenerator extends base_generator/* .BaseGenerator */.t { /** * Generates the rule body from the node. * * @param node Cosmetic rule node. * * @returns Raw rule body. * * @throws Error if the rule type is unknown. * * @example * - '##.foo' → '.foo' * - 'example.com,example.org##.foo' → '.foo' * - 'example.com#%#//scriptlet('foo')' → '//scriptlet('foo')' */ static generate(node) { let result = constants/* .EMPTY */.wg; switch (node.type) { case nodes/* .CosmeticRuleType.ElementHidingRule */.k9.ElementHidingRule: result = node.body.selectorList.value; break; case nodes/* .CosmeticRuleType.CssInjectionRule */.k9.CssInjectionRule: if (node.syntax === adblockers/* .AdblockSyntax.Adg */.YG.Adg || node.syntax === adblockers/* .AdblockSyntax.Abp */.YG.Abp) { result = AdgCssInjectionGenerator.generate(node.body); } else if (node.syntax === adblockers/* .AdblockSyntax.Ubo */.YG.Ubo) { if (node.body.mediaQueryList) { result += constants/* .COLON */.oH; result += ubo_selector_common/* .UboPseudoName.MatchesMedia */.S.MatchesMedia; result += constants/* .OPEN_PARENTHESIS */.Cx; result += node.body.mediaQueryList.value; result += constants/* .CLOSE_PARENTHESIS */.s1; result += constants/* .SPACE */.t6; } result += node.body.selectorList.value; if (node.body.remove) { result += constants/* .COLON */.oH; result += ubo_selector_common/* .UboPseudoName.Remove */.S.Remove; result += constants/* .OPEN_PARENTHESIS */.Cx; result += constants/* .CLOSE_PARENTHESIS */.s1; } else if (node.body.declarationList) { result += constants/* .COLON */.oH; result += ubo_selector_common/* .UboPseudoName.Style */.S.Style; result += constants/* .OPEN_PARENTHESIS */.Cx; result += node.body.declarationList.value; result += constants/* .CLOSE_PARENTHESIS */.s1; } } break; case nodes/* .CosmeticRuleType.HtmlFilteringRule */.k9.HtmlFilteringRule: switch (node.syntax) { case adblockers/* .AdblockSyntax.Adg */.YG.Adg: result = adg_html_filtering_body_generator/* .AdgHtmlFilteringBodyGenerator.generate */.$.generate(node.body); break; case adblockers/* .AdblockSyntax.Ubo */.YG.Ubo: result = constants/* .UBO_HTML_MASK */._h + ubo_html_filtering_body_generator/* .UboHtmlFilteringBodyGenerator.generate */.b.generate(node.body); break; case adblockers/* .AdblockSyntax.Abp */.YG.Abp: throw new Error('ABP does not support HTML filtering rules'); default: throw new Error('HTML filtering rule should have an explicit syntax'); } break; case nodes/* .CosmeticRuleType.JsInjectionRule */.k9.JsInjectionRule: result = node.body.value; break; case nodes/* .CosmeticRuleType.ScriptletInjectionRule */.k9.ScriptletInjectionRule: switch (node.syntax) { case adblockers/* .AdblockSyntax.Adg */.YG.Adg: result = AdgScriptletInjectionBodyGenerator.generate(node.body); break; case adblockers/* .AdblockSyntax.Abp */.YG.Abp: result = AbpSnippetInjectionBodyGenerator.generate(node.body); break; case adblockers/* .AdblockSyntax.Ubo */.YG.Ubo: result = UboScriptletInjectionBodyGenerator.generate(node.body); break; default: throw new Error('Scriptlet rule should have an explicit syntax'); } break; default: throw new Error('Unknown cosmetic rule type'); } return result; } } }, 60646(__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) { __webpack_require__.d(__webpack_exports__, { $: () => (AdgHtmlFilteringBodyGenerator) }); /* import */ var _base_generator_js__rspack_import_0 = __webpack_require__(15987); /* import */ var _html_filtering_body_generator_js__rspack_import_1 = __webpack_require__(441); /* import */ var _utils_quotes_js__rspack_import_2 = __webpack_require__(68999); /* * AGTree v4.2.1 (build date: Wed, 12 Aug 2026 01:31:02 GMT) * (c) 2026 Adguard Software Ltd. * Released under the MIT license * https://github.com/AdguardTeam/tsurlfilter/tree/master/packages/agtree#readme */ /** * AdGuard HTML Filtering body generator. */ class AdgHtmlFilteringBodyGenerator extends _base_generator_js__rspack_import_0/* .BaseGenerator */.t { /** * Generates a string representation of the AdGuard HTML filtering rule body. * * @param node HTML filtering rule body. * * @returns String representation of the rule body. * * @throws Error if the rule body is invalid. */ static generate(node) { const raw = _html_filtering_body_generator_js__rspack_import_1/* .HtmlFilteringBodyGenerator.generate */.T.generate(node); return _utils_quotes_js__rspack_import_2/* .QuoteUtils.unescapeAttributeDoubleQuotes */.Qj.unescapeAttributeDoubleQuotes(raw); } } }, 441(__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) { // EXPORTS __webpack_require__.d(__webpack_exports__, { T: () => (/* binding */ HtmlFilteringBodyGenerator) }); // EXTERNAL MODULE: ./node_modules/.pnpm/@adguard+agtree@4.2.1/node_modules/@adguard/agtree/dist/generator/base-generator.js var base_generator = __webpack_require__(15987); // EXTERNAL MODULE: ./node_modules/.pnpm/@adguard+agtree@4.2.1/node_modules/@adguard/agtree/dist/generator/misc/value-generator.js var value_generator = __webpack_require__(47924); // EXTERNAL MODULE: ./node_modules/.pnpm/@adguard+agtree@4.2.1/node_modules/@adguard/agtree/dist/utils/constants.js var constants = __webpack_require__(53097); // EXTERNAL MODULE: ./node_modules/.pnpm/@adguard+agtree@4.2.1/node_modules/@adguard/agtree/dist/utils/quotes.js var quotes = __webpack_require__(68999); ;// CONCATENATED MODULE: ./node_modules/.pnpm/@adguard+agtree@4.2.1/node_modules/@adguard/agtree/dist/generator/cosmetic/selector/attribute-selector-generator.js /* * AGTree v4.2.1 (build date: Wed, 12 Aug 2026 01:31:02 GMT) * (c) 2026 Adguard Software Ltd. * Released under the MIT license * https://github.com/AdguardTeam/tsurlfilter/tree/master/packages/agtree#readme */ /** * Attribute selector generator. */ class AttributeSelectorGenerator extends base_generator/* .BaseGenerator */.t { /** * Generates a string representation of the attribute selector. * * @param node Attribute selector node. * * @returns String representation of the attribute selector. */ static generate(node) { const result = []; result.push(constants/* .OPEN_SQUARE_BRACKET */.cU); result.push(value_generator/* .ValueGenerator.generate */.R.generate(node.name)); if ('value' in node) { result.push(value_generator/* .ValueGenerator.generate */.R.generate(node.operator)); const generatedValue = value_generator/* .ValueGenerator.generate */.R.generate(node.value); const quotedValue = quotes/* .QuoteUtils.setStringQuoteType */.Qj.setStringQuoteType(generatedValue, quotes/* .QuoteType.Double */.XA.Double); result.push(quotedValue); if (node.flag) { result.push(constants/* .SPACE */.t6); result.push(value_generator/* .ValueGenerator.generate */.R.generate(node.flag)); } } result.push(constants/* .CLOSE_SQUARE_BRACKET */.A1); return result.join(constants/* .EMPTY */.wg); } } ;// CONCATENATED MODULE: ./node_modules/.pnpm/@adguard+agtree@4.2.1/node_modules/@adguard/agtree/dist/generator/cosmetic/selector/class-selector-generator.js /* * AGTree v4.2.1 (build date: Wed, 12 Aug 2026 01:31:02 GMT) * (c) 2026 Adguard Software Ltd. * Released under the MIT license * https://github.com/AdguardTeam/tsurlfilter/tree/master/packages/agtree#readme */ /** * Class selector generator. */ class ClassSelectorGenerator extends base_generator/* .BaseGenerator */.t { /** * Generates a string representation of the class selector. * * @param node Class selector node. * * @returns String representation of the class selector. */ static generate(node) { return constants/* .DOT */.y0 + node.value; } } ;// CONCATENATED MODULE: ./node_modules/.pnpm/@adguard+agtree@4.2.1/node_modules/@adguard/agtree/dist/generator/cosmetic/selector/id-selector-generator.js /* * AGTree v4.2.1 (build date: Wed, 12 Aug 2026 01:31:02 GMT) * (c) 2026 Adguard Software Ltd. * Released under the MIT license * https://github.com/AdguardTeam/tsurlfilter/tree/master/packages/agtree#readme */ /** * ID selector generator. */ class IdSelectorGenerator extends base_generator/* .BaseGenerator */.t { /** * Generates a string representation of the ID selector. * * @param node ID selector node. * * @returns String representation of the ID selector. */ static generate(node) { return constants/* .HASHMARK */.C + node.value; } } ;// CONCATENATED MODULE: ./node_modules/.pnpm/@adguard+agtree@4.2.1/node_modules/@adguard/agtree/dist/generator/cosmetic/selector/pseudo-class-selector-generator.js /* * AGTree v4.2.1 (build date: Wed, 12 Aug 2026 01:31:02 GMT) * (c) 2026 Adguard Software Ltd. * Released under the MIT license * https://github.com/AdguardTeam/tsurlfilter/tree/master/packages/agtree#readme */ /** * Pseudo-class selector generator. */ class PseudoClassSelectorGenerator extends base_generator/* .BaseGenerator */.t { /** * Generates a string representation of the pseudo-class selector. * * @param node Pseudo-class selector node. * * @returns String representation of the pseudo-class selector. */ static generate(node) { const result = []; result.push(constants/* .COLON */.oH); result.push(value_generator/* .ValueGenerator.generate */.R.generate(node.name)); if (node.argument) { result.push(constants/* .OPEN_PARENTHESIS */.Cx); result.push(value_generator/* .ValueGenerator.generate */.R.generate(node.argument)); result.push(constants/* .CLOSE_PARENTHESIS */.s1); } return result.join(constants/* .EMPTY */.wg); } } ;// CONCATENATED MODULE: ./node_modules/.pnpm/@adguard+agtree@4.2.1/node_modules/@adguard/agtree/dist/generator/cosmetic/selector/selector-combinator-generator.js /* * AGTree v4.2.1 (build date: Wed, 12 Aug 2026 01:31:02 GMT) * (c) 2026 Adguard Software Ltd. * Released under the MIT license * https://github.com/AdguardTeam/tsurlfilter/tree/master/packages/agtree#readme */ /** * Selector combinator generator. */ class SelectorCombinatorGenerator extends base_generator/* .BaseGenerator */.t { /** * Generates a string representation of the selector combinator. * * @param node Selector combinator node. * * @returns String representation of the selector combinator. */ static generate(node) { // For descendant combinator, we don't need to add spaces around it if (node.value === ' ') { return node.value; } return constants/* .SPACE */.t6 + node.value + constants/* .SPACE */.t6; } } ;// CONCATENATED MODULE: ./node_modules/.pnpm/@adguard+agtree@4.2.1/node_modules/@adguard/agtree/dist/generator/cosmetic/selector/type-selector-generator.js /* * AGTree v4.2.1 (build date: Wed, 12 Aug 2026 01:31:02 GMT) * (c) 2026 Adguard Software Ltd. * Released under the MIT license * https://github.com/AdguardTeam/tsurlfilter/tree/master/packages/agtree#readme */ /** * Type selector generator. */ class TypeSelectorGenerator extends base_generator/* .BaseGenerator */.t { /** * Generates a string representation of the type selector. * * @param node Type selector node. * * @returns String representation of the type selector. */ static generate(node) { return node.value; } } ;// CONCATENATED MODULE: ./node_modules/.pnpm/@adguard+agtree@4.2.1/node_modules/@adguard/agtree/dist/generator/cosmetic/selector/complex-selector-generator.js /* * AGTree v4.2.1 (build date: Wed, 12 Aug 2026 01:31:02 GMT) * (c) 2026 Adguard Software Ltd. * Released under the MIT license * https://github.com/AdguardTeam/tsurlfilter/tree/master/packages/agtree#readme */ /** * Complex selector generator. */ class ComplexSelectorGenerator extends base_generator/* .BaseGenerator */.t { /** * Generates a string representation of the complex selector. * * @param node Complex selector node. * * @returns String representation of the complex selector. * * @throws Error if the `node` is invalid. */ static generate(node) { if (node.children.length === 0) { throw new Error('Complex selector cannot be empty'); } const result = []; for (let i = 0; i < node.children.length; i += 1) { const selector = node.children[i]; const { type } = selector; // Validate that compound selectors are not empty if ((i === 0 || node.children[i - 1].type === 'SelectorCombinator') && type === 'SelectorCombinator') { throw new Error('Empty compound selector found'); } let selectorResult; switch (type) { case 'TypeSelector': selectorResult = TypeSelectorGenerator.generate(selector); break; case 'IdSelector': selectorResult = IdSelectorGenerator.generate(selector); break; case 'ClassSelector': selectorResult = ClassSelectorGenerator.generate(selector); break; case 'AttributeSelector': selectorResult = AttributeSelectorGenerator.generate(selector); break; case 'PseudoClassSelector': selectorResult = PseudoClassSelectorGenerator.generate(selector); break; case 'SelectorCombinator': selectorResult = SelectorCombinatorGenerator.generate(selector); break; default: throw new Error(`Unknown selector type: ${type}`); } result.push(selectorResult); } return result.join(constants/* .EMPTY */.wg); } } ;// CONCATENATED MODULE: ./node_modules/.pnpm/@adguard+agtree@4.2.1/node_modules/@adguard/agtree/dist/generator/cosmetic/selector/selector-list-generator.js /* * AGTree v4.2.1 (build date: Wed, 12 Aug 2026 01:31:02 GMT) * (c) 2026 Adguard Software Ltd. * Released under the MIT license * https://github.com/AdguardTeam/tsurlfilter/tree/master/packages/agtree#readme */ /** * Selector list generator. */ class SelectorListGenerator extends base_generator/* .BaseGenerator */.t { /** * Generates a string representation of the selector list. * * @param node Selector list node. * * @returns String representation of the selector list. * * @throws Error if the `node` is invalid. */ static generate(node) { if (node.children.length === 0) { throw new Error('Selector list cannot be empty'); } const result = []; for (let i = 0; i < node.children.length; i += 1) { const complexSelector = node.children[i]; if (i > 0) { result.push(constants/* .COMMA */.KE); result.push(constants/* .SPACE */.t6); } result.push(ComplexSelectorGenerator.generate(complexSelector)); } return result.join(constants/* .EMPTY */.wg); } } ;// CONCATENATED MODULE: ./node_modules/.pnpm/@adguard+agtree@4.2.1/node_modules/@adguard/agtree/dist/generator/cosmetic/html-filtering-body/html-filtering-body-generator.js /* * AGTree v4.2.1 (build date: Wed, 12 Aug 2026 01:31:02 GMT) * (c) 2026 Adguard Software Ltd. * Released under the MIT license * https://github.com/AdguardTeam/tsurlfilter/tree/master/packages/agtree#readme */ /** * HTML Filtering body generator. */ class HtmlFilteringBodyGenerator extends base_generator/* .BaseGenerator */.t { /** * Generates a string representation of the HTML filtering rule body. * * @param node HTML filtering rule body. * * @returns String representation of the rule body. * * @throws Error if the rule body is invalid. */ static generate(node) { if (node.type === 'Value') { return value_generator/* .ValueGenerator.generate */.R.generate(node); } return SelectorListGenerator.generate(node.selectorList); } } }, 63836(__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) { __webpack_require__.d(__webpack_exports__, { b: () => (UboHtmlFilteringBodyGenerator) }); /* import */ var _common_ubo_html_filtering_body_common_js__rspack_import_2 = __webpack_require__(76466); /* import */ var _utils_constants_js__rspack_import_4 = __webpack_require__(53097); /* import */ var _base_generator_js__rspack_import_0 = __webpack_require__(15987); /* import */ var _misc_value_generator_js__rspack_import_3 = __webpack_require__(47924); /* import */ var _html_filtering_body_generator_js__rspack_import_1 = __webpack_require__(441); /* * AGTree v4.2.1 (build date: Wed, 12 Aug 2026 01:31:02 GMT) * (c) 2026 Adguard Software Ltd. * Released under the MIT license * https://github.com/AdguardTeam/tsurlfilter/tree/master/packages/agtree#readme */ /** * UBlock HTML Filtering body generator. */ class UboHtmlFilteringBodyGenerator extends _base_generator_js__rspack_import_0/* .BaseGenerator */.t { /** * Generates a string representation of the uBlock HTML filtering rule body * and also uBlock-style response header removal rules. * * @param node HTML filtering rule body. * * @returns String representation of the rule body. * * @throws Error if the rule body is invalid. */ static generate(node) { // First, check if it's a response header removal rule and return if so const responseHeaderBody = UboHtmlFilteringBodyGenerator.generateResponseHeaderRule(node); if (responseHeaderBody !== null) { return responseHeaderBody; } return _html_filtering_body_generator_js__rspack_import_1/* .HtmlFilteringBodyGenerator.generate */.T.generate(node); } /** * Generates a string representation of the uBlock-style response header removal rule. * * @param node Potential response header removal rule node. * * @returns String representation of the response header removal rule, * or `null` if the node is not a response header removal rule. * * @note This method accepts `HtmlFilteringRuleBody` as `node` because, * response header removal rule syntax is same as uBlock-style HTML filtering rule syntax. */ static generateResponseHeaderRule(node) { if (node.type !== 'HtmlFilteringRuleBody' || !(0,_common_ubo_html_filtering_body_common_js__rspack_import_2/* .isUboResponseHeaderRemovalRuleBody */.l)(node)) { return null; } // Length of AST nodes, types of nodes, non-null argument // check are already done in `isUboResponseHeaderRemovalRuleBody()` const { selectorList } = node; const complexSelector = selectorList.children[0]; const pseudoClass = complexSelector.children[0]; const headerName = _misc_value_generator_js__rspack_import_3/* .ValueGenerator.generate */.R.generate(pseudoClass.argument); const result = []; result.push(_utils_constants_js__rspack_import_4/* .UBO_RESPONSEHEADER_FN */.Bt); result.push(_utils_constants_js__rspack_import_4/* .OPEN_PARENTHESIS */.Cx); result.push(headerName); result.push(_utils_constants_js__rspack_import_4/* .CLOSE_PARENTHESIS */.s1); return result.join(_utils_constants_js__rspack_import_4/* .EMPTY */.wg); } } }, 92835(__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) { __webpack_require__.d(__webpack_exports__, { H: () => (ParameterListGenerator) }); /* import */ var _utils_constants_js__rspack_import_1 = __webpack_require__(53097); /* import */ var _base_generator_js__rspack_import_0 = __webpack_require__(15987); /* import */ var _value_generator_js__rspack_import_2 = __webpack_require__(47924); /* * AGTree v4.2.1 (build date: Wed, 12 Aug 2026 01:31:02 GMT) * (c) 2026 Adguard Software Ltd. * Released under the MIT license * https://github.com/AdguardTeam/tsurlfilter/tree/master/packages/agtree#readme */ /** * Generator for parameter list nodes. */ class ParameterListGenerator extends _base_generator_js__rspack_import_0/* .BaseGenerator */.t { /** * Converts a parameter list AST to a string. * * @param params Parameter list AST. * @param separator Separator character (default: comma). * @param allowSpace Allow space between parameters (default: true). * * @returns String representation of the parameter list. */ static generate(params, separator = _utils_constants_js__rspack_import_1/* .COMMA */.KE, allowSpace = true) { const collection = []; let i = 0; for (; i < params.children.length; i += 1) { const param = params.children[i]; if (param === null) { collection.push(_utils_constants_js__rspack_import_1/* .EMPTY */.wg); } else { collection.push(_value_generator_js__rspack_import_2/* .ValueGenerator.generate */.R.generate(param)); } } let result = _utils_constants_js__rspack_import_1/* .EMPTY */.wg; // if allowSpace is true, join with a single separator // without space if (!allowSpace && separator !== _utils_constants_js__rspack_import_1/* .SPACE */.t6) { result = collection.join(separator); } else { // join parameters with separator // if the separator is a space, join with a single space result = collection.join(separator === _utils_constants_js__rspack_import_1/* .SPACE */.t6 ? separator : `${separator}${_utils_constants_js__rspack_import_1/* .SPACE */.t6}`); } return result; } } }, 47924(__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) { __webpack_require__.d(__webpack_exports__, { R: () => (ValueGenerator) }); /* import */ var _base_generator_js__rspack_import_0 = __webpack_require__(15987); /* * AGTree v4.2.1 (build date: Wed, 12 Aug 2026 01:31:02 GMT) * (c) 2026 Adguard Software Ltd. * Released under the MIT license * https://github.com/AdguardTeam/tsurlfilter/tree/master/packages/agtree#readme */ /** * Generator for value nodes. */ class ValueGenerator extends _base_generator_js__rspack_import_0/* .BaseGenerator */.t { /** * Converts a value node to a string. * * @param node Value node. * * @returns Raw string. */ static generate(node) { return node.value; } } }, 11598(__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) { // EXPORTS __webpack_require__.d(__webpack_exports__, { u: () => (/* binding */ RuleGenerator) }); // EXTERNAL MODULE: ./node_modules/.pnpm/@adguard+agtree@4.2.1/node_modules/@adguard/agtree/dist/nodes/index.js var nodes = __webpack_require__(79864); // EXTERNAL MODULE: ./node_modules/.pnpm/@adguard+agtree@4.2.1/node_modules/@adguard/agtree/dist/utils/constants.js var constants = __webpack_require__(53097); // EXTERNAL MODULE: ./node_modules/.pnpm/@adguard+agtree@4.2.1/node_modules/@adguard/agtree/dist/generator/base-generator.js var base_generator = __webpack_require__(15987); // EXTERNAL MODULE: ./node_modules/.pnpm/@adguard+agtree@4.2.1/node_modules/@adguard/agtree/dist/utils/type-guards.js var type_guards = __webpack_require__(64505); ;// CONCATENATED MODULE: ./node_modules/.pnpm/@adguard+agtree@4.2.1/node_modules/@adguard/agtree/dist/generator/comment/agent-generator.js /* * AGTree v4.2.1 (build date: Wed, 12 Aug 2026 01:31:02 GMT) * (c) 2026 Adguard Software Ltd. * Released under the MIT license * https://github.com/AdguardTeam/tsurlfilter/tree/master/packages/agtree#readme */ /** * Generator for adblock agent nodes. * This class is responsible for converting adblock agent nodes into their string representation. */ class AgentGenerator extends base_generator/* .BaseGenerator */.t { /** * Converts an adblock agent node to a string. * * @param value Agent node. * * @returns Raw string. */ static generate(value) { let result = constants/* .EMPTY */.wg; // Agent adblock name result += value.adblock.value; // Agent adblock version (if present) if (!(0,type_guards/* .isUndefined */.b0)(value.version)) { // Add a space between the name and the version result += constants/* .SPACE */.t6; result += value.version.value; } return result; } } ;// CONCATENATED MODULE: ./node_modules/.pnpm/@adguard+agtree@4.2.1/node_modules/@adguard/agtree/dist/generator/comment/agent-comment-generator.js /* * AGTree v4.2.1 (build date: Wed, 12 Aug 2026 01:31:02 GMT) * (c) 2026 Adguard Software Ltd. * Released under the MIT license * https://github.com/AdguardTeam/tsurlfilter/tree/master/packages/agtree#readme */ /** * Generator for agent comment rules. */ class AgentCommentGenerator extends base_generator/* .BaseGenerator */.t { /** * Converts an adblock agent AST to a string. * * @param ast Agent rule AST. * * @returns Raw string. */ static generate(ast) { let result = constants/* .OPEN_SQUARE_BRACKET */.cU; result += ast.children .map(AgentGenerator.generate) .join(constants/* .SEMICOLON */.I8 + constants/* .SPACE */.t6); result += constants/* .CLOSE_SQUARE_BRACKET */.A1; return result; } } // EXTERNAL MODULE: ./node_modules/.pnpm/@adguard+agtree@4.2.1/node_modules/@adguard/agtree/dist/generator/misc/parameter-list-generator.js var parameter_list_generator = __webpack_require__(92835); ;// CONCATENATED MODULE: ./node_modules/.pnpm/@adguard+agtree@4.2.1/node_modules/@adguard/agtree/dist/generator/comment/config-comment-generator.js /* * AGTree v4.2.1 (build date: Wed, 12 Aug 2026 01:31:02 GMT) * (c) 2026 Adguard Software Ltd. * Released under the MIT license * https://github.com/AdguardTeam/tsurlfilter/tree/master/packages/agtree#readme */ /** * Converts inline configuration comment nodes to their string format. */ class ConfigCommentGenerator extends base_generator/* .BaseGenerator */.t { /** * Converts an inline configuration comment node to a string. * * @param node Inline configuration comment node. * * @returns Raw string. */ static generate(node) { let result = constants/* .EMPTY */.wg; result += node.marker.value; result += constants/* .SPACE */.t6; result += node.command.value; if (node.params) { result += constants/* .SPACE */.t6; if (node.params.type === 'ParameterList') { result += parameter_list_generator/* .ParameterListGenerator.generate */.H.generate(node.params, constants/* .COMMA */.KE); } else { // Trim JSON boundaries result += JSON.stringify(node.params.value).slice(1, -1).trim(); } } // Add comment within the config comment if (node.comment) { result += constants/* .SPACE */.t6; result += node.comment.value; } return result; } } ;// CONCATENATED MODULE: ./node_modules/.pnpm/@adguard+agtree@4.2.1/node_modules/@adguard/agtree/dist/generator/comment/hint-generator.js /* * AGTree v4.2.1 (build date: Wed, 12 Aug 2026 01:31:02 GMT) * (c) 2026 Adguard Software Ltd. * Released under the MIT license * https://github.com/AdguardTeam/tsurlfilter/tree/master/packages/agtree#readme */ /** * Hint generator. */ class HintGenerator extends base_generator/* .BaseGenerator */.t { /** * Generates a string representation of a hint. * * @param hint Hint AST node. * * @returns String representation of the hint. */ static generate(hint) { let result = constants/* .EMPTY */.wg; result += hint.name.value; if (hint.params && hint.params.children.length > 0) { result += constants/* .OPEN_PARENTHESIS */.Cx; result += parameter_list_generator/* .ParameterListGenerator.generate */.H.generate(hint.params, constants/* .COMMA */.KE); result += constants/* .CLOSE_PARENTHESIS */.s1; } return result; } } ;// CONCATENATED MODULE: ./node_modules/.pnpm/@adguard+agtree@4.2.1/node_modules/@adguard/agtree/dist/generator/comment/hint-comment-generator.js /* * AGTree v4.2.1 (build date: Wed, 12 Aug 2026 01:31:02 GMT) * (c) 2026 Adguard Software Ltd. * Released under the MIT license * https://github.com/AdguardTeam/tsurlfilter/tree/master/packages/agtree#readme */ /** * Hint comment generator. */ class HintCommentGenerator extends base_generator/* .BaseGenerator */.t { /** * Converts a hint rule node to a raw string. * * @param node Hint rule node. * * @returns Raw string. */ static generate(node) { let result = constants/* .HINT_MARKER */.j6 + constants/* .SPACE */.t6; result += node.children.map(HintGenerator.generate).join(constants/* .SPACE */.t6); return result; } } // EXTERNAL MODULE: ./node_modules/.pnpm/@adguard+agtree@4.2.1/node_modules/@adguard/agtree/dist/generator/misc/value-generator.js var value_generator = __webpack_require__(47924); ;// CONCATENATED MODULE: ./node_modules/.pnpm/@adguard+agtree@4.2.1/node_modules/@adguard/agtree/dist/generator/comment/metadata-comment-generator.js /* * AGTree v4.2.1 (build date: Wed, 12 Aug 2026 01:31:02 GMT) * (c) 2026 Adguard Software Ltd. * Released under the MIT license * https://github.com/AdguardTeam/tsurlfilter/tree/master/packages/agtree#readme */ /** * Metadata comment generator. */ class MetadataCommentGenerator extends base_generator/* .BaseGenerator */.t { /** * Converts a metadata comment rule node to a string. * * @param node Metadata comment rule node. * * @returns Raw string. */ static generate(node) { let result = constants/* .EMPTY */.wg; result += value_generator/* .ValueGenerator.generate */.R.generate(node.marker); result += constants/* .SPACE */.t6; result += value_generator/* .ValueGenerator.generate */.R.generate(node.header); result += constants/* .COLON */.oH; result += constants/* .SPACE */.t6; result += value_generator/* .ValueGenerator.generate */.R.generate(node.value); return result; } } // EXTERNAL MODULE: ./node_modules/.pnpm/@adguard+agtree@4.2.1/node_modules/@adguard/agtree/dist/parser/misc/logical-expression-parser.js var logical_expression_parser = __webpack_require__(48609); ;// CONCATENATED MODULE: ./node_modules/.pnpm/@adguard+agtree@4.2.1/node_modules/@adguard/agtree/dist/generator/misc/logical-expression-generator.js /* * AGTree v4.2.1 (build date: Wed, 12 Aug 2026 01:31:02 GMT) * (c) 2026 Adguard Software Ltd. * Released under the MIT license * https://github.com/AdguardTeam/tsurlfilter/tree/master/packages/agtree#readme */ /** * Generator for logical expression nodes. */ class LogicalExpressionGenerator extends base_generator/* .BaseGenerator */.t { /** * Generates a string representation of the logical expression (serialization). * * @param node Expression node. * * @returns String representation of the logical expression. */ static generate(node) { if (node.type === logical_expression_parser/* .NodeType.Variable */.Z.Variable) { return node.name; } if (node.type === logical_expression_parser/* .NodeType.Operator */.Z.Operator) { const left = LogicalExpressionGenerator.generate(node.left); const right = node.right ? LogicalExpressionGenerator.generate(node.right) : undefined; const { operator } = node; // Special case for NOT operator if (operator === nodes/* .OperatorValue.Not */.oC.Not) { return `${operator}${left}`; } // Right operand is required for AND and OR operators if (!right) { throw new Error('Expected right operand'); } return `${left} ${operator} ${right}`; } if (node.type === logical_expression_parser/* .NodeType.Parenthesis */.Z.Parenthesis) { const expressionString = LogicalExpressionGenerator.generate(node.expression); return `(${expressionString})`; } // Theoretically, this shouldn't happen if the library is used correctly throw new Error('Unexpected node type'); } } ;// CONCATENATED MODULE: ./node_modules/.pnpm/@adguard+agtree@4.2.1/node_modules/@adguard/agtree/dist/generator/comment/pre-processor-comment-generator.js /* * AGTree v4.2.1 (build date: Wed, 12 Aug 2026 01:31:02 GMT) * (c) 2026 Adguard Software Ltd. * Released under the MIT license * https://github.com/AdguardTeam/tsurlfilter/tree/master/packages/agtree#readme */ /** * Pre-processor comment generator. */ class PreProcessorCommentGenerator extends base_generator/* .BaseGenerator */.t { /** * Converts a pre-processor comment node to a string. * * @param node Pre-processor comment node. * * @returns Raw string. */ static generate(node) { let result = constants/* .EMPTY */.wg; result += constants/* .PREPROCESSOR_MARKER */.PD; result += node.name.value; if (node.params) { let allowSpaceBetweenParams = true; // Space between cb is not allowed for "safari_cb_affinity" directive. if (node.name.value === constants/* .SAFARI_CB_AFFINITY */.us) { allowSpaceBetweenParams = false; } // Space is not allowed after "safari_cb_affinity" directive, so we need to handle it separately. if (node.name.value !== constants/* .SAFARI_CB_AFFINITY */.us) { result += constants/* .SPACE */.t6; } if (node.params.type === 'Value') { result += value_generator/* .ValueGenerator.generate */.R.generate(node.params); } else if (node.params.type === 'ParameterList') { result += constants/* .OPEN_PARENTHESIS */.Cx; result += parameter_list_generator/* .ParameterListGenerator.generate */.H.generate(node.params, constants/* .COMMA */.KE, allowSpaceBetweenParams); result += constants/* .CLOSE_PARENTHESIS */.s1; } else { result += LogicalExpressionGenerator.generate(node.params); } } return result; } } ;// CONCATENATED MODULE: ./node_modules/.pnpm/@adguard+agtree@4.2.1/node_modules/@adguard/agtree/dist/generator/comment/simple-comment-generator.js /* * AGTree v4.2.1 (build date: Wed, 12 Aug 2026 01:31:02 GMT) * (c) 2026 Adguard Software Ltd. * Released under the MIT license * https://github.com/AdguardTeam/tsurlfilter/tree/master/packages/agtree#readme */ /** * Simple comment generator. */ class SimpleCommentGenerator extends base_generator/* .BaseGenerator */.t { /** * Converts a comment rule node to a string. * * @param node Comment rule node. * * @returns Raw string. */ static generate(node) { let result = constants/* .EMPTY */.wg; result += value_generator/* .ValueGenerator.generate */.R.generate(node.marker); result += value_generator/* .ValueGenerator.generate */.R.generate(node.text); return result; } } ;// CONCATENATED MODULE: ./node_modules/.pnpm/@adguard+agtree@4.2.1/node_modules/@adguard/agtree/dist/generator/comment/comment-rule-generator.js /* * AGTree v4.2.1 (build date: Wed, 12 Aug 2026 01:31:02 GMT) * (c) 2026 Adguard Software Ltd. * Released under the MIT license * https://github.com/AdguardTeam/tsurlfilter/tree/master/packages/agtree#readme */ /* eslint-disable no-param-reassign */ /** * `CommentRuleGenerator` is responsible for generating any comment-like adblock rules. */ class CommentRuleGenerator extends base_generator/* .BaseGenerator */.t { /** * Converts a comment rule node to a string. * * @param node Comment rule node. * * @returns Raw string. */ static generate(node) { switch (node.type) { case nodes/* .CommentRuleType.AgentCommentRule */.gV.AgentCommentRule: return AgentCommentGenerator.generate(node); case nodes/* .CommentRuleType.HintCommentRule */.gV.HintCommentRule: return HintCommentGenerator.generate(node); case nodes/* .CommentRuleType.PreProcessorCommentRule */.gV.PreProcessorCommentRule: return PreProcessorCommentGenerator.generate(node); case nodes/* .CommentRuleType.MetadataCommentRule */.gV.MetadataCommentRule: return MetadataCommentGenerator.generate(node); case nodes/* .CommentRuleType.ConfigCommentRule */.gV.ConfigCommentRule: return ConfigCommentGenerator.generate(node); case nodes/* .CommentRuleType.CommentRule */.gV.CommentRule: return SimpleCommentGenerator.generate(node); default: throw new Error('Unknown comment rule type'); } } } // EXTERNAL MODULE: ./node_modules/.pnpm/@adguard+agtree@4.2.1/node_modules/@adguard/agtree/dist/utils/adblockers.js var adblockers = __webpack_require__(22380); // EXTERNAL MODULE: ./node_modules/.pnpm/@adguard+agtree@4.2.1/node_modules/@adguard/agtree/dist/generator/cosmetic/cosmetic-rule-body-generator.js + 4 modules var cosmetic_rule_body_generator = __webpack_require__(82605); ;// CONCATENATED MODULE: ./node_modules/.pnpm/@adguard+agtree@4.2.1/node_modules/@adguard/agtree/dist/generator/misc/list-items-generator.js /* * AGTree v4.2.1 (build date: Wed, 12 Aug 2026 01:31:02 GMT) * (c) 2026 Adguard Software Ltd. * Released under the MIT license * https://github.com/AdguardTeam/tsurlfilter/tree/master/packages/agtree#readme */ /** * Utility class for generating string representations of list items. */ class ListItemsGenerator { /** * Generates a string representation of a list item. * * @template T Type of the list item. * * @param item List item to generate. * * @returns String representation of the list item. */ static generateListItem = (item) => { return `${item.exception ? constants/* .NEGATION_MARKER */.bP : constants/* .EMPTY */.wg}${item.value}`; }; /** * Generates a string representation of a list of items. * * @template T Type of the list items. * * @param items List of items to generate. * @param separator Separator character. * * @returns String representation of the list of items. */ static generate = (items, separator) => { return items.map(ListItemsGenerator.generateListItem) .join(separator); }; } ;// CONCATENATED MODULE: ./node_modules/.pnpm/@adguard+agtree@4.2.1/node_modules/@adguard/agtree/dist/generator/misc/domain-list-generator.js /* * AGTree v4.2.1 (build date: Wed, 12 Aug 2026 01:31:02 GMT) * (c) 2026 Adguard Software Ltd. * Released under the MIT license * https://github.com/AdguardTeam/tsurlfilter/tree/master/packages/agtree#readme */ /** * Domain list generator. */ class DomainListGenerator extends base_generator/* .BaseGenerator */.t { /** * Converts a domain list node to a string. * * @param node Domain list node. * * @returns Raw string. */ static generate(node) { return ListItemsGenerator.generate(node.children, node.separator); } } ;// CONCATENATED MODULE: ./node_modules/.pnpm/@adguard+agtree@4.2.1/node_modules/@adguard/agtree/dist/generator/misc/modifier-generator.js /* * AGTree v4.2.1 (build date: Wed, 12 Aug 2026 01:31:02 GMT) * (c) 2026 Adguard Software Ltd. * Released under the MIT license * https://github.com/AdguardTeam/tsurlfilter/tree/master/packages/agtree#readme */ /** * Generator for modifier nodes. */ class ModifierGenerator extends base_generator/* .BaseGenerator */.t { /** * Converts a modifier AST node to a string. * * @param modifier Modifier AST node to convert. * * @returns String representation of the modifier. */ static generate(modifier) { let result = constants/* .EMPTY */.wg; if (modifier.exception) { result += constants/* .NEGATION_MARKER */.bP; } result += modifier.name.value; if (modifier.value !== undefined) { result += constants/* .MODIFIER_ASSIGN_OPERATOR */.li; result += modifier.value.value; } return result; } } ;// CONCATENATED MODULE: ./node_modules/.pnpm/@adguard+agtree@4.2.1/node_modules/@adguard/agtree/dist/generator/misc/modifier-list-generator.js /* * AGTree v4.2.1 (build date: Wed, 12 Aug 2026 01:31:02 GMT) * (c) 2026 Adguard Software Ltd. * Released under the MIT license * https://github.com/AdguardTeam/tsurlfilter/tree/master/packages/agtree#readme */ /** * Generator for modifier list nodes. */ class ModifierListGenerator extends base_generator/* .BaseGenerator */.t { /** * Converts a modifier list AST to a string. * * @param ast Modifier list AST. * * @returns Raw string. */ static generate(ast) { const result = ast.children .map(ModifierGenerator.generate) .join(constants/* .MODIFIERS_SEPARATOR */.b9); return result; } } ;// CONCATENATED MODULE: ./node_modules/.pnpm/@adguard+agtree@4.2.1/node_modules/@adguard/agtree/dist/generator/cosmetic/cosmetic-rule-pattern-generator.js /* * AGTree v4.2.1 (build date: Wed, 12 Aug 2026 01:31:02 GMT) * (c) 2026 Adguard Software Ltd. * Released under the MIT license * https://github.com/AdguardTeam/tsurlfilter/tree/master/packages/agtree#readme */ /** * Cosmetic rule pattern generator. */ class CosmeticRulePatternGenerator extends base_generator/* .BaseGenerator */.t { /** * Generates the rule pattern from the AST. * * @param node Cosmetic rule node. * * @returns Raw rule pattern. * * @example * - '##.foo' → '' * - 'example.com,example.org##.foo' → 'example.com,example.org' * - '[$path=/foo/bar]example.com##.foo' → '[$path=/foo/bar]example.com' */ static generate(node) { let result = constants/* .EMPTY */.wg; // AdGuard modifiers (if any) if (node.syntax === adblockers/* .AdblockSyntax.Adg */.YG.Adg && node.modifiers && node.modifiers.children.length > 0) { result += constants/* .OPEN_SQUARE_BRACKET */.cU; result += constants/* .DOLLAR_SIGN */.nj; result += ModifierListGenerator.generate(node.modifiers); result += constants/* .CLOSE_SQUARE_BRACKET */.A1; } // Domain list (if any) result += DomainListGenerator.generate(node.domains); return result; } } ;// CONCATENATED MODULE: ./node_modules/.pnpm/@adguard+agtree@4.2.1/node_modules/@adguard/agtree/dist/generator/cosmetic/cosmetic-rule-generator.js /* * AGTree v4.2.1 (build date: Wed, 12 Aug 2026 01:31:02 GMT) * (c) 2026 Adguard Software Ltd. * Released under the MIT license * https://github.com/AdguardTeam/tsurlfilter/tree/master/packages/agtree#readme */ /** * `CosmeticRuleGenerator` is responsible for generating cosmetic rules from their AST representation. * * This class takes a parsed cosmetic rule Abstract Syntax Tree (AST) and converts it back into a raw string format. * It handles the generation of the pattern, separator, uBO rule modifiers, and the rule body. */ class CosmeticRuleGenerator extends base_generator/* .BaseGenerator */.t { /** * Converts a cosmetic rule AST into a string. * * @param node Cosmetic rule AST. * * @returns Raw string. */ static generate(node) { let result = constants/* .EMPTY */.wg; // Pattern result += CosmeticRulePatternGenerator.generate(node); // Separator result += node.separator.value; // uBO rule modifiers if (node.syntax === adblockers/* .AdblockSyntax.Ubo */.YG.Ubo && node.modifiers) { node.modifiers.children.forEach((modifier) => { if (modifier.exception) { result += constants/* .COLON */.oH; result += constants/* .CSS_NOT_PSEUDO */.vr; result += constants/* .OPEN_PARENTHESIS */.Cx; } result += constants/* .COLON */.oH; result += modifier.name.value; if (modifier.value) { result += constants/* .OPEN_PARENTHESIS */.Cx; result += modifier.value.value; result += constants/* .CLOSE_PARENTHESIS */.s1; } if (modifier.exception) { result += constants/* .CLOSE_PARENTHESIS */.s1; } }); // If there are at least one modifier, add a space if (node.modifiers.children.some((modifier) => modifier?.name.value)) { result += constants/* .SPACE */.t6; } } // Body result += cosmetic_rule_body_generator/* .CosmeticRuleBodyGenerator.generate */.H.generate(node); return result; } } ;// CONCATENATED MODULE: ./node_modules/.pnpm/@adguard+agtree@4.2.1/node_modules/@adguard/agtree/dist/generator/network/host-rule-generator.js /* * AGTree v4.2.1 (build date: Wed, 12 Aug 2026 01:31:02 GMT) * (c) 2026 Adguard Software Ltd. * Released under the MIT license * https://github.com/AdguardTeam/tsurlfilter/tree/master/packages/agtree#readme */ /** * Generator for host rule nodes. */ class HostRuleGenerator extends base_generator/* .BaseGenerator */.t { /** * Converts a host rule node to a raw string. * * @param node Host rule node. * * @returns Raw string. */ static generate(node) { const result = []; if (node.ip) { result.push(node.ip.value); } if (node.hostnames) { result.push(constants/* .SPACE */.t6); result.push(node.hostnames.children.map(({ value }) => value).join(constants/* .SPACE */.t6)); } if (node.comment) { result.push(constants/* .SPACE */.t6); result.push(constants/* .HASHMARK */.C); result.push(constants/* .SPACE */.t6); result.push(node.comment.value); } return result.join(constants/* .EMPTY */.wg); } } ;// CONCATENATED MODULE: ./node_modules/.pnpm/@adguard+agtree@4.2.1/node_modules/@adguard/agtree/dist/generator/network/network-rule-generator.js /* * AGTree v4.2.1 (build date: Wed, 12 Aug 2026 01:31:02 GMT) * (c) 2026 Adguard Software Ltd. * Released under the MIT license * https://github.com/AdguardTeam/tsurlfilter/tree/master/packages/agtree#readme */ /** * Generator for network rule nodes. */ class NetworkRuleGenerator extends base_generator/* .BaseGenerator */.t { /** * Generates a string from a network rule AST node. * * @param node Network rule node to generate a string from. * * @returns Generated string representation of the network rule. */ static generate(node) { let result = constants/* .EMPTY */.wg; // If the rule is an exception, add the exception marker: `@@||example.org` if (node.exception) { result += constants/* .NETWORK_RULE_EXCEPTION_MARKER */.rF; } // Add the pattern: `||example.org` result += node.pattern.value; // If there are modifiers, add a separator and the modifiers: `||example.org$important` if (node.modifiers && node.modifiers.children.length > 0) { result += constants/* .NETWORK_RULE_SEPARATOR */.Xj; result += ModifierListGenerator.generate(node.modifiers); } return result; } } ;// CONCATENATED MODULE: ./node_modules/.pnpm/@adguard+agtree@4.2.1/node_modules/@adguard/agtree/dist/generator/rule-generator.js /* * AGTree v4.2.1 (build date: Wed, 12 Aug 2026 01:31:02 GMT) * (c) 2026 Adguard Software Ltd. * Released under the MIT license * https://github.com/AdguardTeam/tsurlfilter/tree/master/packages/agtree#readme */ /** * RuleGenerator is responsible for converting adblock rule ASTs to their string representation. */ class RuleGenerator extends base_generator/* .BaseGenerator */.t { /** * Converts a rule AST to a string. * * @param ast Adblock rule AST. * * @returns Raw string. * * @example * Take a look at the following example: * ```js * // Parse the rule to the AST * const ast = RuleParser.parse("example.org##.banner"); * // Generate the rule from the AST * const raw = RuleParser.generate(ast); * // Print the generated rule * console.log(raw); // "example.org##.banner" * ``` */ static generate(ast) { switch (ast.category) { // Empty lines case nodes/* .RuleCategory.Empty */.$O.Empty: return constants/* .EMPTY */.wg; // Invalid rules case nodes/* .RuleCategory.Invalid */.$O.Invalid: return ast.raw; // Comment rules case nodes/* .RuleCategory.Comment */.$O.Comment: return CommentRuleGenerator.generate(ast); // Cosmetic / non-basic rules case nodes/* .RuleCategory.Cosmetic */.$O.Cosmetic: return CosmeticRuleGenerator.generate(ast); // Network / basic rules case nodes/* .RuleCategory.Network */.$O.Network: switch (ast.type) { case nodes/* .NetworkRuleType.HostRule */.vY.HostRule: return HostRuleGenerator.generate(ast); case nodes/* .NetworkRuleType.NetworkRule */.vY.NetworkRule: return NetworkRuleGenerator.generate(ast); default: throw new Error('Unknown network rule type'); } default: throw new Error('Unknown rule category'); } } } }, 6730() { /* * AGTree v4.2.1 (build date: Wed, 12 Aug 2026 01:31:02 GMT) * (c) 2026 Adguard Software Ltd. * Released under the MIT license * https://github.com/AdguardTeam/tsurlfilter/tree/master/packages/agtree#readme */ }, 79864(__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) { __webpack_require__.d(__webpack_exports__, { $O: () => (RuleCategory), WR: () => (ListItemNodeType), gV: () => (CommentRuleType), h6: () => (ListNodeType), k9: () => (CosmeticRuleType), oC: () => (OperatorValue), p5: () => (CosmeticRuleSeparator), vY: () => (NetworkRuleType), yg: () => (CommentMarker) }); /* * AGTree v4.2.1 (build date: Wed, 12 Aug 2026 01:31:02 GMT) * (c) 2026 Adguard Software Ltd. * Released under the MIT license * https://github.com/AdguardTeam/tsurlfilter/tree/master/packages/agtree#readme */ const OperatorValue = { Not: '!', And: '&&', Or: '||', }; /** * Represents the different comment markers that can be used in an adblock rule. * * @example * - If the rule is `! This is just a comment`, then the marker will be `!`. * - If the rule is `# This is just a comment`, then the marker will be `#`. */ const CommentMarker = { /** * Regular comment marker. It is supported by all ad blockers. */ Regular: '!', /** * Hashmark comment marker. It is supported by uBlock Origin and AdGuard, * and also used in hosts files. */ Hashmark: '#', }; /** * Represents the main categories that an adblock rule can belong to. * Of course, these include additional subcategories. */ const RuleCategory = { /** * Empty "rules" that are only containing whitespaces. These rules are handled just for convenience. */ Empty: 'Empty', /** * Syntactically invalid rules (tolerant mode only). */ Invalid: 'Invalid', /** * Comment rules, such as comment rules, metadata rules, preprocessor rules, etc. */ Comment: 'Comment', /** * Cosmetic rules, such as element hiding rules, CSS rules, scriptlet rules, HTML rules, and JS rules. */ Cosmetic: 'Cosmetic', /** * Network rules, such as basic network rules, header remover network rules, redirect network rules, * response header filtering rules, etc. */ Network: 'Network', }; /** * Represents similar types of modifiers values * which may be separated by a comma `,` (only for DomainList) or a pipe `|`. */ const ListNodeType = { AppList: 'AppList', DomainList: 'DomainList', MethodList: 'MethodList', StealthOptionList: 'StealthOptionList', }; /** * Represents child items for {@link ListNodeType}. */ const ListItemNodeType = { Unknown: 'Unknown', App: 'App', Domain: 'Domain', Method: 'Method', StealthOption: 'StealthOption', }; /** * Represents possible comment types. */ const CommentRuleType = { AgentCommentRule: 'AgentCommentRule', CommentRule: 'CommentRule', ConfigCommentRule: 'ConfigCommentRule', HintCommentRule: 'HintCommentRule', MetadataCommentRule: 'MetadataCommentRule', PreProcessorCommentRule: 'PreProcessorCommentRule', }; /** * Represents possible cosmetic rule types. */ const CosmeticRuleType = { ElementHidingRule: 'ElementHidingRule', CssInjectionRule: 'CssInjectionRule', ScriptletInjectionRule: 'ScriptletInjectionRule', HtmlFilteringRule: 'HtmlFilteringRule', JsInjectionRule: 'JsInjectionRule', }; /** * Represents possible cosmetic rule separators. */ const CosmeticRuleSeparator = { /** * @see {@link https://help.eyeo.com/adblockplus/how-to-write-filters#elemhide_basic} */ ElementHiding: '##', /** * @see {@link https://help.eyeo.com/adblockplus/how-to-write-filters#elemhide_basic} */ ElementHidingException: '#@#', /** * @see {@link https://help.eyeo.com/adblockplus/how-to-write-filters#elemhide_basic} */ ExtendedElementHiding: '#?#', /** * @see {@link https://help.eyeo.com/adblockplus/how-to-write-filters#elemhide_basic} */ ExtendedElementHidingException: '#@?#', /** * @see {@link https://help.eyeo.com/adblockplus/how-to-write-filters#elemhide_basic} */ AbpSnippet: '#$#', /** * @see {@link https://help.eyeo.com/adblockplus/how-to-write-filters#elemhide_basic} */ AbpSnippetException: '#@$#', /** * @see {@link https://kb.adguard.com/en/general/how-to-create-your-own-ad-filters#cosmetic-css-rules} */ AdgCssInjection: '#$#', /** * @see {@link https://kb.adguard.com/en/general/how-to-create-your-own-ad-filters#cosmetic-css-rules} */ AdgCssInjectionException: '#@$#', /** * @see {@link https://kb.adguard.com/en/general/how-to-create-your-own-ad-filters#cosmetic-css-rules} */ AdgExtendedCssInjection: '#$?#', /** * @see {@link https://kb.adguard.com/en/general/how-to-create-your-own-ad-filters#cosmetic-css-rules} */ AdgExtendedCssInjectionException: '#@$?#', /** * @see {@link https://kb.adguard.com/en/general/how-to-create-your-own-ad-filters#scriptlets} */ AdgJsInjection: '#%#', /** * @see {@link https://kb.adguard.com/en/general/how-to-create-your-own-ad-filters#scriptlets} */ AdgJsInjectionException: '#@%#', /** * @see {@link https://kb.adguard.com/en/general/how-to-create-your-own-ad-filters#html-filtering-rules} */ AdgHtmlFiltering: '$$', /** * @see {@link https://kb.adguard.com/en/general/how-to-create-your-own-ad-filters#html-filtering-rules} */ AdgHtmlFilteringException: '$@$', }; /** * Represents the different types of network rules. */ const NetworkRuleType = { NetworkRule: 'NetworkRule', HostRule: 'HostRule', }; }, 79963(__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) { __webpack_require__.d(__webpack_exports__, { V: () => (BaseParser) }); /* import */ var _errors_not_implemented_error_js__rspack_import_0 = __webpack_require__(82535); /* * AGTree v4.2.1 (build date: Wed, 12 Aug 2026 01:31:02 GMT) * (c) 2026 Adguard Software Ltd. * Released under the MIT license * https://github.com/AdguardTeam/tsurlfilter/tree/master/packages/agtree#readme */ /** * @file Base parser class. */ /** * Base class for parsers. Each parser should extend this class. */ class BaseParser { /** * Parses the input string and returns the AST node. * * @param input Input string to parse. * @param options Parser options, see {@link ParserOptions}. * @param baseOffset Base offset. Locations in the AST node will be relative to this offset. * @param args Additional, parser-specific arguments, if needed. */ // eslint-disable-next-line @typescript-eslint/no-unused-vars static parse(input, options, baseOffset, ...args) { throw new _errors_not_implemented_error_js__rspack_import_0/* .NotImplementedError */.E(); } } }, 83102(__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) { // EXPORTS __webpack_require__.d(__webpack_exports__, { B: () => (/* binding */ CommentParser) }); // EXTERNAL MODULE: ./node_modules/.pnpm/@adguard+agtree@4.2.1/node_modules/@adguard/agtree/dist/parser/base-parser.js var base_parser = __webpack_require__(79963); // EXTERNAL MODULE: ./node_modules/.pnpm/@adguard+agtree@4.2.1/node_modules/@adguard/agtree/dist/parser/options.js var parser_options = __webpack_require__(64626); // EXTERNAL MODULE: ./node_modules/.pnpm/@adguard+agtree@4.2.1/node_modules/@adguard/agtree/dist/errors/adblock-syntax-error.js var adblock_syntax_error = __webpack_require__(10631); // EXTERNAL MODULE: ./node_modules/.pnpm/@adguard+agtree@4.2.1/node_modules/@adguard/agtree/dist/nodes/index.js var nodes = __webpack_require__(79864); // EXTERNAL MODULE: ./node_modules/.pnpm/@adguard+agtree@4.2.1/node_modules/@adguard/agtree/dist/utils/adblockers.js var adblockers = __webpack_require__(22380); // EXTERNAL MODULE: ./node_modules/.pnpm/@adguard+agtree@4.2.1/node_modules/@adguard/agtree/dist/utils/constants.js var constants = __webpack_require__(53097); // EXTERNAL MODULE: ./node_modules/.pnpm/@adguard+agtree@4.2.1/node_modules/@adguard/agtree/dist/utils/cosmetic-rule-separator.js var cosmetic_rule_separator = __webpack_require__(77342); // EXTERNAL MODULE: ./node_modules/.pnpm/@adguard+agtree@4.2.1/node_modules/@adguard/agtree/dist/utils/string.js var string = __webpack_require__(16875); // EXTERNAL MODULE: ./node_modules/.pnpm/@adguard+agtree@4.2.1/node_modules/@adguard/agtree/dist/utils/type-guards.js var type_guards = __webpack_require__(64505); ;// CONCATENATED MODULE: ./node_modules/.pnpm/@adguard+agtree@4.2.1/node_modules/@adguard/agtree/dist/common/agent-common.js /* * AGTree v4.2.1 (build date: Wed, 12 Aug 2026 01:31:02 GMT) * (c) 2026 Adguard Software Ltd. * Released under the MIT license * https://github.com/AdguardTeam/tsurlfilter/tree/master/packages/agtree#readme */ /** * Possible AdGuard agent markers. */ const ADG_NAME_MARKERS = new Set([ 'adguard', 'adg', ]); /** * Possible uBlock Origin agent markers. */ const UBO_NAME_MARKERS = new Set([ 'ublock', 'ublock origin', 'ubo', ]); /** * Possible Adblock Plus agent markers. */ const ABP_NAME_MARKERS = new Set([ 'adblock', 'adblock plus', 'adblockplus', 'abp', ]); /** * Returns the adblock syntax based on the adblock name parsed from the agent type comment. * Needed for modifiers validation of network rules by AGLint. * * @param name Adblock name. * * @returns Adblock syntax. */ const getAdblockSyntax = (name) => { let syntax = adblockers/* .AdblockSyntax.Common */.YG.Common; const lowerCaseName = name.toLowerCase(); if (ADG_NAME_MARKERS.has(lowerCaseName)) { syntax = adblockers/* .AdblockSyntax.Adg */.YG.Adg; } else if (UBO_NAME_MARKERS.has(lowerCaseName)) { syntax = adblockers/* .AdblockSyntax.Ubo */.YG.Ubo; } else if (ABP_NAME_MARKERS.has(lowerCaseName)) { syntax = adblockers/* .AdblockSyntax.Abp */.YG.Abp; } return syntax; }; // EXTERNAL MODULE: ./node_modules/.pnpm/@adguard+agtree@4.2.1/node_modules/@adguard/agtree/dist/parser/misc/value-parser.js var value_parser = __webpack_require__(29090); ;// CONCATENATED MODULE: ./node_modules/.pnpm/@adguard+agtree@4.2.1/node_modules/@adguard/agtree/dist/parser/comment/agent-parser.js /* * AGTree v4.2.1 (build date: Wed, 12 Aug 2026 01:31:02 GMT) * (c) 2026 Adguard Software Ltd. * Released under the MIT license * https://github.com/AdguardTeam/tsurlfilter/tree/master/packages/agtree#readme */ /** * `AgentParser` is responsible for parsing single adblock agent elements. * * @example * If the adblock agent rule is * ```adblock * [Adblock Plus 2.0; AdGuard] * ``` * then the adblock agents are `Adblock Plus 2.0` and `AdGuard`, and this * class is responsible for parsing them. The rule itself is parsed by * `AgentCommentParser`, which uses this class to parse single agents. */ class AgentParser extends base_parser/* .BaseParser */.V { /** * Regex to match a version inside a string. */ static VERSION_REGEX = /\b\d+\.\d+(\.\d+)?\b/; /** * Checks if the string is a valid version. * * The string can have a version in formats like * [Adblock Plus 2.0], or [Adblock Plus 3.1; AdGuard]. * * @param str String to check. * * @returns `true` if the string is a valid version, `false` otherwise. */ static isValidVersion(str) { // Check if the string contains a valid version pattern return AgentParser.VERSION_REGEX.test(str); } /** * Parses a raw rule as an adblock agent comment. * * @param raw Raw input to parse. * @param options Global parser options. * @param baseOffset Starting offset of the input. Node locations are calculated relative to this offset. * * @returns Agent rule AST. * * @throws {AdblockSyntaxError} If the raw rule cannot be parsed as an adblock agent. */ static parse(raw, options = parser_options/* .defaultParserOptions */.n, baseOffset = 0) { let offset = 0; // Save name start position const nameStartIndex = offset; let nameEndIndex = offset; // Prepare variables for name and version let name; let version; // default value for the syntax let syntax = adblockers/* .AdblockSyntax.Common */.YG.Common; // Get agent parts by splitting it by spaces. The last part may be a version. // Example: "Adblock Plus 2.0" while (offset < raw.length) { // Skip whitespace before the part offset = string/* .StringUtils.skipWS */.$x.skipWS(raw, offset); const partEnd = string/* .StringUtils.findNextWhitespaceCharacter */.$x.findNextWhitespaceCharacter(raw, offset); const part = raw.slice(offset, partEnd); if (AgentParser.isValidVersion(part)) { if (!(0,type_guards/* .isUndefined */.b0)(version)) { throw new adblock_syntax_error/* .AdblockSyntaxError */.q('Duplicated versions are not allowed', baseOffset + offset, baseOffset + partEnd); } const parsedNamePart = raw.slice(nameStartIndex, nameEndIndex); name = value_parser/* .ValueParser.parse */.J.parse(parsedNamePart, options, baseOffset + nameStartIndex); version = value_parser/* .ValueParser.parse */.J.parse(part, options, baseOffset + offset); syntax = getAdblockSyntax(parsedNamePart); } else { nameEndIndex = partEnd; } // Skip whitespace after the part offset = string/* .StringUtils.skipWS */.$x.skipWS(raw, partEnd); } // If we didn't find a version, the whole string is the name if ((0,type_guards/* .isUndefined */.b0)(name)) { const parsedNamePart = raw.slice(nameStartIndex, nameEndIndex); name = value_parser/* .ValueParser.parse */.J.parse(parsedNamePart, options, baseOffset + nameStartIndex); syntax = getAdblockSyntax(parsedNamePart); } // Agent name cannot be empty if (name.value.length === 0) { throw new adblock_syntax_error/* .AdblockSyntaxError */.q('Agent name cannot be empty', baseOffset, baseOffset + raw.length); } const result = { type: 'Agent', adblock: name, syntax, }; // only add version if it's present if (version) { result.version = version; } if (options.isLocIncluded) { result.start = baseOffset; result.end = baseOffset + raw.length; } return result; } } ;// CONCATENATED MODULE: ./node_modules/.pnpm/@adguard+agtree@4.2.1/node_modules/@adguard/agtree/dist/parser/comment/agent-comment-parser.js /* * AGTree v4.2.1 (build date: Wed, 12 Aug 2026 01:31:02 GMT) * (c) 2026 Adguard Software Ltd. * Released under the MIT license * https://github.com/AdguardTeam/tsurlfilter/tree/master/packages/agtree#readme */ /** * `AgentParser` is responsible for parsing an Adblock agent rules. * Adblock agent comment marks that the filter list is supposed to * be used by the specified ad blockers. * * @example * - ```adblock * [AdGuard] * ``` * - ```adblock * [Adblock Plus 2.0] * ``` * - ```adblock * [uBlock Origin] * ``` * - ```adblock * [uBlock Origin 1.45.3] * ``` * - ```adblock * [Adblock Plus 2.0; AdGuard] * ``` */ class AgentCommentParser extends base_parser/* .BaseParser */.V { /** * Checks if the raw rule is an adblock agent comment. * * @param raw Raw rule. * * @returns `true` if the rule is an adblock agent, `false` otherwise. */ static isAgentRule(raw) { const rawTrimmed = raw.trim(); if (rawTrimmed.startsWith(constants/* .OPEN_SQUARE_BRACKET */.cU) && rawTrimmed.endsWith(constants/* .CLOSE_SQUARE_BRACKET */.A1)) { // Avoid this case: [$adg-modifier]##[class^="adg-"] return (0,type_guards/* .isNull */.kZ)(cosmetic_rule_separator/* .CosmeticRuleSeparatorUtils.find */.m.find(rawTrimmed)); } return false; } /** * Parses a raw rule as an adblock agent comment. * * @param raw Raw input to parse. * @param options Global parser options. * @param baseOffset Starting offset of the input. Node locations are calculated relative to this offset. * * @returns Agent rule AST or null (if the raw rule cannot be parsed as an adblock agent comment). */ static parse(raw, options = parser_options/* .defaultParserOptions */.n, baseOffset = 0) { // Ignore non-agent rules if (!AgentCommentParser.isAgentRule(raw)) { return null; } let offset = 0; // Skip whitespace characters before the rule offset = string/* .StringUtils.skipWS */.$x.skipWS(raw, offset); // Skip opening bracket offset += 1; // last character should be a closing bracket const closingBracketIndex = string/* .StringUtils.skipWSBack */.$x.skipWSBack(raw, raw.length - 1); if (closingBracketIndex === -1 || raw[closingBracketIndex] !== constants/* .CLOSE_SQUARE_BRACKET */.A1) { throw new adblock_syntax_error/* .AdblockSyntaxError */.q('Missing closing bracket', offset, offset + raw.length); } // Initialize the agent list const result = { type: nodes/* .CommentRuleType.AgentCommentRule */.gV.AgentCommentRule, syntax: adblockers/* .AdblockSyntax.Common */.YG.Common, category: nodes/* .RuleCategory.Comment */.$O.Comment, children: [], }; if (options.includeRaws) { result.raws = { text: raw, }; } if (options.isLocIncluded) { result.start = baseOffset; result.end = baseOffset + raw.length; } while (offset < closingBracketIndex) { // Skip whitespace characters before the agent offset = string/* .StringUtils.skipWS */.$x.skipWS(raw, offset); // Find the separator or the closing bracket let separatorIndex = raw.indexOf(constants/* .SEMICOLON */.I8, offset); if (separatorIndex === -1) { separatorIndex = closingBracketIndex; } // Find the last non-whitespace character of the agent // [AdGuard ; Adblock Plus 2.0] // ^ // (if we have spaces between the agent name and the separator) const agentEndIndex = string/* .StringUtils.findLastNonWhitespaceCharacter */.$x.findLastNonWhitespaceCharacter(raw.slice(offset, separatorIndex)) + offset + 1; // Collect the agent result.children.push(AgentParser.parse(raw.slice(offset, agentEndIndex), options, baseOffset + offset)); // Set the offset to the next agent or the end of the rule offset = separatorIndex + 1; } if (result.children.length === 0) { throw new adblock_syntax_error/* .AdblockSyntaxError */.q('Empty agent list', baseOffset, baseOffset + raw.length); } return result; } } // EXTERNAL MODULE: ./node_modules/.pnpm/json5@2.2.3/node_modules/json5/dist/index.js var dist = __webpack_require__(57917); // EXTERNAL MODULE: ./node_modules/.pnpm/@adguard+agtree@4.2.1/node_modules/@adguard/agtree/dist/parser/misc/parameter-list-parser.js var parameter_list_parser = __webpack_require__(43939); ;// CONCATENATED MODULE: ./node_modules/.pnpm/@adguard+agtree@4.2.1/node_modules/@adguard/agtree/dist/parser/comment/config-comment-parser.js /* * AGTree v4.2.1 (build date: Wed, 12 Aug 2026 01:31:02 GMT) * (c) 2026 Adguard Software Ltd. * Released under the MIT license * https://github.com/AdguardTeam/tsurlfilter/tree/master/packages/agtree#readme */ /** * @file AGLint configuration comments. Inspired by ESLint inline configuration comments. * * @see {@link https://eslint.org/docs/latest/user-guide/configuring/rules#using-configuration-comments} */ /** * `ConfigCommentParser` is responsible for parsing inline AGLint configuration rules. * Generally, the idea is inspired by ESLint inline configuration comments. * * @see {@link https://eslint.org/docs/latest/user-guide/configuring/rules#using-configuration-comments} */ class ConfigCommentParser extends base_parser/* .BaseParser */.V { /** * Checks if the raw rule is an inline configuration comment rule. * * @param raw Raw rule. * * @returns `true` if the rule is an inline configuration comment rule, otherwise `false`. */ static isConfigComment(raw) { const trimmed = raw.trim(); if (trimmed[0] === nodes/* .CommentMarker.Regular */.yg.Regular || trimmed[0] === nodes/* .CommentMarker.Hashmark */.yg.Hashmark) { // Skip comment marker and trim comment text (it is necessary because of "! something") const text = raw.slice(1).trim(); // The code below is "not pretty", but it runs fast, which is necessary, since it will run on EVERY comment // The essence of the indicator is that the control comment always starts with the "aglint" prefix return ((text[0] === 'a' || text[0] === 'A') && (text[1] === 'g' || text[1] === 'G') && (text[2] === 'l' || text[2] === 'L') && (text[3] === 'i' || text[3] === 'I') && (text[4] === 'n' || text[4] === 'N') && (text[5] === 't' || text[5] === 'T')); } return false; } /** * Parses a raw rule as an inline configuration comment. * * @param raw Raw input to parse. * @param options Global parser options. * @param baseOffset Starting offset of the input. Node locations are calculated relative to this offset. * * @returns * Inline configuration comment AST or null (if the raw rule cannot be parsed as configuration comment). */ static parse(raw, options = parser_options/* .defaultParserOptions */.n, baseOffset = 0) { if (!ConfigCommentParser.isConfigComment(raw)) { return null; } let offset = 0; // Skip leading whitespace (if any) offset = string/* .StringUtils.skipWS */.$x.skipWS(raw, offset); // Get comment marker const marker = value_parser/* .ValueParser.parse */.J.parse(raw[offset], options, baseOffset + offset); // Skip marker offset += 1; // Skip whitespace (if any) offset = string/* .StringUtils.skipWS */.$x.skipWS(raw, offset); // Save the command start position const commandStart = offset; // Get comment text, for example: "aglint-disable-next-line" offset = string/* .StringUtils.findNextWhitespaceCharacter */.$x.findNextWhitespaceCharacter(raw, offset); const command = value_parser/* .ValueParser.parse */.J.parse(raw.slice(commandStart, offset), options, baseOffset + commandStart); // Skip whitespace after command offset = string/* .StringUtils.skipWS */.$x.skipWS(raw, offset); // Get comment (if any) const commentStart = raw.indexOf(constants/* .AGLINT_CONFIG_COMMENT_MARKER */.Ez, offset); const commentEnd = commentStart !== -1 ? string/* .StringUtils.skipWSBack */.$x.skipWSBack(raw) + 1 : -1; let comment; // Check if there is a comment if (commentStart !== -1) { comment = value_parser/* .ValueParser.parse */.J.parse(raw.slice(commentStart, commentEnd), options, baseOffset + commentStart); } // Get parameter const paramsStart = offset; const paramsEnd = commentStart !== -1 ? string/* .StringUtils.skipWSBack */.$x.skipWSBack(raw, commentStart - 1) + 1 : string/* .StringUtils.skipWSBack */.$x.skipWSBack(raw) + 1; let params; // `! aglint ...` config comment if (command.value === constants/* .AGLINT_COMMAND_PREFIX */.BH) { params = { type: 'ConfigNode', // It is necessary to use JSON5.parse instead of JSON.parse because JSON5 allows unquoted keys. // But don't forget to add { } to the beginning and end of the string, // otherwise JSON5 will not be able to parse it. // TODO: Better solution? ESLint uses "levn" package for parsing these comments. value: dist.parse(`{${raw.slice(paramsStart, paramsEnd)}}`), }; if (options.isLocIncluded) { params.start = paramsStart; params.end = paramsEnd; } // Throw error for empty config if (Object.keys(params.value).length === 0) { throw new Error('Empty AGLint config'); } } else if (paramsStart < paramsEnd) { params = parameter_list_parser/* .ParameterListParser.parse */.D.parse(raw.slice(paramsStart, paramsEnd), options, baseOffset + paramsStart, constants/* .COMMA */.KE); } const result = { type: nodes/* .CommentRuleType.ConfigCommentRule */.gV.ConfigCommentRule, category: nodes/* .RuleCategory.Comment */.$O.Comment, syntax: adblockers/* .AdblockSyntax.Common */.YG.Common, marker, command, params, comment, }; if (options.includeRaws) { result.raws = { text: raw, }; } if (options.isLocIncluded) { result.start = baseOffset; result.end = baseOffset + raw.length; } return result; } } ;// CONCATENATED MODULE: ./node_modules/.pnpm/@adguard+agtree@4.2.1/node_modules/@adguard/agtree/dist/parser/comment/hint-parser.js /* * AGTree v4.2.1 (build date: Wed, 12 Aug 2026 01:31:02 GMT) * (c) 2026 Adguard Software Ltd. * Released under the MIT license * https://github.com/AdguardTeam/tsurlfilter/tree/master/packages/agtree#readme */ /* eslint-disable no-param-reassign */ /** * @file AdGuard Hints. * * @see {@link https://kb.adguard.com/en/general/how-to-create-your-own-ad-filters#hints} */ /** * `HintParser` is responsible for parsing AdGuard hints. * * @example * If the hint rule is * ```adblock * !+ NOT_OPTIMIZED PLATFORM(windows) * ``` * then the hints are `NOT_OPTIMIZED` and `PLATFORM(windows)`, and this * class is responsible for parsing them. The rule itself is parsed by * the `HintRuleParser`, which uses this class to parse single hints. */ class HintParser extends base_parser/* .BaseParser */.V { /** * Parses a raw rule as a hint. * * @param raw Raw input to parse. * @param options Global parser options. * @param baseOffset Starting offset of the input. Node locations are calculated relative to this offset. * * @returns Hint rule AST or null. * * @throws If the syntax is invalid. */ static parse(raw, options = parser_options/* .defaultParserOptions */.n, baseOffset = 0) { let offset = 0; // Skip whitespace characters before the hint offset = string/* .StringUtils.skipWS */.$x.skipWS(raw); // Hint should start with the hint name in every case // Save the start offset of the hint name const nameStartIndex = offset; // Parse the hint name for (; offset < raw.length; offset += 1) { const char = raw[offset]; // Abort consuming the hint name if we encounter a whitespace character // or an opening parenthesis, which means 'HIT_NAME(' case if (char === constants/* .OPEN_PARENTHESIS */.Cx || char === constants/* .SPACE */.t6) { break; } // Hint name should only contain letters, digits, and underscores if (!string/* .StringUtils.isAlphaNumeric */.$x.isAlphaNumeric(char) && char !== constants/* .UNDERSCORE */.fB) { throw new adblock_syntax_error/* .AdblockSyntaxError */.q(`Invalid character "${char}" in hint name: "${char}"`, baseOffset + nameStartIndex, baseOffset + offset); } } // Save the end offset of the hint name const nameEndIndex = offset; // Save the hint name token const name = raw.slice(nameStartIndex, nameEndIndex); // Hint name cannot be empty if (name === constants/* .EMPTY */.wg) { throw new adblock_syntax_error/* .AdblockSyntaxError */.q('Empty hint name', baseOffset, baseOffset + nameEndIndex); } // Now we have two case: // 1. We have HINT_NAME and should return it // 2. We have HINT_NAME(PARAMS) and should continue parsing // Skip whitespace characters after the hint name offset = string/* .StringUtils.skipWS */.$x.skipWS(raw, offset); // Throw error for 'HINT_NAME (' case if (offset > nameEndIndex && raw[offset] === constants/* .OPEN_PARENTHESIS */.Cx) { throw new adblock_syntax_error/* .AdblockSyntaxError */.q('Unexpected whitespace(s) between hint name and opening parenthesis', baseOffset + nameEndIndex, baseOffset + offset); } // Create the hint name node (we can reuse it in the 'HINT_NAME' case, if needed) const nameNode = value_parser/* .ValueParser.parse */.J.parse(name, options, baseOffset + nameStartIndex); // Just return the hint name if we have 'HINT_NAME' case (no params) if (raw[offset] !== constants/* .OPEN_PARENTHESIS */.Cx) { const result = { type: 'Hint', name: nameNode, }; if (options.isLocIncluded) { result.start = baseOffset; result.end = baseOffset + offset; } return result; } // Skip the opening parenthesis offset += 1; // Find closing parenthesis const closeParenthesisIndex = raw.lastIndexOf(constants/* .CLOSE_PARENTHESIS */.s1); // Throw error if we don't have closing parenthesis if (closeParenthesisIndex === -1) { throw new adblock_syntax_error/* .AdblockSyntaxError */.q(`Missing closing parenthesis for hint "${name}"`, baseOffset + nameStartIndex, baseOffset + raw.length); } // Save the start and end index of the params const paramsStartIndex = offset; const paramsEndIndex = closeParenthesisIndex; // Parse the params const params = parameter_list_parser/* .ParameterListParser.parse */.D.parse(raw.slice(paramsStartIndex, paramsEndIndex), options, baseOffset + paramsStartIndex, constants/* .COMMA */.KE); offset = closeParenthesisIndex + 1; // Skip whitespace characters after the closing parenthesis offset = string/* .StringUtils.skipWS */.$x.skipWS(raw, offset); // Throw error if we don't reach the end of the input if (offset !== raw.length) { throw new adblock_syntax_error/* .AdblockSyntaxError */.q( // eslint-disable-next-line max-len `Unexpected input after closing parenthesis for hint "${name}": "${raw.slice(closeParenthesisIndex + 1, offset + 1)}"`, baseOffset + closeParenthesisIndex + 1, baseOffset + offset + 1); } // Return the HINT_NAME(PARAMS) case AST const result = { type: 'Hint', name: nameNode, params, }; if (options.isLocIncluded) { result.start = baseOffset; result.end = baseOffset + offset; } return result; } } ;// CONCATENATED MODULE: ./node_modules/.pnpm/@adguard+agtree@4.2.1/node_modules/@adguard/agtree/dist/parser/comment/hint-comment-parser.js /* * AGTree v4.2.1 (build date: Wed, 12 Aug 2026 01:31:02 GMT) * (c) 2026 Adguard Software Ltd. * Released under the MIT license * https://github.com/AdguardTeam/tsurlfilter/tree/master/packages/agtree#readme */ /** * `HintRuleParser` is responsible for parsing AdGuard hint rules. * * @see {@link https://kb.adguard.com/en/general/how-to-create-your-own-ad-filters#hints} * * @example * The following hint rule * ```adblock * !+ NOT_OPTIMIZED PLATFORM(windows) * ``` * contains two hints: `NOT_OPTIMIZED` and `PLATFORM`. */ class HintCommentParser extends base_parser/* .BaseParser */.V { /** * Checks if the raw rule is a hint rule. * * @param raw Raw rule. * * @returns `true` if the rule is a hint rule, `false` otherwise. */ static isHintRule(raw) { return raw.trim().startsWith(constants/* .HINT_MARKER */.j6); } /** * Parses a raw rule as a hint comment. * * @see {@link https://kb.adguard.com/en/general/how-to-create-your-own-ad-filters#hints-1} * * @param raw Raw input to parse. * @param options Global parser options. * @param baseOffset Starting offset of the input. Node locations are calculated relative to this offset. * * @returns Hint AST or null (if the raw rule cannot be parsed as a hint comment). * * @throws If the input matches the HINT pattern but syntactically invalid. */ static parse(raw, options = parser_options/* .defaultParserOptions */.n, baseOffset = 0) { // Ignore non-hint rules if (!HintCommentParser.isHintRule(raw)) { return null; } let offset = 0; // Skip whitespace characters before the rule offset = string/* .StringUtils.skipWS */.$x.skipWS(raw); // Skip hint marker offset += constants/* .HINT_MARKER_LEN */.BR; const hints = []; // Collect hints. Each hint is a string, optionally followed by a parameter list, // enclosed in parentheses. One rule can contain multiple hints. while (offset < raw.length) { // Split rule into raw hints (e.g. 'HINT_NAME' or 'HINT_NAME(PARAMS)') // Hints are separated by whitespace characters, but we should ignore // whitespace characters inside the parameter list // Ignore whitespace characters before the hint offset = string/* .StringUtils.skipWS */.$x.skipWS(raw, offset); // Save the start index of the hint const hintStartIndex = offset; // Find the end of the hint let hintEndIndex = offset; let balance = 0; while (hintEndIndex < raw.length) { if (raw[hintEndIndex] === constants/* .OPEN_PARENTHESIS */.Cx && raw[hintEndIndex - 1] !== constants/* .BACKSLASH */.r_) { balance += 1; // Throw error for nesting if (balance > 1) { throw new adblock_syntax_error/* .AdblockSyntaxError */.q('Invalid hint: nested parentheses are not allowed', baseOffset + hintStartIndex, baseOffset + hintEndIndex); } } else if (raw[hintEndIndex] === constants/* .CLOSE_PARENTHESIS */.s1 && raw[hintEndIndex - 1] !== constants/* .BACKSLASH */.r_) { balance -= 1; } else if (string/* .StringUtils.isWhitespace */.$x.isWhitespace(raw[hintEndIndex]) && balance === 0) { break; } hintEndIndex += 1; } offset = hintEndIndex; // Skip whitespace characters after the hint offset = string/* .StringUtils.skipWS */.$x.skipWS(raw, offset); // Parse the hint const hint = HintParser.parse(raw.slice(hintStartIndex, hintEndIndex), options, baseOffset + hintStartIndex); hints.push(hint); } // Throw error if no hints were found if (hints.length === 0) { throw new adblock_syntax_error/* .AdblockSyntaxError */.q('Empty hint rule', baseOffset, baseOffset + offset); } const result = { type: nodes/* .CommentRuleType.HintCommentRule */.gV.HintCommentRule, category: nodes/* .RuleCategory.Comment */.$O.Comment, syntax: adblockers/* .AdblockSyntax.Adg */.YG.Adg, children: hints, }; if (options.includeRaws) { result.raws = { text: raw, }; } if (options.isLocIncluded) { result.start = baseOffset; result.end = baseOffset + offset; } return result; } } ;// CONCATENATED MODULE: ./node_modules/.pnpm/@adguard+agtree@4.2.1/node_modules/@adguard/agtree/dist/parser/comment/metadata-comment-parser.js /* * AGTree v4.2.1 (build date: Wed, 12 Aug 2026 01:31:02 GMT) * (c) 2026 Adguard Software Ltd. * Released under the MIT license * https://github.com/AdguardTeam/tsurlfilter/tree/master/packages/agtree#readme */ /** * @file Metadata comments. */ /** * Set of known metadata headers. This helps to quickly identify and validate * metadata headers in the comments. */ const KNOWN_METADATA_HEADERS = new Set([ 'Checksum', 'Description', 'Expires', 'Homepage', 'Last Modified', 'LastModified', 'Licence', 'License', 'Time Updated', 'TimeUpdated', 'Version', 'Title', ]); /** * `MetadataParser` is responsible for parsing metadata comments. * Metadata comments are special comments that specify some properties of the list. * * @see {@link https://help.eyeo.com/adblockplus/how-to-write-filters#special-comments} * * @example * For example, in the case of * ```adblock * ! Title: My List * ``` * the name of the header is `Title`, and the value is `My List`, which means that * the list title is `My List`, and it can be used in the adblocker UI. */ class MetadataCommentParser extends base_parser/* .BaseParser */.V { /** * Parses a raw rule as a metadata comment. * * @param raw Raw input to parse. * @param options Global parser options. * @param baseOffset Starting offset of the input. Node locations are calculated relative to this offset. * * @returns Metadata comment AST or null (if the raw rule cannot be parsed as a metadata comment). */ static parse(raw, options = parser_options/* .defaultParserOptions */.n, baseOffset = 0) { // Fast check to avoid unnecessary work if (raw.indexOf(constants/* .COLON */.oH) === -1) { return null; } let offset = 0; // Skip leading spaces before the comment marker offset = string/* .StringUtils.skipWS */.$x.skipWS(raw, offset); // Check if the rule starts with a comment marker (first non-space sequence) if (raw[offset] !== nodes/* .CommentMarker.Regular */.yg.Regular && raw[offset] !== nodes/* .CommentMarker.Hashmark */.yg.Hashmark) { return null; } // Consume the comment marker const marker = value_parser/* .ValueParser.parse */.J.parse(raw[offset], options, baseOffset + offset); offset += 1; // Skip spaces offset = string/* .StringUtils.skipWS */.$x.skipWS(raw, offset); // Save header start position const headerStart = offset; // Check if the comment text starts with a known header const text = raw.slice(offset); for (const knownHeader of KNOWN_METADATA_HEADERS) { // Check if the comment text starts with the header (case-insensitive) if (text.toLocaleLowerCase().startsWith(knownHeader.toLocaleLowerCase())) { // Skip the header offset += knownHeader.length; // Save header const header = value_parser/* .ValueParser.parse */.J.parse(raw.slice(headerStart, offset), options, baseOffset + headerStart); // Skip spaces after the header offset = string/* .StringUtils.skipWS */.$x.skipWS(raw, offset); // Check if the rule contains a separator after the header if (raw[offset] !== constants/* .COLON */.oH) { return null; } // Skip the separator offset += 1; // Skip spaces after the separator offset = string/* .StringUtils.skipWS */.$x.skipWS(raw, offset); // Save the value start position const valueStart = offset; // Check if the rule contains a value if (offset >= raw.length) { return null; } const valueEnd = string/* .StringUtils.skipWSBack */.$x.skipWSBack(raw, raw.length - 1) + 1; // Save the value const value = value_parser/* .ValueParser.parse */.J.parse(raw.slice(valueStart, valueEnd), options, baseOffset + valueStart); const result = { type: nodes/* .CommentRuleType.MetadataCommentRule */.gV.MetadataCommentRule, category: nodes/* .RuleCategory.Comment */.$O.Comment, syntax: adblockers/* .AdblockSyntax.Common */.YG.Common, marker, header, value, }; if (options.includeRaws) { result.raws = { text: raw, }; } if (options.isLocIncluded) { result.start = baseOffset; result.end = baseOffset + raw.length; } return result; } } return null; } } // EXTERNAL MODULE: ./node_modules/.pnpm/@adguard+agtree@4.2.1/node_modules/@adguard/agtree/dist/parser/misc/logical-expression-parser.js var logical_expression_parser = __webpack_require__(48609); ;// CONCATENATED MODULE: ./node_modules/.pnpm/@adguard+agtree@4.2.1/node_modules/@adguard/agtree/dist/parser/comment/preprocessor-parser.js /* * AGTree v4.2.1 (build date: Wed, 12 Aug 2026 01:31:02 GMT) * (c) 2026 Adguard Software Ltd. * Released under the MIT license * https://github.com/AdguardTeam/tsurlfilter/tree/master/packages/agtree#readme */ /** * Pre-processor directives. * * @see {@link https://kb.adguard.com/en/general/how-to-create-your-own-ad-filters#pre-processor-directives} * @see {@link https://github.com/gorhill/uBlock/wiki/Static-filter-syntax#pre-parsing-directives} */ /** * `PreProcessorParser` is responsible for parsing preprocessor rules. * Pre-processor comments are special comments that are used to control the behavior of the filter list processor. * Please note that this parser only handles general syntax for now, and does not validate the parameters at * the parsing stage. * * @see {@link https://kb.adguard.com/en/general/how-to-create-your-own-ad-filters#pre-processor-directives} * @see {@link https://github.com/gorhill/uBlock/wiki/Static-filter-syntax#pre-parsing-directives} * * @example * If your rule is * ```adblock * !#if (adguard) * ``` * then the directive's name is `if` and its value is `(adguard)`, but the parameter list * is not parsed / validated further. */ class PreProcessorCommentParser extends base_parser/* .BaseParser */.V { /** * Determines whether the rule is a pre-processor rule. * * @param raw Raw rule. * * @returns `true` if the rule is a pre-processor rule, `false` otherwise. */ static isPreProcessorRule(raw) { const trimmed = raw.trim(); // Avoid this case: !##... (commonly used in AdGuard filters) return trimmed.startsWith(constants/* .PREPROCESSOR_MARKER */.PD) && trimmed[constants/* .PREPROCESSOR_MARKER_LEN */.nx] !== constants/* .HASHMARK */.C; } /** * Parses a raw rule as a pre-processor comment. * * @param raw Raw input to parse. * @param options Global parser options. * @param baseOffset Starting offset of the input. Node locations are calculated relative to this offset. * * @returns * Pre-processor comment AST or null (if the raw rule cannot be parsed as a pre-processor comment). */ static parse(raw, options = parser_options/* .defaultParserOptions */.n, baseOffset = 0) { // Ignore non-pre-processor rules if (!PreProcessorCommentParser.isPreProcessorRule(raw)) { return null; } let offset = 0; // Ignore whitespace characters before the rule (if any) offset = string/* .StringUtils.skipWS */.$x.skipWS(raw, offset); // Ignore the pre-processor marker offset += constants/* .PREPROCESSOR_MARKER_LEN */.nx; // Ignore whitespace characters after the pre-processor marker (if any) // Note: this is incorrect according to the spec, but we do it for tolerance offset = string/* .StringUtils.skipWS */.$x.skipWS(raw, offset); // Directive name should start at this offset, so we save this offset now const nameStart = offset; // Consume directive name, so parse the sequence until the first // whitespace / opening parenthesis / end of string while (offset < raw.length) { const ch = raw[offset]; if (ch === constants/* .PREPROCESSOR_SEPARATOR */.sA || ch === constants/* .OPEN_PARENTHESIS */.Cx) { break; } offset += 1; } // Save name end offset const nameEnd = offset; // Create name node const name = value_parser/* .ValueParser.parse */.J.parse(raw.slice(nameStart, nameEnd), options, baseOffset + nameStart); // Ignore whitespace characters after the directive name (if any) // Note: this may incorrect according to the spec, but we do it for tolerance offset = string/* .StringUtils.skipWS */.$x.skipWS(raw, offset); // If the directive name is "safari_cb_affinity", then we have a special case if (name.value === constants/* .SAFARI_CB_AFFINITY */.us) { // Throw error if there are spaces after the directive name if (offset > nameEnd) { throw new adblock_syntax_error/* .AdblockSyntaxError */.q(`Unexpected whitespace after "${constants/* .SAFARI_CB_AFFINITY */.us}" directive name`, baseOffset + nameEnd, baseOffset + offset); } // safari_cb_affinity directive optionally accepts a parameter list // So at this point we should check if there are parameters or not // (cb_affinity directive followed by an opening parenthesis or if we // skip the whitespace we reach the end of the string) if (string/* .StringUtils.skipWS */.$x.skipWS(raw, offset) !== raw.length) { if (raw[offset] !== constants/* .OPEN_PARENTHESIS */.Cx) { throw new adblock_syntax_error/* .AdblockSyntaxError */.q(`Unexpected character '${raw[offset]}' after '${constants/* .SAFARI_CB_AFFINITY */.us}' directive name`, baseOffset + offset, baseOffset + offset + 1); } // If we have parameters, then we should parse them // Note: we don't validate the parameters at this stage // Ignore opening parenthesis offset += 1; // Save parameter list start offset const parameterListStart = offset; // Check for closing parenthesis const closingParenthesesIndex = string/* .StringUtils.skipWSBack */.$x.skipWSBack(raw); if (closingParenthesesIndex === -1 || raw[closingParenthesesIndex] !== constants/* .CLOSE_PARENTHESIS */.s1) { throw new adblock_syntax_error/* .AdblockSyntaxError */.q(`Missing closing parenthesis for '${constants/* .SAFARI_CB_AFFINITY */.us}' directive`, baseOffset + offset, baseOffset + raw.length); } // Save parameter list end offset const parameterListEnd = closingParenthesesIndex; // Parse parameters between the opening and closing parentheses const result = { type: nodes/* .CommentRuleType.PreProcessorCommentRule */.gV.PreProcessorCommentRule, category: nodes/* .RuleCategory.Comment */.$O.Comment, syntax: adblockers/* .AdblockSyntax.Adg */.YG.Adg, name, // comma separated list of parameters params: parameter_list_parser/* .ParameterListParser.parse */.D.parse(raw.slice(parameterListStart, parameterListEnd), options, baseOffset + parameterListStart, constants/* .COMMA */.KE), }; if (options.includeRaws) { result.raws = { text: raw, }; } if (options.isLocIncluded) { result.start = baseOffset; result.end = baseOffset + raw.length; } return result; } } // If we reached the end of the string, then we have a directive without parameters // (e.g. "!#safari_cb_affinity" or "!#endif") // No need to continue parsing in this case. if (offset === raw.length) { // Throw error if the directive name is "if" or "include", because these directives // should have parameters if (name.value === constants.IF || name.value === constants/* .INCLUDE */.rM) { throw new adblock_syntax_error/* .AdblockSyntaxError */.q(`Directive "${name.value}" requires parameters`, baseOffset, baseOffset + raw.length); } const result = { type: nodes/* .CommentRuleType.PreProcessorCommentRule */.gV.PreProcessorCommentRule, category: nodes/* .RuleCategory.Comment */.$O.Comment, syntax: adblockers/* .AdblockSyntax.Common */.YG.Common, name, }; if (options.includeRaws) { result.raws = { text: raw, }; } if (options.isLocIncluded) { result.start = baseOffset; result.end = baseOffset + raw.length; } return result; } // Get start and end offsets of the directive parameters const paramsStart = offset; const paramsEnd = string/* .StringUtils.skipWSBack */.$x.skipWSBack(raw) + 1; // Prepare parameters node let params; // Parse parameters. Handle "if" and "safari_cb_affinity" directives // separately. if (name.value === constants.IF) { params = logical_expression_parser/* .LogicalExpressionParser.parse */.f.parse(raw.slice(paramsStart, paramsEnd), options, baseOffset + paramsStart); } else { params = value_parser/* .ValueParser.parse */.J.parse(raw.slice(paramsStart, paramsEnd), options, baseOffset + paramsStart); } const result = { type: nodes/* .CommentRuleType.PreProcessorCommentRule */.gV.PreProcessorCommentRule, category: nodes/* .RuleCategory.Comment */.$O.Comment, syntax: adblockers/* .AdblockSyntax.Common */.YG.Common, name, params, }; if (options.includeRaws) { result.raws = { text: raw, }; } if (options.isLocIncluded) { result.start = baseOffset; result.end = baseOffset + raw.length; } return result; } } ;// CONCATENATED MODULE: ./node_modules/.pnpm/@adguard+agtree@4.2.1/node_modules/@adguard/agtree/dist/parser/comment/simple-comment-parser.js /* * AGTree v4.2.1 (build date: Wed, 12 Aug 2026 01:31:02 GMT) * (c) 2026 Adguard Software Ltd. * Released under the MIT license * https://github.com/AdguardTeam/tsurlfilter/tree/master/packages/agtree#readme */ /** * `SimpleCommentParser` is responsible for parsing simple comments. * Some comments have a special meaning in adblock syntax, like agent comments or hints, * but this parser is only responsible for parsing regular comments, * whose only purpose is to provide some human-readable information. * * @example * ```adblock * ! This is a simple comment * # This is a simple comment, but in host-like syntax * ``` */ class SimpleCommentParser extends base_parser/* .BaseParser */.V { /** * Checks if the raw rule is a simple comment. * * @param raw Raw input to check. * * @returns `true` if the input is a simple comment, `false` otherwise. * * @note This method does not check for adblock agent comments. */ static isSimpleComment(raw) { const trimmed = raw.trim(); // Exclamation mark based comments if (trimmed.startsWith(nodes/* .CommentMarker.Regular */.yg.Regular)) { return true; } // Hashmark based comments // Note: in this case, we must be sure that we do not mistakenly parse a cosmetic rule as a #-like comment, // since most cosmetic rule separators also start with # if (trimmed.startsWith(nodes/* .CommentMarker.Hashmark */.yg.Hashmark)) { const result = cosmetic_rule_separator/* .CosmeticRuleSeparatorUtils.find */.m.find(trimmed); // If we cannot find a separator, it means that the rule is definitely a comment if (result === null) { return true; } // Otherwise, we must check if the separator is followed by a valid selector const { end } = result; // No valid selector if (!trimmed[end] || string/* .StringUtils.isWhitespace */.$x.isWhitespace(trimmed[end]) || (trimmed[end] === nodes/* .CommentMarker.Hashmark */.yg.Hashmark && trimmed[end + 1] === nodes/* .CommentMarker.Hashmark */.yg.Hashmark)) { return true; } } return false; } /** * Parses a raw rule as a simple comment. * * @param raw Raw input to parse. * @param options Global parser options. * @param baseOffset Starting offset of the input. Node locations are calculated relative to this offset. * * @returns Comment rule node or null (if the raw rule cannot be parsed as a simple comment). */ static parse(raw, options = parser_options/* .defaultParserOptions */.n, baseOffset = 0) { // Ignore non-comment rules if (!this.isSimpleComment(raw)) { return null; } // If we are here, it means that the rule is a regular comment let offset = 0; // Skip leading whitespace (if any) offset = string/* .StringUtils.skipWS */.$x.skipWS(raw, offset); // Get comment marker const marker = value_parser/* .ValueParser.parse */.J.parse(raw[offset], options, baseOffset + offset); // Skip marker offset += 1; // Get comment text const text = value_parser/* .ValueParser.parse */.J.parse(raw.slice(offset), options, baseOffset + offset); // Regular comment rule const result = { category: nodes/* .RuleCategory.Comment */.$O.Comment, type: nodes/* .CommentRuleType.CommentRule */.gV.CommentRule, // TODO: Change syntax when hashmark is used syntax: adblockers/* .AdblockSyntax.Common */.YG.Common, marker, text, }; if (options.includeRaws) { result.raws = { text: raw, }; } if (options.isLocIncluded) { result.start = baseOffset; result.end = baseOffset + raw.length; } return result; } } ;// CONCATENATED MODULE: ./node_modules/.pnpm/@adguard+agtree@4.2.1/node_modules/@adguard/agtree/dist/parser/comment/comment-parser.js /* * AGTree v4.2.1 (build date: Wed, 12 Aug 2026 01:31:02 GMT) * (c) 2026 Adguard Software Ltd. * Released under the MIT license * https://github.com/AdguardTeam/tsurlfilter/tree/master/packages/agtree#readme */ /** * `CommentParser` is responsible for parsing any comment-like adblock rules. * * @example * Example rules: * - Adblock agent rules: * - ```adblock * [AdGuard] * ``` * - ```adblock * [Adblock Plus 2.0] * ``` * - etc. * - AdGuard hint rules: * - ```adblock * !+ NOT_OPTIMIZED * ``` * - ```adblock * !+ NOT_OPTIMIZED PLATFORM(windows) * ``` * - etc. * - Pre-processor rules: * - ```adblock * !#if (adguard) * ``` * - ```adblock * !#endif * ``` * - etc. * - Metadata rules: * - ```adblock * ! Title: My List * ``` * - ```adblock * ! Version: 2.0.150 * ``` * - etc. * - AGLint inline config rules: * - ```adblock * ! aglint-enable some-rule * ``` * - ```adblock * ! aglint-disable some-rule * ``` * - etc. * - Simple comments: * - Regular version: * ```adblock * ! This is just a comment * ``` * - uBlock Origin / "hostlist" version: * ```adblock * # This is just a comment * ``` * - etc. */ class CommentParser extends base_parser/* .BaseParser */.V { /** * Checks whether a rule is a comment. * * @param raw Raw rule. * * @returns `true` if the rule is a comment, `false` otherwise. */ static isCommentRule(raw) { const trimmed = raw.trim(); return SimpleCommentParser.isSimpleComment(trimmed) || AgentCommentParser.isAgentRule(trimmed); } /** * Parses a raw rule as comment. * * @param raw Raw input to parse. * @param options Global parser options. * @param baseOffset Starting offset of the input. Node locations are calculated relative to this offset. * * @returns Comment AST or null (if the raw rule cannot be parsed as comment). */ static parse(raw, options = parser_options/* .defaultParserOptions */.n, baseOffset = 0) { // Ignore non-comment rules if (!CommentParser.isCommentRule(raw)) { return null; } // Note: we parse non-functional comments at the end, // if the input does not match any of the previous, more specific comment patterns return AgentCommentParser.parse(raw, options, baseOffset) || HintCommentParser.parse(raw, options, baseOffset) || PreProcessorCommentParser.parse(raw, options, baseOffset) || MetadataCommentParser.parse(raw, options, baseOffset) || ConfigCommentParser.parse(raw, options, baseOffset) || SimpleCommentParser.parse(raw, options, baseOffset); } } }, 36573(__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) { // EXPORTS __webpack_require__.d(__webpack_exports__, { R: () => (/* binding */ CosmeticRuleParser) }); // UNUSED EXPORTS: ERROR_MESSAGES // EXTERNAL MODULE: ./node_modules/.pnpm/sprintf-js@1.1.3/node_modules/sprintf-js/src/sprintf.js var sprintf = __webpack_require__(37155); // EXTERNAL MODULE: ./node_modules/.pnpm/@adguard+css-tokenizer@1.2.0/node_modules/@adguard/css-tokenizer/dist/csstokenizer.mjs var csstokenizer = __webpack_require__(83747); // EXTERNAL MODULE: ./node_modules/.pnpm/@adguard+agtree@4.2.1/node_modules/@adguard/agtree/dist/common/ubo-selector-common.js var ubo_selector_common = __webpack_require__(15862); // EXTERNAL MODULE: ./node_modules/.pnpm/@adguard+agtree@4.2.1/node_modules/@adguard/agtree/dist/errors/adblock-syntax-error.js var adblock_syntax_error = __webpack_require__(10631); // EXTERNAL MODULE: ./node_modules/.pnpm/@adguard+agtree@4.2.1/node_modules/@adguard/agtree/dist/nodes/index.js var nodes = __webpack_require__(79864); // EXTERNAL MODULE: ./node_modules/.pnpm/@adguard+agtree@4.2.1/node_modules/@adguard/agtree/dist/utils/adblockers.js var adblockers = __webpack_require__(22380); // EXTERNAL MODULE: ./node_modules/.pnpm/@adguard+agtree@4.2.1/node_modules/@adguard/agtree/dist/utils/constants.js var constants = __webpack_require__(53097); // EXTERNAL MODULE: ./node_modules/.pnpm/@adguard+agtree@4.2.1/node_modules/@adguard/agtree/dist/utils/cosmetic-rule-separator.js var cosmetic_rule_separator = __webpack_require__(77342); // EXTERNAL MODULE: ./node_modules/.pnpm/@adguard+agtree@4.2.1/node_modules/@adguard/agtree/dist/utils/string.js var string = __webpack_require__(16875); // EXTERNAL MODULE: ./node_modules/.pnpm/@adguard+agtree@4.2.1/node_modules/@adguard/agtree/dist/parser/base-parser.js var base_parser = __webpack_require__(79963); // EXTERNAL MODULE: ./node_modules/.pnpm/@adguard+agtree@4.2.1/node_modules/@adguard/agtree/dist/parser/comment/comment-parser.js + 9 modules var comment_parser = __webpack_require__(83102); // EXTERNAL MODULE: ./node_modules/.pnpm/@adguard+agtree@4.2.1/node_modules/@adguard/agtree/dist/converter/data/css.js var css = __webpack_require__(63829); // EXTERNAL MODULE: ./node_modules/.pnpm/@adguard+agtree@4.2.1/node_modules/@adguard/agtree/dist/parser/options.js var parser_options = __webpack_require__(64626); // EXTERNAL MODULE: ./node_modules/.pnpm/@adguard+agtree@4.2.1/node_modules/@adguard/agtree/dist/parser/css/css-token-stream.js var css_token_stream = __webpack_require__(44148); ;// CONCATENATED MODULE: ./node_modules/.pnpm/@adguard+agtree@4.2.1/node_modules/@adguard/agtree/dist/parser/css/adg-css-injection-parser.js /* * AGTree v4.2.1 (build date: Wed, 12 Aug 2026 01:31:02 GMT) * (c) 2026 Adguard Software Ltd. * Released under the MIT license * https://github.com/AdguardTeam/tsurlfilter/tree/master/packages/agtree#readme */ /** * @file Parser for AdGuard CSS injections. */ const ERROR_MESSAGES = { MEDIA_QUERY_LIST_IS_EMPTY: 'Media query list is empty', SELECTOR_LIST_IS_EMPTY: 'Selector list is empty', DECLARATION_LIST_IS_EMPTY: 'Declaration list is empty', }; /** * Parser for AdGuard CSS injection. */ class AdgCssInjectionParser extends base_parser/* .BaseParser */.V { /** * Parses an AdGuard CSS injection. * * @param raw Raw input to parse. * @param options Global parser options. * @param baseOffset Starting offset of the input. Node locations are calculated relative to this offset. * * @returns Parsed AdGuard CSS injection {@link CssInjectionRuleBody}. * * @throws An {@link AdblockSyntaxError} if the selector list is syntactically invalid. */ static parse(raw, options = parser_options/* .defaultParserOptions */.n, baseOffset = 0) { let mediaQueryList; const selectorList = { type: 'Value', value: constants/* .EMPTY */.wg }; const declarationList = { type: 'Value', value: constants/* .EMPTY */.wg }; const stream = new css_token_stream/* .CssTokenStream */.d(raw, baseOffset); // Skip leading whitespace characters stream.skipWhitespace(); // We have two possible CSS injection formats: // 1. @media (media-query-list) { selector list { declarations separated by semicolons } } // 2. selector list { declarations separated by semicolons } // Handle '@media' case: let balanceShift = 0; if (stream.getOrFail().type === csstokenizer/* .TokenType.AtKeyword */.ks.AtKeyword) { // Currently only '@media' is supported, we should throw an error if we encounter anything else, // like '@supports' or '@charset', etc. stream.expect(csstokenizer/* .TokenType.AtKeyword */.ks.AtKeyword, { value: constants/* .CSS_MEDIA_MARKER */.Ae, balance: 0 }); stream.advance(); // Skip whitespace characters after @media keyword, if any // @media (media-query-list) { ... // ↑ // └ this one (if any) stream.skipWhitespace(); const mediaQueryListStart = stream.getOrFail().start; // Skip everything until we found the opening curly bracket of the declaration block // @media media-query-list { ... // ↑ // └ this one let lastNonWsIndex = -1; while (!stream.isEof()) { const token = stream.getOrFail(); if (token.type === csstokenizer/* .TokenType.OpenCurlyBracket */.ks.OpenCurlyBracket && token.balance === 1) { break; } if (token.type !== csstokenizer/* .TokenType.Whitespace */.ks.Whitespace) { lastNonWsIndex = token.end; } stream.advance(); } // If the skipped tokens count is 0 without leading and trailing whitespace characters, then the media query // list is empty if (lastNonWsIndex === -1) { throw new adblock_syntax_error/* .AdblockSyntaxError */.q(ERROR_MESSAGES.MEDIA_QUERY_LIST_IS_EMPTY, baseOffset + mediaQueryListStart, baseOffset + raw.length); } // It is safe to use non-null assertion here, because we have already checked previous tokens. // eslint-disable-next-line @typescript-eslint/no-non-null-assertion const mediaQueryListEnd = lastNonWsIndex; mediaQueryList = { type: 'Value', value: raw.slice(mediaQueryListStart, mediaQueryListEnd), }; if (options.isLocIncluded) { mediaQueryList.start = baseOffset + mediaQueryListStart; mediaQueryList.end = baseOffset + mediaQueryListEnd; } // Next token should be an open curly bracket // @media (media-query-list) { ... // ↑ // └ this one stream.expect(csstokenizer/* .TokenType.OpenCurlyBracket */.ks.OpenCurlyBracket); stream.advance(); // '@media' at-rule wrap increases the balance level by 1 for the rule within the at-rule, because it // has its own { ... } block balanceShift = 1; } // Skip leading whitespace before the rule, if any // Note: rule = selector list { declarations separated by semicolons } stream.skipWhitespace(); const selectorStart = stream.getOrFail().start; // Jump to the opening curly bracket of the declaration block, based on the balance level // .selector { padding-top: 10px; padding-bottom: 10px; } // ↑ // └ this one const { skippedTrimmed: selectorTokensLength } = stream.skipUntilExt(csstokenizer/* .TokenType.OpenCurlyBracket */.ks.OpenCurlyBracket, balanceShift + 1); stream.expect(csstokenizer/* .TokenType.OpenCurlyBracket */.ks.OpenCurlyBracket); // If the skipped tokens count is 0 without leading and trailing whitespace characters, then the selector list // is empty if (selectorTokensLength === 0) { throw new adblock_syntax_error/* .AdblockSyntaxError */.q(ERROR_MESSAGES.SELECTOR_LIST_IS_EMPTY, baseOffset + selectorStart, baseOffset + raw.length); } // It is safe to use non-null assertion here, because we have already checked previous tokens. // eslint-disable-next-line @typescript-eslint/no-non-null-assertion const selectorEnd = stream.lookbehindForNonWs().end; selectorList.value = raw.slice(selectorStart, selectorEnd); if (options.isLocIncluded) { selectorList.start = baseOffset + selectorStart; selectorList.end = baseOffset + selectorEnd; } // Jump to the next token after the opening curly bracket of the declaration block // .selector { padding-top: 10px; padding-bottom: 10px; } // ↑ // └ this one stream.advance(); // Skip whitespace characters after the opening curly bracket of the declaration block, if any stream.skipWhitespace(); // Jump to the closing curly bracket of the declaration block, based on the balance level // .selector { padding-top: 10px; padding-bottom: 10px; } // ↑ // └ this one const declarationsStart = stream.getOrFail().start; const declarations = new Set(); let declarationsEnd = -1; let remove = false; let lastNonWsIndex = -1; while (!stream.isEof()) { const token = stream.getOrFail(); if (token.type === csstokenizer/* .TokenType.CloseCurlyBracket */.ks.CloseCurlyBracket && stream.getBalance() === balanceShift) { declarationsEnd = lastNonWsIndex; break; } if (token.type !== csstokenizer/* .TokenType.Whitespace */.ks.Whitespace) { lastNonWsIndex = token.end; } if (token.type === csstokenizer/* .TokenType.Ident */.ks.Ident && stream.lookahead()?.type === csstokenizer/* .TokenType.Colon */.ks.Colon) { const ident = raw.slice(token.start, token.end); declarations.add(ident); // Consume ident and colon stream.advance(); stream.advance(); // only 'remove: true' is allowed if (ident === css/* .REMOVE_PROPERTY */.JX) { // Skip whitespace after colon, if any stream.skipWhitespace(); // Next token should be an ident, with value 'true' stream.expect(csstokenizer/* .TokenType.Ident */.ks.Ident, { value: css/* .REMOVE_VALUE */.FH }); stream.advance(); remove = true; } } else { stream.advance(); } } if (declarationsEnd === -1) { throw new adblock_syntax_error/* .AdblockSyntaxError */.q(ERROR_MESSAGES.DECLARATION_LIST_IS_EMPTY, baseOffset + declarationsStart, baseOffset + raw.length); } declarationList.value = raw.slice(declarationsStart, declarationsEnd); if (options.isLocIncluded) { declarationList.start = baseOffset + declarationsStart; declarationList.end = baseOffset + declarationsEnd; } // Eat the close curly bracket of the declaration block // .selector { padding-top: 10px; padding-bottom: 10px; } // ↑ // └ this one stream.expect(csstokenizer/* .TokenType.CloseCurlyBracket */.ks.CloseCurlyBracket); stream.advance(); // Skip whitespace after the rule, if any stream.skipWhitespace(); // If we have a media query, we should have an extra close curly bracket if (balanceShift === 1) { stream.expect(csstokenizer/* .TokenType.CloseCurlyBracket */.ks.CloseCurlyBracket); stream.advance(); } const result = { type: 'CssInjectionRuleBody', selectorList, declarationList, remove, }; if (options.isLocIncluded) { result.start = baseOffset; result.end = baseOffset + raw.length; } if (mediaQueryList) { result.mediaQueryList = mediaQueryList; } return result; } } // EXTERNAL MODULE: ./node_modules/.pnpm/@adguard+agtree@4.2.1/node_modules/@adguard/agtree/dist/parser/css/balancing.js var balancing = __webpack_require__(51175); ;// CONCATENATED MODULE: ./node_modules/.pnpm/@adguard+agtree@4.2.1/node_modules/@adguard/agtree/dist/parser/css/ubo-selector-parser.js /* * AGTree v4.2.1 (build date: Wed, 12 Aug 2026 01:31:02 GMT) * (c) 2026 Adguard Software Ltd. * Released under the MIT license * https://github.com/AdguardTeam/tsurlfilter/tree/master/packages/agtree#readme */ /** * @file Parser for special uBO selectors. */ /** * Possible error messages for uBO selectors. Formatted with {@link sprintf}. */ const ubo_selector_parser_ERROR_MESSAGES = { DUPLICATED_UBO_MODIFIER: "uBO modifier '%s' cannot be used more than once", EXPECTED_BUT_GOT_BEFORE: "Expected '%s' but got '%s' before '%s'", // eslint-disable-next-line max-len NEGATED_UBO_MODIFIER_CANNOT_BE_FOLLOWED_BY: "Negated uBO modifier '%s' cannot be followed by anything else than a closing parenthesis or a whitespace", NEGATED_UBO_MODIFIER_CANNOT_BE_PRECEDED_BY: "Negated uBO modifier '%s' cannot be preceded by '%s'", PSEUDO_CANNOT_BE_NESTED: "uBO modifier '%s' cannot be nested inside '%s', only '%s' is allowed as a wrapper", UBO_MODIFIER_CANNOT_BE_NESTED: "uBO modifier '%s' cannot be nested", UBO_STYLE_CANNOT_BE_FOLLOWED: 'uBO style injection cannot be followed by anything else than a whitespace', }; /** * Dummy parameter for uBO modifiers in error messages. */ const DUMMY_PARAM = '...'; /** * Set of known uBO modifiers. * * @note We use `string` instead of `UboPseudoName` because we use this set for checking if a modifier is a known uBO, * and an unknown sequence is just a string. */ const KNOWN_UBO_MODIFIERS = new Set([ ubo_selector_common/* .UboPseudoName.MatchesMedia */.S.MatchesMedia, ubo_selector_common/* .UboPseudoName.MatchesPath */.S.MatchesPath, ubo_selector_common/* .UboPseudoName.Remove */.S.Remove, ubo_selector_common/* .UboPseudoName.Style */.S.Style, ]); /** * Helper function to check if the given selector has any uBO modifier. This function should be fast, because it's used * in the hot path of the parser. * * @param raw Raw selector string. * * @returns `true` if the selector has any uBO modifier, `false` otherwise. */ const hasAnyUboModifier = (raw) => { // Find the first colon let colonIndex = raw.indexOf(constants/* .COLON */.oH); while (colonIndex !== -1) { // Find next opening parenthesis const openingParenthesisIndex = raw.indexOf(constants/* .OPEN_PARENTHESIS */.Cx, colonIndex + 1); // If there is no opening parenthesis, then the selector doesn't contain any uBO modifier if (openingParenthesisIndex === -1) { return false; } // Check if the modifier is a known uBO modifier if (KNOWN_UBO_MODIFIERS.has(raw.slice(colonIndex + 1, openingParenthesisIndex))) { return true; } // Find next colon colonIndex = raw.indexOf(constants/* .COLON */.oH, colonIndex + 1); } return false; }; /** * A simple helper function to format a pseudo name for error messages. * * @param name Pseudo name. * @param wrapper Wrapper pseudo name (eg. `not`) (optional, defaults to `undefined`). * * @returns Formatted pseudo name. * * @example * ```ts * formatPseudoName('matches-path', 'not'); // => ':not(:matches-path(...))' * formatPseudoName('matches-media'); // => ':matches-media(...)' * ``` */ const formatPseudoName = (name, wrapper) => { const result = []; if (wrapper) { result.push(constants/* .COLON */.oH, wrapper, constants/* .OPEN_PARENTHESIS */.Cx); } result.push(constants/* .COLON */.oH, name, constants/* .OPEN_PARENTHESIS */.Cx, DUMMY_PARAM, constants/* .CLOSE_PARENTHESIS */.s1); if (wrapper) { result.push(constants/* .CLOSE_PARENTHESIS */.s1); } return result.join(constants/* .EMPTY */.wg); }; /** * Parser for uBO selectors. */ class UboSelectorParser extends base_parser/* .BaseParser */.V { /** * Parses a uBO selector list, eg. `div:matches-path(/path)`. * * @param raw Raw input to parse. * @param options Global parser options. * @param baseOffset Starting offset of the input. Node locations are calculated relative to this offset. * * @returns Parsed uBO selector {@link UboSelectorParser}. * * @throws An {@link AdblockSyntaxError} if the selector list is syntactically invalid. */ static parse(raw, options = parser_options/* .defaultParserOptions */.n, baseOffset = 0) { // Prepare helper variables const modifiers = { type: 'ModifierList', children: [], }; if (options.isLocIncluded) { modifiers.start = baseOffset; modifiers.end = baseOffset + raw.length; } // Do not perform any parsing if the selector doesn't contain any uBO modifier // Parsing is a relatively expensive operation, but this check is cheap, so we can avoid unnecessary work // TODO: Move this check to the cosmetic parser (adjustable syntaxes - if uBO syntax is disabled, then we don't // need to check for uBO modifiers) if (!hasAnyUboModifier(raw)) { const selector = { type: 'Value', value: raw, }; if (options.isLocIncluded) { selector.start = baseOffset; selector.end = baseOffset + raw.length; } const result = { type: 'UboSelector', selector, modifiers, }; if (options.isLocIncluded) { result.start = baseOffset; result.end = baseOffset + raw.length; } return result; } // Simple way to check if a modifier is already processed to avoid duplicate modifiers const processedModifiers = new Set(); // We need to keep track of the tokens for handling negations properly const tokens = []; // This array is used to mark the character slots in the selector string that are occupied by uBO modifiers const uboIndexes = new Array(raw.length); const uboModifierStack = []; let i = 0; // Helper function to stack a uBO modifier const stackModifier = (modifier) => { if (processedModifiers.has(modifier.name)) { throw new adblock_syntax_error/* .AdblockSyntaxError */.q((0,sprintf.sprintf)(ubo_selector_parser_ERROR_MESSAGES.DUPLICATED_UBO_MODIFIER, formatPseudoName(modifier.name)), baseOffset + modifier.modifierStart, baseOffset + raw.length); } uboModifierStack.push(modifier); }; // Tokenize the selector, calculate the balance (0,balancing/* .tokenizeFnBalanced */.g)(raw, (type, start, end, _, balance) => { // Special case: style injection (`:style(...)` and `:remove()`) can only be used at the end of the // selector, like // - `div:style(...)`, // - `div:matches-media(...):style(...)`, // - `div:remove()`, // etc. // // But not like // - `:style(...) div`, // - `:matches-media(...):style(...) div`, // - `:remove() div`, // etc. // // The one exception is whitespace, which is allowed after style injection, like // - `div:style(...) `, // - `div:matches-media(...):style(...) `, // - `div:remove() `, // etc. if ((processedModifiers.has(ubo_selector_common/* .UboPseudoName.Style */.S.Style) || processedModifiers.has(ubo_selector_common/* .UboPseudoName.Remove */.S.Remove)) && type !== csstokenizer/* .TokenType.Whitespace */.ks.Whitespace) { throw new adblock_syntax_error/* .AdblockSyntaxError */.q(ubo_selector_parser_ERROR_MESSAGES.UBO_STYLE_CANNOT_BE_FOLLOWED, baseOffset + start, baseOffset + raw.length); } // Check for pseudo classes (colon followed by a function) if (tokens[i - 1]?.type === csstokenizer/* .TokenType.Colon */.ks.Colon && type === csstokenizer/* .TokenType.Function */.ks.Function) { // Since closing parenthesis is always included in the function token, but we only need the function // name, we need to cut off the last character, this is why we use `end - 1` here const fn = raw.slice(start, end - 1); // Check if the pseudo class is a known uBO modifier if (KNOWN_UBO_MODIFIERS.has(fn)) { // Generally, uBO modifiers cannot be nested, like // - `:any(:matches-media(...))`, // - `:matches-media(:matches-media(...))`, // - `:not(style(...))`, // etc. if (balance > 1) { // However, we have one exception: `:matches-path()` can be nested inside `:not()`s, like: // - `:not(:matches-path(...))`, // - `:not(:not(:matches-path(...)))`, // etc. // // But it can't be nested inside any other pseudo class, like: // - `:anything(:matches-path(...))`, // etc. // // Moreover, :not() can't contain any other data, like // - `:not(div:matches-path(...))`, // - `:not(:matches-path(...):matches-path(...))`, // - `:not(:matches-path(...) div)`, // etc. if (fn === ubo_selector_common/* .UboPseudoName.MatchesPath */.S.MatchesPath) { if (uboModifierStack.length > 0) { throw new adblock_syntax_error/* .AdblockSyntaxError */.q((0,sprintf.sprintf)(ubo_selector_parser_ERROR_MESSAGES.PSEUDO_CANNOT_BE_NESTED, formatPseudoName(ubo_selector_common/* .UboPseudoName.MatchesPath */.S.MatchesPath), formatPseudoName(uboModifierStack[uboModifierStack.length - 1].name), formatPseudoName(constants/* .CSS_NOT_PSEUDO */.vr)), baseOffset + start - 1, baseOffset + raw.length); } let isException = false; let modifierBalance = balance; let modifierStart = start; for (let j = i - 1; j >= 0; j -= 1) { // If we have reached the root level, then we should check if the `not` function is // preceded by a colon (which means that it's a pseudo class) if (tokens[j].balance === 0) { modifierStart = tokens[j].start; modifierBalance = tokens[j].balance; break; } else if (tokens[j].type === csstokenizer/* .TokenType.Colon */.ks.Colon || tokens[j].type === csstokenizer/* .TokenType.Whitespace */.ks.Whitespace) { continue; } else if (tokens[j].type === csstokenizer/* .TokenType.Function */.ks.Function) { const wrapperFnName = raw.slice(tokens[j].start, tokens[j].end - 1); if (wrapperFnName !== constants/* .CSS_NOT_PSEUDO */.vr) { throw new adblock_syntax_error/* .AdblockSyntaxError */.q((0,sprintf.sprintf)(ubo_selector_parser_ERROR_MESSAGES.PSEUDO_CANNOT_BE_NESTED, formatPseudoName(ubo_selector_common/* .UboPseudoName.MatchesPath */.S.MatchesPath), formatPseudoName(wrapperFnName), formatPseudoName(constants/* .CSS_NOT_PSEUDO */.vr)), baseOffset + tokens[j].start - 1, baseOffset + raw.length); } if (tokens[j - 1]?.type !== csstokenizer/* .TokenType.Colon */.ks.Colon) { const got = tokens[j - 1]?.type ? (0,csstokenizer/* .getFormattedTokenName */.bZ)(tokens[j - 1]?.type) : 'nothing'; throw new adblock_syntax_error/* .AdblockSyntaxError */.q((0,sprintf.sprintf)(ubo_selector_parser_ERROR_MESSAGES.EXPECTED_BUT_GOT_BEFORE, (0,csstokenizer/* .getFormattedTokenName */.bZ)(csstokenizer/* .TokenType.Colon */.ks.Colon), got, formatPseudoName(ubo_selector_common/* .UboPseudoName.MatchesPath */.S.MatchesPath, constants/* .CSS_NOT_PSEUDO */.vr)), // eslint-disable-next-line no-unsafe-optional-chaining baseOffset + tokens[j - 1]?.start || 0, baseOffset + raw.length); } isException = !isException; continue; } else { throw new adblock_syntax_error/* .AdblockSyntaxError */.q((0,sprintf.sprintf)(ubo_selector_parser_ERROR_MESSAGES.NEGATED_UBO_MODIFIER_CANNOT_BE_PRECEDED_BY, formatPseudoName(ubo_selector_common/* .UboPseudoName.MatchesPath */.S.MatchesPath), (0,csstokenizer/* .getFormattedTokenName */.bZ)(tokens[j].type)), baseOffset + tokens[j].start, baseOffset + raw.length); } } stackModifier({ name: fn, modifierStart, modifierBalance, nameStart: start, nameEnd: end - 1, // ignore opening parenthesis valueStart: end, valueBalance: balance, isException, }); } else { throw new adblock_syntax_error/* .AdblockSyntaxError */.q((0,sprintf.sprintf)(ubo_selector_parser_ERROR_MESSAGES.UBO_MODIFIER_CANNOT_BE_NESTED, formatPseudoName(fn)), baseOffset + start - 1, baseOffset + raw.length); } } else { stackModifier({ name: fn, modifierStart: start - 1, // Include the colon modifierBalance: balance, nameStart: start, nameEnd: end - 1, // ignore opening parenthesis valueStart: end, valueBalance: balance, isException: false, }); } } } else { // Get the last stacked modifier const lastStackedModifier = uboModifierStack[uboModifierStack.length - 1]; // Do not allow any other token after `:matches-path(...)` inside `:not(...)` if (lastStackedModifier?.name === ubo_selector_common/* .UboPseudoName.MatchesPath */.S.MatchesPath && lastStackedModifier?.isException) { if (!(type === csstokenizer/* .TokenType.CloseParenthesis */.ks.CloseParenthesis || type === csstokenizer/* .TokenType.Whitespace */.ks.Whitespace) && balance < lastStackedModifier.valueBalance) { throw new adblock_syntax_error/* .AdblockSyntaxError */.q((0,sprintf.sprintf)(ubo_selector_parser_ERROR_MESSAGES.NEGATED_UBO_MODIFIER_CANNOT_BE_FOLLOWED_BY, formatPseudoName(ubo_selector_common/* .UboPseudoName.MatchesPath */.S.MatchesPath), (0,csstokenizer/* .getFormattedTokenName */.bZ)(type)), baseOffset + start, baseOffset + raw.length); } } // If we have reached a closing parenthesis, then we should check if it closes the last stacked modifier // and if so, pop it from the stack if (type === csstokenizer/* .TokenType.CloseParenthesis */.ks.CloseParenthesis && lastStackedModifier) { if (balance === Math.max(0, lastStackedModifier.valueBalance - 1)) { lastStackedModifier.valueEnd = start; } if (balance === Math.max(0, lastStackedModifier.modifierBalance - 1)) { const modifierName = { type: 'Value', value: lastStackedModifier.name, }; if (options.isLocIncluded) { // TODO: Refactor modifierName.start = baseOffset + lastStackedModifier.nameStart; modifierName.end = baseOffset + lastStackedModifier.nameEnd; } const value = { type: 'Value', value: raw.slice(lastStackedModifier.valueStart, lastStackedModifier.valueEnd), }; if (options.isLocIncluded) { value.start = baseOffset + lastStackedModifier.valueStart; // It's safe to use `!` here, because we determined the value end index in the // previous `if` statement // eslint-disable-next-line @typescript-eslint/no-non-null-assertion value.end = baseOffset + lastStackedModifier.valueEnd; } const modifier = { type: 'Modifier', name: modifierName, value, exception: lastStackedModifier.isException, }; if (options.isLocIncluded) { modifier.start = baseOffset + lastStackedModifier.modifierStart; modifier.end = baseOffset + end; } modifiers.children.push(modifier); processedModifiers.add(lastStackedModifier.name); uboModifierStack.pop(); // Mark the character slots in the selector string that are occupied by uBO modifiers uboIndexes.fill(true, lastStackedModifier.modifierStart, end); } } } // Save the token to the history and increase the index tokens.push({ type, start, end, balance, }); i += 1; }); const selector = { type: 'Value', value: raw .split(constants/* .EMPTY */.wg) .map((char, p) => (uboIndexes[p] ? constants/* .EMPTY */.wg : char)) .join(constants/* .EMPTY */.wg) .trim(), }; if (options.isLocIncluded) { selector.start = baseOffset; selector.end = baseOffset + raw.length; } const result = { type: 'UboSelector', selector, modifiers, }; if (options.isLocIncluded) { result.start = baseOffset; result.end = baseOffset + raw.length; } return result; } } // EXTERNAL MODULE: ./node_modules/.pnpm/@adguard+agtree@4.2.1/node_modules/@adguard/agtree/dist/parser/misc/domain-list-parser.js + 1 modules var domain_list_parser = __webpack_require__(70254); // EXTERNAL MODULE: ./node_modules/.pnpm/@adguard+agtree@4.2.1/node_modules/@adguard/agtree/dist/parser/misc/modifier-list.js + 1 modules var modifier_list = __webpack_require__(24704); // EXTERNAL MODULE: ./node_modules/.pnpm/@adguard+agtree@4.2.1/node_modules/@adguard/agtree/dist/parser/cosmetic/html-filtering-body/adg-html-filtering-body-parser.js var adg_html_filtering_body_parser = __webpack_require__(55576); // EXTERNAL MODULE: ./node_modules/.pnpm/@adguard+agtree@4.2.1/node_modules/@adguard/agtree/dist/parser/cosmetic/html-filtering-body/ubo-html-filtering-body-parser.js var ubo_html_filtering_body_parser = __webpack_require__(91090); // EXTERNAL MODULE: ./node_modules/.pnpm/@adguard+agtree@4.2.1/node_modules/@adguard/agtree/dist/common/abp-snippet-injection-body-common.js var abp_snippet_injection_body_common = __webpack_require__(7596); // EXTERNAL MODULE: ./node_modules/.pnpm/@adguard+agtree@4.2.1/node_modules/@adguard/agtree/dist/parser/misc/parameter-list-parser.js var parameter_list_parser = __webpack_require__(43939); ;// CONCATENATED MODULE: ./node_modules/.pnpm/@adguard+agtree@4.2.1/node_modules/@adguard/agtree/dist/parser/cosmetic/scriptlet-body/abp-snippet-injection-body-parser.js /* * AGTree v4.2.1 (build date: Wed, 12 Aug 2026 01:31:02 GMT) * (c) 2026 Adguard Software Ltd. * Released under the MIT license * https://github.com/AdguardTeam/tsurlfilter/tree/master/packages/agtree#readme */ /** * @file UBlock scriptlet injection body parser. */ /** * `AbpSnippetInjectionBodyParser` is responsible for parsing the body of an Adblock Plus-style snippet rule. * * Please note that the parser will parse any scriptlet rule if it is syntactically correct. * For example, it will parse this:. * ```adblock * example.com#$#snippet0 arg0 * ``` * * But it didn't check if the scriptlet `snippet0` actually supported by any adblocker.. * * @see {@link https://help.eyeo.com/adblockplus/snippet-filters-tutorial} */ class AbpSnippetInjectionBodyParser extends base_parser/* .BaseParser */.V { /** * Parses the body of an Adblock Plus-style snippet rule. * * @param raw Raw input to parse. * @param options Global parser options. * @param baseOffset Starting offset of the input. Node locations are calculated relative to this offset. * * @returns Node of the parsed scriptlet call body. * * @throws If the body is syntactically incorrect. * * @example * ``` * #$#snippet0 arg0 * ``` */ static parse(raw, options = parser_options/* .defaultParserOptions */.n, baseOffset = 0) { const result = { type: 'ScriptletInjectionRuleBody', children: [], }; if (options.isLocIncluded) { result.start = baseOffset; result.end = baseOffset + raw.length; } let offset = 0; // Skip leading spaces offset = string/* .StringUtils.skipWS */.$x.skipWS(raw, offset); while (offset < raw.length) { offset = string/* .StringUtils.skipWS */.$x.skipWS(raw, offset); const scriptletCallStart = offset; // Find the next semicolon or the end of the string let semicolonIndex = string/* .StringUtils.findUnescapedNonStringNonRegexChar */.$x.findUnescapedNonStringNonRegexChar(raw, constants/* .SEMICOLON */.I8, offset); if (semicolonIndex === -1) { semicolonIndex = raw.length; } const scriptletCallEnd = Math.max(string/* .StringUtils.skipWSBack */.$x.skipWSBack(raw, semicolonIndex - 1) + 1, scriptletCallStart); const params = parameter_list_parser/* .ParameterListParser.parse */.D.parse(raw.slice(scriptletCallStart, scriptletCallEnd), options, baseOffset + scriptletCallStart, constants/* .SPACE */.t6); // Parse the scriptlet call result.children.push(params); // Skip the semicolon offset = semicolonIndex + 1; } if (result.children.length === 0) { throw new adblock_syntax_error/* .AdblockSyntaxError */.q(abp_snippet_injection_body_common/* .AbpSnippetInjectionBodyCommon.ERROR_MESSAGES.EMPTY_SCRIPTLET_CALL */.H.ERROR_MESSAGES.EMPTY_SCRIPTLET_CALL, baseOffset, baseOffset + raw.length); } return result; } } // EXTERNAL MODULE: ./node_modules/.pnpm/@adguard+agtree@4.2.1/node_modules/@adguard/agtree/dist/utils/type-guards.js var type_guards = __webpack_require__(64505); // EXTERNAL MODULE: ./node_modules/.pnpm/@adguard+agtree@4.2.1/node_modules/@adguard/agtree/dist/parser/misc/value-parser.js var value_parser = __webpack_require__(29090); ;// CONCATENATED MODULE: ./node_modules/.pnpm/@adguard+agtree@4.2.1/node_modules/@adguard/agtree/dist/parser/cosmetic/scriptlet-body/adg-scriptlet-injection-body-parser.js /* * AGTree v4.2.1 (build date: Wed, 12 Aug 2026 01:31:02 GMT) * (c) 2026 Adguard Software Ltd. * Released under the MIT license * https://github.com/AdguardTeam/tsurlfilter/tree/master/packages/agtree#readme */ /** * @file AdGuard scriptlet injection body parser. */ /** * `AdgScriptletInjectionBodyParser` is responsible for parsing the body of an AdGuard-style scriptlet rule. * * Please note that the parser will parse any scriptlet rule if it is syntactically correct. * For example, it will parse this:. * ```adblock * example.com#%#//scriptlet('scriptlet0', 'arg0') * ``` * * But it didn't check if the scriptlet `scriptlet0` actually supported by any adblocker.. * * @see {@link https://kb.adguard.com/en/general/how-to-create-your-own-ad-filters#scriptlets} */ class AdgScriptletInjectionBodyParser extends base_parser/* .BaseParser */.V { /** * Error messages used by the parser. */ static ERROR_MESSAGES = { NO_SCRIPTLET_MASK: `Invalid ADG scriptlet call, no scriptlet call mask '${constants/* .ADG_SCRIPTLET_MASK */.x$}' found`, NO_OPENING_PARENTHESIS: `Invalid ADG scriptlet call, no opening parentheses '${constants/* .OPEN_PARENTHESIS */.Cx}' found`, NO_CLOSING_PARENTHESIS: `Invalid ADG scriptlet call, no closing parentheses '${constants/* .CLOSE_PARENTHESIS */.s1}' found`, WHITESPACE_AFTER_MASK: 'Invalid ADG scriptlet call, whitespace is not allowed after the scriptlet call mask', 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'", }; /** * Parses the body of an AdGuard-style scriptlet rule. * * @param raw Raw input to parse. * @param options Global parser options. * @param baseOffset Starting offset of the input. Node locations are calculated relative to this offset. * * @returns Node of the parsed scriptlet call body. * * @throws If the body is syntactically incorrect. * * @example * ``` * //scriptlet('scriptlet0', 'arg0') * ``` */ static parse(raw, options = parser_options/* .defaultParserOptions */.n, baseOffset = 0) { let offset = 0; // Skip leading spaces offset = string/* .StringUtils.skipWS */.$x.skipWS(raw, offset); // Scriptlet call should start with "//scriptlet" if (!raw.startsWith(constants/* .ADG_SCRIPTLET_MASK */.x$, offset)) { throw new adblock_syntax_error/* .AdblockSyntaxError */.q(this.ERROR_MESSAGES.NO_SCRIPTLET_MASK, baseOffset + offset, baseOffset + raw.length); } offset += constants/* .ADG_SCRIPTLET_MASK.length */.x$.length; // Whitespace is not allowed after the mask if (raw[offset] === constants/* .SPACE */.t6) { throw new adblock_syntax_error/* .AdblockSyntaxError */.q(this.ERROR_MESSAGES.WHITESPACE_AFTER_MASK, baseOffset + offset, baseOffset + raw.length); } // Parameter list should be wrapped in parentheses if (raw[offset] !== constants/* .OPEN_PARENTHESIS */.Cx) { throw new adblock_syntax_error/* .AdblockSyntaxError */.q(this.ERROR_MESSAGES.NO_OPENING_PARENTHESIS, baseOffset + offset, baseOffset + raw.length); } // Save the offset of the opening parentheses const openingParenthesesIndex = offset; // Skip whitespace from the end const closingParenthesesIndex = string/* .StringUtils.skipWSBack */.$x.skipWSBack(raw, raw.length - 1); // Closing parentheses should be present if (raw[closingParenthesesIndex] !== constants/* .CLOSE_PARENTHESIS */.s1 || raw[closingParenthesesIndex - 1] === constants/* .ESCAPE_CHARACTER */.Kx) { throw new adblock_syntax_error/* .AdblockSyntaxError */.q(this.ERROR_MESSAGES.NO_CLOSING_PARENTHESIS, baseOffset + offset, baseOffset + raw.length); } // Skip space, if any offset = string/* .StringUtils.skipWS */.$x.skipWS(raw, offset + 1); const result = { type: 'ScriptletInjectionRuleBody', children: [], }; if (options.isLocIncluded) { result.start = baseOffset; result.end = baseOffset + raw.length; } // Special case: empty scriptlet call, like `//scriptlet()`, `//scriptlet( )` etc. if (string/* .StringUtils.skipWS */.$x.skipWS(raw, openingParenthesesIndex + 1) === closingParenthesesIndex) { return result; } let detectedQuote = null; const parameterList = { type: 'ParameterList', children: [], }; if (options.isLocIncluded) { parameterList.start = baseOffset + openingParenthesesIndex + 1; parameterList.end = baseOffset + closingParenthesesIndex; } while (offset < closingParenthesesIndex) { // Skip whitespace offset = string/* .StringUtils.skipWS */.$x.skipWS(raw, offset); // Expect comma if not first parameter if (parameterList.children.length > 0) { if (raw[offset] !== constants/* .COMMA */.KE) { throw new adblock_syntax_error/* .AdblockSyntaxError */.q((0,sprintf.sprintf)(AdgScriptletInjectionBodyParser.ERROR_MESSAGES.EXPECTED_COMMA, raw[offset]), baseOffset + offset, baseOffset + raw.length); } // Eat the comma offset += 1; // Skip whitespace offset = string/* .StringUtils.skipWS */.$x.skipWS(raw, offset); } // Next character should be a quote if (raw[offset] === constants/* .SINGLE_QUOTE */.ur || raw[offset] === constants/* .DOUBLE_QUOTE */.fi) { if ((0,type_guards/* .isNull */.kZ)(detectedQuote)) { detectedQuote = raw[offset]; } else if (detectedQuote !== raw[offset]) { throw new adblock_syntax_error/* .AdblockSyntaxError */.q(AdgScriptletInjectionBodyParser.ERROR_MESSAGES.NO_INCONSISTENT_QUOTES, baseOffset + offset, baseOffset + raw.length); } // Find next unescaped same quote const closingQuoteIndex = string/* .StringUtils.findNextUnescapedCharacter */.$x.findNextUnescapedCharacter(raw, detectedQuote, offset + 1); if (closingQuoteIndex === -1) { throw new adblock_syntax_error/* .AdblockSyntaxError */.q(AdgScriptletInjectionBodyParser.ERROR_MESSAGES.NO_UNCLOSED_PARAMETER, baseOffset + offset, baseOffset + raw.length); } // Save the parameter const parameter = value_parser/* .ValueParser.parse */.J.parse(raw.slice(offset, closingQuoteIndex + 1), options, baseOffset + offset); parameterList.children.push(parameter); // Move after the closing quote offset = string/* .StringUtils.skipWS */.$x.skipWS(raw, closingQuoteIndex + 1); } else { throw new adblock_syntax_error/* .AdblockSyntaxError */.q((0,sprintf.sprintf)(AdgScriptletInjectionBodyParser.ERROR_MESSAGES.EXPECTED_QUOTE, raw[offset]), baseOffset + offset, baseOffset + raw.length); } } result.children.push(parameterList); return result; } } // EXTERNAL MODULE: ./node_modules/.pnpm/@adguard+agtree@4.2.1/node_modules/@adguard/agtree/dist/utils/quotes.js var quotes = __webpack_require__(68999); ;// CONCATENATED MODULE: ./node_modules/.pnpm/@adguard+agtree@4.2.1/node_modules/@adguard/agtree/dist/parser/misc/ubo-parameter-list-parser.js /* * AGTree v4.2.1 (build date: Wed, 12 Aug 2026 01:31:02 GMT) * (c) 2026 Adguard Software Ltd. * Released under the MIT license * https://github.com/AdguardTeam/tsurlfilter/tree/master/packages/agtree#readme */ /** * Parser for uBO-specific parameter lists. */ class UboParameterListParser extends parameter_list_parser/* .ParameterListParser */.D { /** * Parses an "uBO-specific parameter list". * * @param raw Raw input to parse. * @param options Global parser options. * @param baseOffset Starting offset of the input. Node locations are calculated relative to this offset. * @param separator Separator character (default: comma). * @param requireQuotes Whether to require quotes around the parameter values (default: false). * @param supportedQuotes Set of accepted quotes (default: {@link QUOTE_SET}). * * @returns Parameter list node. * * @note Based on {@link https://github.com/gorhill/uBlock/blob/f9ab4b75041815e6e5690d80851189ae3dc660d0/src/js/static-filtering-parser.js#L607-L699} to provide consistency. */ static parse(raw, options = parser_options/* .defaultParserOptions */.n, baseOffset = 0, separator = constants/* .COMMA */.KE, requireQuotes = false, supportedQuotes = quotes/* .QUOTE_SET */.iO) { // Prepare the parameter list node const params = { type: 'ParameterList', children: [], }; const { length } = raw; if (options.isLocIncluded) { params.start = baseOffset; params.end = baseOffset + length; } let offset = 0; // TODO: Eliminate the need for extraNull let extraNull = false; while (offset < length) { offset = string/* .StringUtils.skipWS */.$x.skipWS(raw, offset); const paramStart = offset; let paramEnd = offset; if (supportedQuotes.has(raw[offset])) { // Find the closing quote const possibleClosingQuoteIndex = string/* .StringUtils.findNextUnescapedCharacter */.$x.findNextUnescapedCharacter(raw, raw[offset], offset + 1); if (possibleClosingQuoteIndex !== -1) { // Next non-whitespace character after the closing quote should be the separator const nextSeparatorIndex = string/* .StringUtils.skipWS */.$x.skipWS(raw, possibleClosingQuoteIndex + 1); if (nextSeparatorIndex === length) { // If the separator is not found, the param end is the end of the string paramEnd = string/* .StringUtils.skipWSBack */.$x.skipWSBack(raw, length - 1) + 1; offset = length; } else if (raw[nextSeparatorIndex] === separator) { // If the quote is followed by a separator, we can use it as a closing quote paramEnd = possibleClosingQuoteIndex + 1; offset = nextSeparatorIndex + 1; } else { if (requireQuotes) { throw new adblock_syntax_error/* .AdblockSyntaxError */.q(`Expected separator, got: '${raw[nextSeparatorIndex]}'`, baseOffset + nextSeparatorIndex, baseOffset + length); } /** * At that point found `possibleClosingQuoteIndex` is wrong * | is `offset` * ~ is `possibleClosingQuoteIndex` * ^ is `nextSeparatorIndex`. * * Example 1: "abc, ').cba='1'" * | ~^. * Example 2: "abc, ').cba, '1'" * | ~^ * Example 3: "abc, ').cba='1', cba" * | ~^. * * Search for separator before `possibleClosingQuoteIndex`. */ const separatorIndexBeforeQuote = string/* .StringUtils.findNextUnescapedCharacterBackwards */.$x.findNextUnescapedCharacterBackwards(raw, separator, possibleClosingQuoteIndex, constants/* .ESCAPE_CHARACTER */.Kx, offset + 1); if (separatorIndexBeforeQuote !== -1) { // Found separator before (Example 2) paramEnd = string/* .StringUtils.skipWSBack */.$x.skipWSBack(raw, separatorIndexBeforeQuote - 1) + 1; offset = separatorIndexBeforeQuote + 1; } else { // Didn't found separator before, search after const separatorIndexAfterQuote = string/* .StringUtils.findNextUnescapedCharacter */.$x.findNextUnescapedCharacter(raw, separator, possibleClosingQuoteIndex); if (separatorIndexAfterQuote !== -1) { // We found separator after (Example 3) paramEnd = string/* .StringUtils.skipWSBack */.$x.skipWSBack(raw, separatorIndexAfterQuote - 1) + 1; offset = separatorIndexAfterQuote + 1; } else { // If the separator is not found, the param end is the end of the string (Example 1) paramEnd = string/* .StringUtils.skipWSBack */.$x.skipWSBack(raw, length - 1) + 1; offset = length; } } } } else { if (requireQuotes) { throw new adblock_syntax_error/* .AdblockSyntaxError */.q('Expected closing quote, got end of string', baseOffset + offset, baseOffset + length); } // If the closing quote is not found, the param end is the end of the string paramEnd = string/* .StringUtils.skipWSBack */.$x.skipWSBack(raw, length - 1) + 1; offset = length; } } else { if (requireQuotes) { throw new adblock_syntax_error/* .AdblockSyntaxError */.q(`Expected quote, got: '${raw[offset]}'`, baseOffset + offset, baseOffset + length); } const nextSeparator = string/* .StringUtils.findNextUnescapedCharacter */.$x.findNextUnescapedCharacter(raw, separator, offset); if (nextSeparator === -1) { // If the separator is not found, the param end is the end of the string paramEnd = string/* .StringUtils.skipWSBack */.$x.skipWSBack(raw, length - 1) + 1; offset = length; } else { // Param end should be the last non-whitespace character before the separator paramEnd = string/* .StringUtils.skipWSBack */.$x.skipWSBack(raw, nextSeparator - 1) + 1; offset = nextSeparator + 1; if (string/* .StringUtils.skipWS */.$x.skipWS(raw, length - 1) === nextSeparator) { extraNull = true; } } } if (paramStart < paramEnd) { params.children.push(value_parser/* .ValueParser.parse */.J.parse(raw.slice(paramStart, paramEnd), options, baseOffset + paramStart)); } else { params.children.push(null); } } if (extraNull) { params.children.push(null); } return params; } } ;// CONCATENATED MODULE: ./node_modules/.pnpm/@adguard+agtree@4.2.1/node_modules/@adguard/agtree/dist/parser/cosmetic/scriptlet-body/ubo-scriptlet-injection-body-parser.js /* * AGTree v4.2.1 (build date: Wed, 12 Aug 2026 01:31:02 GMT) * (c) 2026 Adguard Software Ltd. * Released under the MIT license * https://github.com/AdguardTeam/tsurlfilter/tree/master/packages/agtree#readme */ /** * @file UBlock scriptlet injection body parser. */ /** * `UboScriptletInjectionBodyParser` is responsible for parsing the body of a uBlock-style scriptlet rule. * * Please note that the parser will parse any scriptlet rule if it is syntactically correct. * For example, it will parse this:. * ```adblock * example.com##+js(scriptlet0, arg0) * ``` * * But it didn't check if the scriptlet `scriptlet0` actually supported by any adblocker.. * * @see {@link https://github.com/gorhill/uBlock/wiki/Static-filter-syntax#scriptlet-injection} */ class UboScriptletInjectionBodyParser extends base_parser/* .BaseParser */.V { /** * Error messages used by the parser. */ static ERROR_MESSAGES = { NO_SCRIPTLET_MASK: `Invalid uBO scriptlet call, no scriptlet call mask '${constants/* .UBO_SCRIPTLET_MASK */.Rq}' found`, NO_OPENING_PARENTHESIS: `Invalid uBO scriptlet call, no opening parentheses '${constants/* .OPEN_PARENTHESIS */.Cx}' found`, NO_CLOSING_PARENTHESIS: `Invalid uBO scriptlet call, no closing parentheses '${constants/* .CLOSE_PARENTHESIS */.s1}' 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', }; /** * Parses the body of a uBlock-style scriptlet rule. * * @param raw Raw input to parse. * @param options Global parser options. * @param baseOffset Starting offset of the input. Node locations are calculated relative to this offset. * * @returns Node of the parsed scriptlet call body. * * @throws If the body is syntactically incorrect. * * @example * ``` * ##+js(scriptlet0, arg0) * ``` */ static parse(raw, options = parser_options/* .defaultParserOptions */.n, baseOffset = 0) { let offset = 0; // Skip leading spaces offset = string/* .StringUtils.skipWS */.$x.skipWS(raw, offset); let scriptletMaskLength = 0; if (raw.startsWith(constants/* .UBO_SCRIPTLET_MASK */.Rq, offset)) { scriptletMaskLength = constants/* .UBO_SCRIPTLET_MASK.length */.Rq.length; } else if (raw.startsWith(constants/* .UBO_SCRIPTLET_MASK_LEGACY */.Vs, offset)) { scriptletMaskLength = constants/* .UBO_SCRIPTLET_MASK_LEGACY.length */.Vs.length; } // Scriptlet call should start with "+js" if (!scriptletMaskLength) { throw new adblock_syntax_error/* .AdblockSyntaxError */.q(this.ERROR_MESSAGES.NO_SCRIPTLET_MASK, baseOffset + offset, baseOffset + raw.length); } offset += scriptletMaskLength; // Whitespace is not allowed after the mask if (raw[offset] === constants/* .SPACE */.t6) { throw new adblock_syntax_error/* .AdblockSyntaxError */.q(this.ERROR_MESSAGES.WHITESPACE_AFTER_MASK, baseOffset + offset, baseOffset + raw.length); } // Parameter list should be wrapped in parentheses if (raw[offset] !== constants/* .OPEN_PARENTHESIS */.Cx) { throw new adblock_syntax_error/* .AdblockSyntaxError */.q(this.ERROR_MESSAGES.NO_OPENING_PARENTHESIS, baseOffset + offset, baseOffset + raw.length); } // Save the offset of the opening parentheses const openingParenthesesIndex = offset; // Skip whitespace from the end const closingParenthesesIndex = string/* .StringUtils.skipWSBack */.$x.skipWSBack(raw, raw.length - 1); // Closing parentheses should be present if (raw[closingParenthesesIndex] !== constants/* .CLOSE_PARENTHESIS */.s1 || raw[closingParenthesesIndex - 1] === constants/* .ESCAPE_CHARACTER */.Kx) { throw new adblock_syntax_error/* .AdblockSyntaxError */.q(this.ERROR_MESSAGES.NO_CLOSING_PARENTHESIS, baseOffset + offset, baseOffset + raw.length); } const result = { type: 'ScriptletInjectionRuleBody', children: [], }; if (options.isLocIncluded) { result.start = baseOffset; result.end = baseOffset + raw.length; } // Special case: empty scriptlet call, like +js(), +js( ), etc. if (string/* .StringUtils.skipWS */.$x.skipWS(raw, openingParenthesesIndex + 1) === closingParenthesesIndex) { return result; } // Parse parameter list const params = UboParameterListParser.parse(raw.slice(openingParenthesesIndex + 1, closingParenthesesIndex), options, baseOffset + openingParenthesesIndex + 1, constants/* .COMMA */.KE); // Do not allow parameters without scriptlet: +js(, arg0, arg1) if (params.children.length > 0 && params.children[0] === null) { throw new adblock_syntax_error/* .AdblockSyntaxError */.q(this.ERROR_MESSAGES.NO_SCRIPTLET_NAME, baseOffset + offset, baseOffset + raw.length); } result.children.push(params); return result; } } ;// CONCATENATED MODULE: ./node_modules/.pnpm/@adguard+agtree@4.2.1/node_modules/@adguard/agtree/dist/parser/cosmetic/cosmetic-rule-parser.js /* * AGTree v4.2.1 (build date: Wed, 12 Aug 2026 01:31:02 GMT) * (c) 2026 Adguard Software Ltd. * Released under the MIT license * https://github.com/AdguardTeam/tsurlfilter/tree/master/packages/agtree#readme */ /** * Possible error messages for uBO selectors. Formatted with {@link sprintf}. */ const cosmetic_rule_parser_ERROR_MESSAGES = { EMPTY_RULE_BODY: 'Empty rule body', INVALID_BODY_FOR_SEPARATOR: "Body '%s' is not valid for the '%s' cosmetic rule separator", MISSING_ADGUARD_MODIFIER_LIST_END: "Missing '%s' at the end of the AdGuard modifier list in pattern '%s'", MISSING_ADGUARD_MODIFIER_LIST_MARKER: "Missing '%s' at the beginning of the AdGuard modifier list in pattern '%s'", SYNTAXES_CANNOT_BE_MIXED: "'%s' syntax cannot be mixed with '%s' syntax", SYNTAX_DISABLED: "Parsing '%s' syntax is disabled, but the rule uses it", }; const ADG_CSS_INJECTION_PATTERN = /^(?:.+){(?:.+)}$/; /** * `CosmeticRuleParser` is responsible for parsing cosmetic rules. * * Where possible, it automatically detects the difference between supported syntaxes: * - AdGuard * - uBlock Origin * - Adblock Plus. * * If the syntax is common / cannot be determined, the parser gives `Common` syntax. * * Please note that syntactically correct rules are parsed even if they are not actually * compatible with the given adblocker. This is a completely natural behavior, meaningful * checking of compatibility is not done at the parser level. */ // TODO: Make raw body parsing optional // TODO: Split into smaller sections class CosmeticRuleParser extends base_parser/* .BaseParser */.V { /** * Determines whether a rule is a cosmetic rule. The rule is considered cosmetic if it * contains a cosmetic rule separator. * * @param raw Raw rule. * * @returns `true` if the rule is a cosmetic rule, `false` otherwise. */ static isCosmeticRule(raw) { const trimmed = raw.trim(); if (comment_parser/* .CommentParser.isCommentRule */.B.isCommentRule(trimmed)) { return false; } return cosmetic_rule_separator/* .CosmeticRuleSeparatorUtils.find */.m.find(trimmed) !== null; } /** * Parses a cosmetic rule. The structure of the cosmetic rules: * - pattern (AdGuard pattern can have modifiers, other syntaxes don't) * - separator * - body. * * @param raw Raw input to parse. * @param options Global parser options. * @param baseOffset Starting offset of the input. Node locations are calculated relative to this offset. * * @returns * Parsed cosmetic rule AST or null if it failed to parse based on the known cosmetic rules. * * @throws If the input matches the cosmetic rule pattern but syntactically invalid. */ // TODO: Split to smaller functions static parse(raw, options = parser_options/* .defaultParserOptions */.n, baseOffset = 0) { // Find cosmetic rule separator - each cosmetic rule must have it, otherwise it is not a cosmetic rule const separatorResult = cosmetic_rule_separator/* .CosmeticRuleSeparatorUtils.find */.m.find(raw); if (!separatorResult) { return null; } let syntax = adblockers/* .AdblockSyntax.Common */.YG.Common; let modifiers; const patternStart = string/* .StringUtils.skipWS */.$x.skipWS(raw); const patternEnd = string/* .StringUtils.skipWSBack */.$x.skipWSBack(raw, separatorResult.start - 1) + 1; const bodyStart = string/* .StringUtils.skipWS */.$x.skipWS(raw, separatorResult.end); const bodyEnd = string/* .StringUtils.skipWSBack */.$x.skipWSBack(raw) + 1; // Note we use '<=' instead of '===' because we have bidirectional trim if (bodyEnd <= bodyStart) { throw new adblock_syntax_error/* .AdblockSyntaxError */.q(cosmetic_rule_parser_ERROR_MESSAGES.EMPTY_RULE_BODY, baseOffset, baseOffset + raw.length); } // Step 1. Parse the pattern: it can be a domain list or a domain list with modifiers (AdGuard) const rawPattern = raw.slice(patternStart, patternEnd); let patternOffset = patternStart; if (rawPattern[patternOffset] === constants/* .OPEN_SQUARE_BRACKET */.cU) { // Save offset to the beginning of the modifier list for later const modifierListStart = patternOffset; // Consume opening square bracket patternOffset += 1; // Skip whitespace after opening square bracket patternOffset = string/* .StringUtils.skipWS */.$x.skipWS(rawPattern, patternOffset); // Open square bracket should be followed by a modifier separator: [$ if (rawPattern[patternOffset] !== constants/* .DOLLAR_SIGN */.nj) { throw new adblock_syntax_error/* .AdblockSyntaxError */.q((0,sprintf.sprintf)(cosmetic_rule_parser_ERROR_MESSAGES.MISSING_ADGUARD_MODIFIER_LIST_MARKER, constants/* .DOLLAR_SIGN */.nj, rawPattern), baseOffset + patternOffset, baseOffset + rawPattern.length); } // Consume modifier separator patternOffset += 1; // Skip whitespace after modifier separator patternOffset = string/* .StringUtils.skipWS */.$x.skipWS(rawPattern, patternOffset); // Modifier list ends with the last unescaped square bracket // that is not inside a regex or string // We search for the last such square bracket, // because some modifiers can contain square brackets, // e.g. [$domain=/example[0-9]\.(com|org)/]##.ad const modifierListEnd = string/* .StringUtils.findLastUnescapedNonStringNonRegexChar */.$x.findLastUnescapedNonStringNonRegexChar(rawPattern, constants/* .CLOSE_SQUARE_BRACKET */.A1); if (modifierListEnd === -1) { throw new adblock_syntax_error/* .AdblockSyntaxError */.q((0,sprintf.sprintf)(cosmetic_rule_parser_ERROR_MESSAGES.MISSING_ADGUARD_MODIFIER_LIST_END, constants/* .CLOSE_SQUARE_BRACKET */.A1, rawPattern), baseOffset + patternOffset, baseOffset + rawPattern.length); } // Parse modifier list modifiers = modifier_list/* .ModifierListParser.parse */.l.parse(raw.slice(patternOffset, modifierListEnd), options, baseOffset + patternOffset); // Expand modifier list location to include the opening and closing square brackets if (options.isLocIncluded) { modifiers.start = baseOffset + modifierListStart; modifiers.end = baseOffset + modifierListEnd + 1; } // Consume modifier list patternOffset = modifierListEnd + 1; // Change the syntax to ADG syntax = adblockers/* .AdblockSyntax.Adg */.YG.Adg; } // Skip whitespace after modifier list patternOffset = string/* .StringUtils.skipWS */.$x.skipWS(rawPattern, patternOffset); // Parse domains const domains = domain_list_parser/* .DomainListParser.parse */.y.parse(rawPattern.slice(patternOffset), options, baseOffset + patternOffset); // Step 2. Parse the separator const separator = { type: 'Value', value: separatorResult.separator, }; if (options.isLocIncluded) { separator.start = baseOffset + separatorResult.start; separator.end = baseOffset + separatorResult.end; } const exception = cosmetic_rule_separator/* .CosmeticRuleSeparatorUtils.isException */.m.isException(separatorResult.separator); // Step 3. Parse the rule body let rawBody = raw.slice(bodyStart, bodyEnd); /** * Ensures that the rule syntax is common or the expected one. This function is used to prevent mixing * different syntaxes in the same rule. * * @param expectedSyntax Expected syntax. * * @throws If the rule syntax is not common or the expected one. * * @example * The following rule mixes AdGuard and uBO syntaxes, because it uses AdGuard modifier list and uBO * CSS injection: * ```adblock * [$path=/something]example.com##.foo:style(color: red) * ``` * In this case, parser sets syntax to AdGuard, because it detects the AdGuard modifier list, but * when parsing the rule body, it detects uBO CSS injection, which is not compatible with AdGuard. */ const expectCommonOrSpecificSyntax = (expectedSyntax) => { if (syntax !== adblockers/* .AdblockSyntax.Common */.YG.Common && syntax !== expectedSyntax) { throw new adblock_syntax_error/* .AdblockSyntaxError */.q((0,sprintf.sprintf)(cosmetic_rule_parser_ERROR_MESSAGES.SYNTAXES_CANNOT_BE_MIXED, expectedSyntax, syntax), baseOffset + patternStart, baseOffset + bodyEnd); } }; let uboSelector; // Parse UBO rule modifiers if (options.parseUboSpecificRules) { uboSelector = UboSelectorParser.parse(rawBody, options, baseOffset + bodyStart); rawBody = uboSelector.selector.value; // Do not allow ADG modifiers and UBO modifiers in the same rule if (uboSelector.modifiers && uboSelector.modifiers.children.length > 0) { // If modifiers are present, that means that the ADG modifier list was parsed expectCommonOrSpecificSyntax(adblockers/* .AdblockSyntax.Ubo */.YG.Ubo); // Change the syntax to uBO syntax = adblockers/* .AdblockSyntax.Ubo */.YG.Ubo; // Store the rule modifiers // Please note that not each special uBO modifier is a rule modifier, some of them are // used for CSS injection, for example `:style()` and `:remove()` for (const modifier of uboSelector.modifiers.children) { // TODO: Add support for matches-media and element hiding rules // TODO: Improve this condition if new uBO modifiers are added if (modifier.name.value === ubo_selector_common/* .UboPseudoName.MatchesPath */.S.MatchesPath) { // Prepare the modifier list if it does not exist yet if (!modifiers) { modifiers = { type: 'ModifierList', children: [], }; if (options.isLocIncluded) { modifiers.start = baseOffset + bodyStart; modifiers.end = baseOffset + bodyEnd; } } modifiers.children.push(modifier); } } } } const raws = { text: raw, }; const baseRule = { category: nodes/* .RuleCategory.Cosmetic */.$O.Cosmetic, exception, modifiers, domains, separator, }; if (options.includeRaws) { baseRule.raws = raws; } if (options.isLocIncluded) { baseRule.start = baseOffset; baseRule.end = baseOffset + raw.length; } const parseUboCssInjection = () => { if (!uboSelector || !uboSelector.modifiers || uboSelector.modifiers.children?.length < 1) { return null; } expectCommonOrSpecificSyntax(adblockers/* .AdblockSyntax.Ubo */.YG.Ubo); const selectorList = uboSelector.selector; let declarationList; let mediaQueryList; let remove = false; for (const modifier of uboSelector.modifiers.children) { switch (modifier.name.value) { case ubo_selector_common/* .UboPseudoName.Style */.S.Style: declarationList = modifier.value; break; case ubo_selector_common/* .UboPseudoName.Remove */.S.Remove: declarationList = { type: 'Value', value: '', }; remove = true; break; case ubo_selector_common/* .UboPseudoName.MatchesMedia */.S.MatchesMedia: mediaQueryList = modifier.value; break; } } // If neither `:style()` nor `:remove()` is present if (!declarationList) { return null; } const body = { type: 'CssInjectionRuleBody', selectorList, declarationList, mediaQueryList, remove, }; if (options.isLocIncluded) { body.start = baseOffset + bodyStart; body.end = baseOffset + bodyEnd; } return { syntax: adblockers/* .AdblockSyntax.Ubo */.YG.Ubo, type: nodes/* .CosmeticRuleType.CssInjectionRule */.k9.CssInjectionRule, body, }; }; const parseElementHiding = () => { const selectorList = { type: 'Value', value: rawBody, }; if (options.isLocIncluded) { selectorList.start = baseOffset + bodyStart; selectorList.end = baseOffset + bodyEnd; } const body = { type: 'ElementHidingRuleBody', selectorList, }; if (options.isLocIncluded) { body.start = baseOffset + bodyStart; body.end = baseOffset + bodyEnd; } return { syntax, type: nodes/* .CosmeticRuleType.ElementHidingRule */.k9.ElementHidingRule, body, }; }; const parseAdgCssInjection = () => { // TODO: Improve this detection. Need to cover the following cases: // #$#body { color: red; // #$#@media (min-width: 100px) { body { color: red; } // ADG CSS injection if (!ADG_CSS_INJECTION_PATTERN.test(rawBody)) { return null; } expectCommonOrSpecificSyntax(adblockers/* .AdblockSyntax.Adg */.YG.Adg); return { syntax: adblockers/* .AdblockSyntax.Adg */.YG.Adg, type: nodes/* .CosmeticRuleType.CssInjectionRule */.k9.CssInjectionRule, body: AdgCssInjectionParser.parse(rawBody, options, baseOffset + bodyStart), }; }; /** * Parses Adb CSS injection rules * eg: example.com##.foo { display: none; }. * * @returns Parsed rule. */ const parseAbpCssInjection = () => { if (!options.parseAbpSpecificRules) { return null; } // check if the rule contains both CSS block open and close characters // if none of them is present we can stop parsing if (rawBody.indexOf(constants/* .CSS_BLOCK_OPEN */.zW) === -1 && rawBody.indexOf(constants/* .CSS_BLOCK_CLOSE */.pi) === -1) { return null; } if (!(0,csstokenizer/* .hasToken */.y0)(rawBody, new Set([csstokenizer/* .TokenType.OpenCurlyBracket */.ks.OpenCurlyBracket, csstokenizer/* .TokenType.CloseCurlyBracket */.ks.CloseCurlyBracket]))) { return null; } // try to parse the raw body as an AdGuard CSS injection rule const body = AdgCssInjectionParser.parse(rawBody, options, baseOffset + bodyStart); // if the parsed rule type is a 'CssInjectionRuleBody', return the parsed rule return { syntax: adblockers/* .AdblockSyntax.Abp */.YG.Abp, type: nodes/* .CosmeticRuleType.CssInjectionRule */.k9.CssInjectionRule, body, }; }; const parseAbpSnippetInjection = () => { if (!options.parseAbpSpecificRules) { throw new adblock_syntax_error/* .AdblockSyntaxError */.q((0,sprintf.sprintf)(cosmetic_rule_parser_ERROR_MESSAGES.SYNTAX_DISABLED, adblockers/* .AdblockSyntax.Abp */.YG.Abp), baseOffset + bodyStart, baseOffset + bodyEnd); } expectCommonOrSpecificSyntax(adblockers/* .AdblockSyntax.Abp */.YG.Abp); const body = AbpSnippetInjectionBodyParser.parse(rawBody, options, baseOffset + bodyStart); if (options.isLocIncluded) { body.start = baseOffset + bodyStart; body.end = baseOffset + bodyEnd; } return { syntax: adblockers/* .AdblockSyntax.Abp */.YG.Abp, type: nodes/* .CosmeticRuleType.ScriptletInjectionRule */.k9.ScriptletInjectionRule, body, }; }; const parseUboScriptletInjection = () => { if (!rawBody.startsWith(constants/* .UBO_SCRIPTLET_MASK */.Rq) && !rawBody.startsWith(constants/* .UBO_SCRIPTLET_MASK_LEGACY */.Vs)) { return null; } if (!options.parseUboSpecificRules) { throw new adblock_syntax_error/* .AdblockSyntaxError */.q((0,sprintf.sprintf)(cosmetic_rule_parser_ERROR_MESSAGES.SYNTAX_DISABLED, adblockers/* .AdblockSyntax.Ubo */.YG.Ubo), baseOffset + bodyStart, baseOffset + bodyEnd); } expectCommonOrSpecificSyntax(adblockers/* .AdblockSyntax.Ubo */.YG.Ubo); const body = UboScriptletInjectionBodyParser.parse(rawBody, options, baseOffset + bodyStart); if (options.isLocIncluded) { body.start = baseOffset + bodyStart; body.end = baseOffset + bodyEnd; } return { syntax: adblockers/* .AdblockSyntax.Ubo */.YG.Ubo, type: nodes/* .CosmeticRuleType.ScriptletInjectionRule */.k9.ScriptletInjectionRule, body, }; }; const parseAdgScriptletInjection = () => { // ADG scriptlet injection if (!rawBody.startsWith(constants/* .ADG_SCRIPTLET_MASK */.x$)) { return null; } expectCommonOrSpecificSyntax(adblockers/* .AdblockSyntax.Adg */.YG.Adg); const body = AdgScriptletInjectionBodyParser.parse(rawBody, options, baseOffset + bodyStart); if (options.isLocIncluded) { body.start = baseOffset + bodyStart; body.end = baseOffset + bodyEnd; } return { syntax: adblockers/* .AdblockSyntax.Adg */.YG.Adg, type: nodes/* .CosmeticRuleType.ScriptletInjectionRule */.k9.ScriptletInjectionRule, body, }; }; const parseAdgJsInjection = () => { expectCommonOrSpecificSyntax(adblockers/* .AdblockSyntax.Adg */.YG.Adg); const body = { type: 'Value', value: rawBody, }; if (options.isLocIncluded) { body.start = baseOffset + bodyStart; body.end = baseOffset + bodyEnd; } return { syntax: adblockers/* .AdblockSyntax.Adg */.YG.Adg, type: nodes/* .CosmeticRuleType.JsInjectionRule */.k9.JsInjectionRule, body, }; }; const parseUboHtmlFiltering = () => { if (!rawBody.startsWith(constants/* .UBO_HTML_MASK */._h)) { return null; } if (!options.parseUboSpecificRules) { throw new adblock_syntax_error/* .AdblockSyntaxError */.q((0,sprintf.sprintf)(cosmetic_rule_parser_ERROR_MESSAGES.SYNTAX_DISABLED, adblockers/* .AdblockSyntax.Ubo */.YG.Ubo), baseOffset + bodyStart, baseOffset + bodyEnd); } expectCommonOrSpecificSyntax(adblockers/* .AdblockSyntax.Ubo */.YG.Ubo); const rawBodyWithoutMask = rawBody.slice(constants/* .UBO_HTML_MASK.length */._h.length); const body = ubo_html_filtering_body_parser/* .UboHtmlFilteringBodyParser.parse */.V.parse(rawBodyWithoutMask, options, baseOffset + bodyStart + constants/* .UBO_HTML_MASK.length */._h.length); return { syntax: adblockers/* .AdblockSyntax.Ubo */.YG.Ubo, type: nodes/* .CosmeticRuleType.HtmlFilteringRule */.k9.HtmlFilteringRule, body, }; }; const parseAdgHtmlFiltering = () => { expectCommonOrSpecificSyntax(adblockers/* .AdblockSyntax.Adg */.YG.Adg); const body = adg_html_filtering_body_parser/* .AdgHtmlFilteringBodyParser.parse */.h.parse(rawBody, options, baseOffset + bodyStart); return { syntax: adblockers/* .AdblockSyntax.Adg */.YG.Adg, type: nodes/* .CosmeticRuleType.HtmlFilteringRule */.k9.HtmlFilteringRule, body, }; }; // Create a fast lookup table for cosmetic rule separators and their parsing functions. // One separator can have multiple parsing functions. If the first function returns null, // the next function is called, and so on. // If all functions return null, an error should be thrown. const separatorMap = { '##': [ parseUboHtmlFiltering, parseUboScriptletInjection, parseUboCssInjection, parseAbpCssInjection, parseElementHiding, ], '#@#': [ parseUboHtmlFiltering, parseUboScriptletInjection, parseUboCssInjection, parseAbpCssInjection, parseElementHiding, ], '#?#': [parseUboCssInjection, parseAbpCssInjection, parseElementHiding], '#@?#': [parseUboCssInjection, parseAbpCssInjection, parseElementHiding], '#$#': [parseAdgCssInjection, parseAbpSnippetInjection], '#@$#': [parseAdgCssInjection, parseAbpSnippetInjection], '#$?#': [parseAdgCssInjection], '#@$?#': [parseAdgCssInjection], '#%#': [parseAdgScriptletInjection, parseAdgJsInjection], '#@%#': [parseAdgScriptletInjection, parseAdgJsInjection], $$: [parseAdgHtmlFiltering], '$@$': [parseAdgHtmlFiltering], }; const parseFunctions = separatorMap[separatorResult.separator]; let restProps; for (const parseFunction of parseFunctions) { restProps = parseFunction(); if (restProps) { break; } } // If none of the parsing functions returned a result, it means that the rule is unknown / invalid. if (!restProps) { throw new adblock_syntax_error/* .AdblockSyntaxError */.q((0,sprintf.sprintf)(cosmetic_rule_parser_ERROR_MESSAGES.INVALID_BODY_FOR_SEPARATOR, rawBody, separatorResult.separator), baseOffset + bodyStart, baseOffset + bodyEnd); } // Combine the base rule with the rest of the properties. return { ...baseRule, ...restProps, }; } } }, 55576(__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) { __webpack_require__.d(__webpack_exports__, { h: () => (AdgHtmlFilteringBodyParser) }); /* import */ var _utils_quotes_js__rspack_import_2 = __webpack_require__(68999); /* import */ var _base_parser_js__rspack_import_0 = __webpack_require__(79963); /* import */ var _options_js__rspack_import_1 = __webpack_require__(64626); /* import */ var _html_filtering_body_parser_js__rspack_import_3 = __webpack_require__(15683); /* * AGTree v4.2.1 (build date: Wed, 12 Aug 2026 01:31:02 GMT) * (c) 2026 Adguard Software Ltd. * Released under the MIT license * https://github.com/AdguardTeam/tsurlfilter/tree/master/packages/agtree#readme */ /** * `AdgHtmlFilteringBodyParser` is responsible for parsing the body of an AdGuard-style HTML filtering rule. * * Please note that the parser will parse any HTML filtering rule if it is syntactically correct. * For example, it will parse this:. * ```adblock * example.com$$div[special-attr="value"] * ``` * * But it didn't check if the attribute `special-attr` actually supported by any adblocker.. * * @see {@link https://www.w3.org/TR/selectors-4} * @see {@link https://adguard.com/kb/general/ad-filtering/create-own-filters/#html-filtering-rules} */ class AdgHtmlFilteringBodyParser extends _base_parser_js__rspack_import_0/* .BaseParser */.V { /** * Parses the body of an AdGuard-style HTML filtering rule. * * @param raw Raw input to parse. * @param options Global parser options. * @param baseOffset Starting offset of the input. Node locations are calculated relative to this offset. * * @returns Node of the parsed HTML filtering rule body. * * @throws If the body is syntactically incorrect. * * @example * ``` * div[some_attribute="some_value"] * ``` */ static parse(raw, options = _options_js__rspack_import_1/* .defaultParserOptions */.n, baseOffset = 0) { // Only escape AdGuard's `""` → `\"` when the body will actually be // CSS-parsed. When `parseHtmlFilteringRuleBodies` is false the raw // string is stored as-is in a Value node; escaping here would cause // double-escaping when the converter later re-parses it. // // Needed for proper `[tag-content]` conversion (to `:contains()`) // where `""` must be used to escape `"`: // https://adguard.com/kb/general/ad-filtering/create-own-filters/#tag-content const input = options.parseHtmlFilteringRuleBodies ? _utils_quotes_js__rspack_import_2/* .QuoteUtils.escapeAttributeDoubleQuotes */.Qj.escapeAttributeDoubleQuotes(raw) : raw; return _html_filtering_body_parser_js__rspack_import_3/* .HtmlFilteringBodyParser.parse */.F.parse(input, options, baseOffset); } } }, 15683(__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) { // EXPORTS __webpack_require__.d(__webpack_exports__, { F: () => (/* binding */ HtmlFilteringBodyParser) }); // EXTERNAL MODULE: ./node_modules/.pnpm/@adguard+agtree@4.2.1/node_modules/@adguard/agtree/dist/parser/base-parser.js var base_parser = __webpack_require__(79963); // EXTERNAL MODULE: ./node_modules/.pnpm/@adguard+agtree@4.2.1/node_modules/@adguard/agtree/dist/parser/options.js var parser_options = __webpack_require__(64626); // EXTERNAL MODULE: ./node_modules/.pnpm/sprintf-js@1.1.3/node_modules/sprintf-js/src/sprintf.js var sprintf = __webpack_require__(37155); // EXTERNAL MODULE: ./node_modules/.pnpm/@adguard+css-tokenizer@1.2.0/node_modules/@adguard/css-tokenizer/dist/csstokenizer.mjs var csstokenizer = __webpack_require__(83747); // EXTERNAL MODULE: ./node_modules/.pnpm/@adguard+agtree@4.2.1/node_modules/@adguard/agtree/dist/errors/adblock-syntax-error.js var adblock_syntax_error = __webpack_require__(10631); // EXTERNAL MODULE: ./node_modules/.pnpm/@adguard+agtree@4.2.1/node_modules/@adguard/agtree/dist/utils/constants.js var constants = __webpack_require__(53097); // EXTERNAL MODULE: ./node_modules/.pnpm/@adguard+agtree@4.2.1/node_modules/@adguard/agtree/dist/parser/css/css-token-stream.js var css_token_stream = __webpack_require__(44148); // EXTERNAL MODULE: ./node_modules/.pnpm/@adguard+agtree@4.2.1/node_modules/@adguard/agtree/dist/utils/quotes.js var quotes = __webpack_require__(68999); // EXTERNAL MODULE: ./node_modules/.pnpm/@adguard+agtree@4.2.1/node_modules/@adguard/agtree/dist/parser/misc/value-parser.js var value_parser = __webpack_require__(29090); ;// CONCATENATED MODULE: ./node_modules/.pnpm/@adguard+agtree@4.2.1/node_modules/@adguard/agtree/dist/parser/cosmetic/selector/handlers/attribute-selector-handler.js /* * AGTree v4.2.1 (build date: Wed, 12 Aug 2026 01:31:02 GMT) * (c) 2026 Adguard Software Ltd. * Released under the MIT license * https://github.com/AdguardTeam/tsurlfilter/tree/master/packages/agtree#readme */ /** * Handles attribute selector parsing in selector list. */ class AttributeSelectorHandler { /** * Set of attribute equality prefixes. * * @see {@link AttributeSelectorOperatorValue} */ static ATTR_EQUALITY_PREFIXES = new Set([ // [attr~="value"] constants/* .TILDE */.wR, // [attr^="value"] constants/* .CARET */.cP, // [attr$="value"] constants/* .DOLLAR_SIGN */.nj, // [attr*="value"] constants/* .ASTERISK */.Ln, // [attr|="value"] constants/* .PIPE */.L5, ]); /** * Set of valid flags for attribute selector values. * * @see {@link AttributeSelectorFlagValue} */ static ALLOWED_ATTRIBUTE_FLAGS = new Set([ 'i', 's', ]); /** * Handles attribute selector parsing by creating an attribute selector node * and appending it to the current complex selector node. * * @param context Selector list parser context. * * @throws If the attribute selector is syntactically incorrect. */ static handle(context) { const { options, baseOffset, stream, complexSelector, } = context; // Get open square bracket token let token = stream.getOrFail(); // Save attribute selector node start position const { start } = token; // Advance open square bracket token stream.advance(); // Skip whitespaces after open square bracket stream.skipWhitespace(); // Expect next token to be an identifier (attribute selector name) stream.expect(csstokenizer/* .TokenType.Ident */.ks.Ident); // Get attribute selector name token token = stream.getOrFail(); // Extract attribute selector name raw value const nameRaw = stream.fragment(); // Construct attribute selector node and attribute selector name node const result = { type: 'AttributeSelector', name: value_parser/* .ValueParser.parse */.J.parse(nameRaw, options, baseOffset + token.start), }; // Include attribute selector node start location if needed if (options.isLocIncluded) { result.start = baseOffset + start; } // Advance attribute selector name token stream.advance(); // Skip whitespaces after attribute selector name stream.skipWhitespace(); // Get closing square bracket or equality sign/prefix token token = stream.getOrFail(); // Check if there is an any value if (token.type !== csstokenizer/* .TokenType.CloseSquareBracket */.ks.CloseSquareBracket) { // Expect next token to be a delimiter (equality sign/prefix) stream.expect(csstokenizer/* .TokenType.Delim */.ks.Delim); // Extract operator raw value let operatorRaw = stream.fragment(); // Check if it's prefix operator if (AttributeSelectorHandler.ATTR_EQUALITY_PREFIXES.has(operatorRaw)) { // Advance prefix operator token stream.advance(); // Expect equal sign token stream.expect(csstokenizer/* .TokenType.Delim */.ks.Delim, { value: constants/* .EQUALS */.UT }); // Append equal sign to prefix value operatorRaw += constants/* .EQUALS */.UT; } else if (operatorRaw !== constants/* .EQUALS */.UT) { // Throw error if it's not equal sign either throw new adblock_syntax_error/* .AdblockSyntaxError */.q((0,sprintf.sprintf)("Invalid attribute selector operator '%s'", operatorRaw), baseOffset + token.start, baseOffset + token.end); } // Save operator node start position const operatorStart = token.start; // Advance equal sign token stream.advance(); // Skip whitespaces after equal sign stream.skipWhitespace(); // Get attribute selector value token token = stream.getOrFail(); // It should be a string or identifier const isValueString = token.type === csstokenizer/* .TokenType.String */.ks.String; if (!isValueString && token.type !== csstokenizer/* .TokenType.Ident */.ks.Ident) { throw new adblock_syntax_error/* .AdblockSyntaxError */.q((0,sprintf.sprintf)( // eslint-disable-next-line max-len `Expected '${(0,csstokenizer/* .getFormattedTokenName */.bZ)(csstokenizer/* .TokenType.Ident */.ks.Ident)}' or '${(0,csstokenizer/* .getFormattedTokenName */.bZ)(csstokenizer/* .TokenType.String */.ks.String)}' as attribute selector value, but got '%s' with value '%s'`, (0,csstokenizer/* .getFormattedTokenName */.bZ)(token.type), stream.fragment()), baseOffset + token.start, baseOffset + token.end); } // Save attribute selector value node start position const valueStart = token.start + (isValueString ? 1 : 0); // Save attribute selector value node end position const valueEnd = token.end - (isValueString ? 1 : 0); // Extract attribute selector value raw value const valueRaw = stream.fragment(); // We should unescape respective quotes inside of the string value const valueUnquotedAndUnescaped = quotes/* .QuoteUtils.removeQuotesAndUnescape */.Qj.removeQuotesAndUnescape(valueRaw); // Construct attribute selector operator node const operatorNode = { type: 'Value', value: operatorRaw, }; // Construct attribute selector value node const valueNode = { type: 'Value', value: valueUnquotedAndUnescaped, }; // Set attribute selector operator and value nodes to result node result.operator = operatorNode; result.value = valueNode; // Include attribute selector operator and value nodes locations if needed if (options.isLocIncluded) { operatorNode.start = baseOffset + operatorStart; operatorNode.end = baseOffset + operatorStart + operatorRaw.length; valueNode.start = baseOffset + valueStart; valueNode.end = baseOffset + valueEnd; } // Advance attribute selector value token stream.advance(); // Skip whitespaces after attribute selector value stream.skipWhitespace(); // Get close square bracket or attribute selector value flag token token = stream.getOrFail(); // Check if there is an any flag part if (token.type !== csstokenizer/* .TokenType.CloseSquareBracket */.ks.CloseSquareBracket) { // Expect a identifier (attribute selector value flag) stream.expect(csstokenizer/* .TokenType.Ident */.ks.Ident); // Extract attribute selector value flag raw value const flagRaw = stream.fragment(); // Validate attribute selector value flag if (!AttributeSelectorHandler.isValidFlag(flagRaw)) { throw new adblock_syntax_error/* .AdblockSyntaxError */.q((0,sprintf.sprintf)("Unexpected token '%s' with value '%s'", (0,csstokenizer/* .getFormattedTokenName */.bZ)(token.type), flagRaw), baseOffset + token.start, baseOffset + token.end); } // Save flag node start position const flagStart = token.start; // Construct attribute selector flag node const flagNode = { type: 'Value', value: flagRaw, }; // Set attribute selector flag node to result node result.flag = flagNode; // Include attribute selector flag node locations if needed if (options.isLocIncluded) { flagNode.start = baseOffset + flagStart; flagNode.end = baseOffset + flagStart + flagRaw.length; } // Advance attribute selector value flag token stream.advance(); // Skip whitespaces after attribute selector value flag stream.skipWhitespace(); // Get close square bracket token token = stream.getOrFail(); } } // Expect close square bracket token stream.expect(csstokenizer/* .TokenType.CloseSquareBracket */.ks.CloseSquareBracket); // Include attribute selector node end location if needed if (options.isLocIncluded) { result.end = baseOffset + token.end; } // Append attribute selector node to the current complex selector node complexSelector.children.push(result); // Advance close square bracket token stream.advance(); } /** * Validates attribute selector flag. * * @param flag Attribute selector flag. * * @returns `true` if the flag is valid, otherwise `false`. */ static isValidFlag(flag) { return AttributeSelectorHandler.ALLOWED_ATTRIBUTE_FLAGS.has(flag); } } ;// CONCATENATED MODULE: ./node_modules/.pnpm/@adguard+agtree@4.2.1/node_modules/@adguard/agtree/dist/parser/cosmetic/selector/handlers/class-selector-handler.js /* * AGTree v4.2.1 (build date: Wed, 12 Aug 2026 01:31:02 GMT) * (c) 2026 Adguard Software Ltd. * Released under the MIT license * https://github.com/AdguardTeam/tsurlfilter/tree/master/packages/agtree#readme */ /** * Handles class selector parsing in selector list. */ class ClassSelectorHandler { /** * Handles class selector parsing by creating a class selector node * and appending it to the current complex selector node. * * @param context Selector list parser context. * * @throws If the class selector is syntactically incorrect. */ static handle(context) { const { options, baseOffset, stream, complexSelector, } = context; // Get class selector dot token const token = stream.getOrFail(); // Advance class selector dot token stream.advance(); // Expect next token to be an identifier (class selector value) stream.expect(csstokenizer/* .TokenType.Ident */.ks.Ident); // Extract class selector value (without dot) const value = stream.fragment(); // Construct class selector node const result = { type: 'ClassSelector', value, }; // Include class selector node locations if needed if (options.isLocIncluded) { result.start = baseOffset + token.start; result.end = baseOffset + token.end + value.length; } // Append class selector node to the current complex selector node complexSelector.children.push(result); // Advance class selector value token stream.advance(); } } ;// CONCATENATED MODULE: ./node_modules/.pnpm/@adguard+agtree@4.2.1/node_modules/@adguard/agtree/dist/parser/cosmetic/selector/handlers/compound-selector-handler.js /* * AGTree v4.2.1 (build date: Wed, 12 Aug 2026 01:31:02 GMT) * (c) 2026 Adguard Software Ltd. * Released under the MIT license * https://github.com/AdguardTeam/tsurlfilter/tree/master/packages/agtree#readme */ /** * Handles compound selector parsing in selector list. */ class CompoundSelectorHandler { /** * Set of allowed symbols between selectors (combinators + comma, except combinator). * * @see {@link SelectorCombinatorValue} */ static ALLOWED_SYMBOLS_BETWEEN_SELECTORS = new Set([ // div > span constants/* .GREATER_THAN */.vz, // div + div constants/* .PLUS */.uu, // div ~ div constants/* .TILDE */.wR, // div, span constants/* .COMMA */.KE, ]); /** * Finishes the current compound selector by: * 1. Validating current compound selector node, * 2. Constructing selector combinator node (if provided), * 3. Appending selector combinator node to the complex selector (if provided). * * @param context Selector list parser context. * @param combinator Optional combinator string. * * @throws If the current compound selector has no simple selectors. */ static handle(context, combinator) { const { raw, options, baseOffset, stream, token, complexSelector, } = context; // Get current compound selector end token const currentEndToken = stream.lookbehindForNonWs(); // Throw error if current compound selector has no simple selectors (empty) if ( // Combinator shouldn't be the first token in the complex selector !currentEndToken || complexSelector.children.length === 0 // And the last token in the complex selector shouldn't be a combinator || complexSelector.children[complexSelector.children.length - 1].type === 'SelectorCombinator') { throw new adblock_syntax_error/* .AdblockSyntaxError */.q((0,sprintf.sprintf)("Unexpected token '%s' with value '%s'", (0,csstokenizer/* .getFormattedTokenName */.bZ)(token.type), raw.slice(token.start, token.end)), baseOffset + token.start, baseOffset + token.end); } // Handle edge case for descendant combinator if (combinator === constants/* .SPACE */.t6) { // Skip whitespaces before checking next token stream.skipWhitespace(); // EOF - just skip, we shouldn't consider it as descendant combinator if (!stream.get()) { return; } // Combinator or Comma - just skip, we shouldn't consider it as descendant combinator if (CompoundSelectorHandler.ALLOWED_SYMBOLS_BETWEEN_SELECTORS.has(stream.fragment())) { return; } } else { // Advance selector combinator token stream.advance(); // Skip whitespaces after selector combinator token stream.skipWhitespace(); } // If no combinator is provided, just return, as we don't need to create and append selector combinator node if (!combinator) { return; } // Next compound selector token should be defined stream.getOrFail(); // Construct selector combinator node const result = { type: 'SelectorCombinator', value: combinator, }; // Include selector combinator node locations if needed if (options.isLocIncluded) { result.start = baseOffset + token.start; result.end = baseOffset + token.start + combinator.length; } // Append selector combinator node to the current complex selector node complexSelector.children.push(result); // Reset type selector set tracker for next compound selector context.isTypeSelectorSet = false; } } ;// CONCATENATED MODULE: ./node_modules/.pnpm/@adguard+agtree@4.2.1/node_modules/@adguard/agtree/dist/parser/cosmetic/selector/handlers/complex-selector-handler.js /* * AGTree v4.2.1 (build date: Wed, 12 Aug 2026 01:31:02 GMT) * (c) 2026 Adguard Software Ltd. * Released under the MIT license * https://github.com/AdguardTeam/tsurlfilter/tree/master/packages/agtree#readme */ /** * Handles complex selector parsing in selector list. */ class ComplexSelectorHandler { /** * Finishes the current complex selector by: * 1. Finishing current compound selector node via {@link CompoundSelectorHandler}, * 2. Validating current complex selector node, * 3. Appending current complex selector node to the selector list node, * If `isEof` is `false`: * 4. Constructing next complex selector node. * * @param context Selector list parser context. * @param isEof Indicates whether the end of the file has been reached. * * @throws If the current compound / complex selector has no simple selectors / compound selectors. */ static handle(context, isEof = true) { const { raw, options, baseOffset, stream, token, result, complexSelector, } = context; // Get current complex selector end token const currentEndToken = stream.lookbehindForNonWs(); // Finish current compound selector node CompoundSelectorHandler.handle(context); // Throw error if current complex selector node has no compound selector nodes (empty) if (!currentEndToken || complexSelector.children.length === 0) { throw new adblock_syntax_error/* .AdblockSyntaxError */.q((0,sprintf.sprintf)("Unexpected token '%s' with value '%s'", (0,csstokenizer/* .getFormattedTokenName */.bZ)(token.type), raw.slice(token.start, token.end)), baseOffset + token.start, baseOffset + token.end); } // Include current complex selector node end location if needed if (options.isLocIncluded) { complexSelector.end = baseOffset + currentEndToken.end; } // Append current complex selector node to selector list node result.children.push(complexSelector); // If EOF is reached, just return, as we don't need to construct a next complex selector node if (isEof) { return; } // Get next complex selector node start token const nextStartToken = stream.getOrFail(); // Construct next complex selector node const nextComplexSelector = { type: 'ComplexSelector', children: [], }; // Include next complex selector node start location if needed if (options.isLocIncluded) { nextComplexSelector.start = baseOffset + nextStartToken.start; } // Update context with new complex selector context.complexSelector = nextComplexSelector; // Reset type selector set tracker for new selector context.isTypeSelectorSet = false; } } ;// CONCATENATED MODULE: ./node_modules/.pnpm/@adguard+agtree@4.2.1/node_modules/@adguard/agtree/dist/parser/cosmetic/selector/handlers/id-selector-handler.js /* * AGTree v4.2.1 (build date: Wed, 12 Aug 2026 01:31:02 GMT) * (c) 2026 Adguard Software Ltd. * Released under the MIT license * https://github.com/AdguardTeam/tsurlfilter/tree/master/packages/agtree#readme */ /** * Handles ID selector parsing in selector list. */ class IdSelectorHandler { /** * Handles ID selector parsing by creating an ID selector node * and appending it to the current complex selector node. * * @param context Selector list parser context. * * @throws If the ID selector is syntactically incorrect. */ static handle(context) { const { raw, options, baseOffset, stream, complexSelector, } = context; // Get ID selector token const token = stream.getOrFail(); // Extract ID selector value (`start + 1` - without hashmark) const value = raw.slice(token.start + 1, token.end); // Construct ID selector node const result = { type: 'IdSelector', value, }; // Include ID selector node locations if needed if (options.isLocIncluded) { result.start = baseOffset + token.start; result.end = baseOffset + token.end; } // Append ID selector node to the current complex selector node complexSelector.children.push(result); // Advance ID selector token stream.advance(); } } ;// CONCATENATED MODULE: ./node_modules/.pnpm/@adguard+agtree@4.2.1/node_modules/@adguard/agtree/dist/parser/cosmetic/selector/handlers/pseudo-class-selector-handler.js /* * AGTree v4.2.1 (build date: Wed, 12 Aug 2026 01:31:02 GMT) * (c) 2026 Adguard Software Ltd. * Released under the MIT license * https://github.com/AdguardTeam/tsurlfilter/tree/master/packages/agtree#readme */ /** * Handles pseudo-class selector parsing in selector list. */ class PseudoClassSelectorHandler { /** * Handles pseudo-class selector parsing by creating a pseudo-class selector node * and appending it to the current complex selector node. * * @param context Selector list parser context. * * @throws If the pseudo-class selector is syntactically incorrect. */ static handle(context) { const { raw, options, baseOffset, stream, complexSelector, } = context; // Get colon token let token = stream.getOrFail(); // Save pseudo-class selector node start position const { start } = token; // Advance colon token stream.advance(); // Get pseudo-class selector name token token = stream.getOrFail(); // It should be a function or identifier const isFunction = token.type === csstokenizer/* .TokenType.Function */.ks.Function; if (!isFunction && token.type !== csstokenizer/* .TokenType.Ident */.ks.Ident) { throw new adblock_syntax_error/* .AdblockSyntaxError */.q((0,sprintf.sprintf)( // eslint-disable-next-line max-len `Expected '${(0,csstokenizer/* .getFormattedTokenName */.bZ)(csstokenizer/* .TokenType.Ident */.ks.Ident)}' or '${(0,csstokenizer/* .getFormattedTokenName */.bZ)(csstokenizer/* .TokenType.Function */.ks.Function)}' as pseudo-class selector name, but got '%s' with value '%s'`, (0,csstokenizer/* .getFormattedTokenName */.bZ)(token.type), stream.fragment()), baseOffset + token.start, baseOffset + token.end); } // Extract pseudo-class selector name raw value let nameRaw; if (!isFunction) { nameRaw = raw.slice(token.start, token.end); } else { nameRaw = raw.slice(token.start, token.end - 1); // Exclude '(' } // Construct pseudo-class selector node const result = { type: 'PseudoClassSelector', name: value_parser/* .ValueParser.parse */.J.parse(nameRaw, options, baseOffset + token.start), }; // Include pseudo-class selector node start location if needed if (options.isLocIncluded) { result.start = baseOffset + start; } // If it's a function, parse its argument if (isFunction) { // Save the function token's balance level for finding the matching close parenthesis const functionBalance = stream.getBalance(); // Advance pseudo-class selector name token stream.advance(); // Get pseudo-class selector argument token token = stream.getOrFail(); // Construct empty pseudo-class selector argument node by default result.argument = { type: 'Value', value: constants/* .EMPTY */.wg, }; // Include pseudo-class selector argument node location if needed if (options.isLocIncluded) { result.argument.start = baseOffset + token.start; result.argument.end = baseOffset + token.start; } // Skip whitespaces after opening parenthesis stream.skipWhitespace(); // Get pseudo-class selector argument or closing parenthesis token token = stream.getOrFail(); // Check if there is any argument part if (token.type !== csstokenizer/* .TokenType.CloseParenthesis */.ks.CloseParenthesis) { // Use the function token's balance level to find the matching closing parenthesis const balance = functionBalance; // Skip leading whitespace stream.skipWhitespace(); // Get argument token token = stream.getOrFail(); // Save pseudo-class selector argument start position const argumentStart = token.start; // Track last non-whitespace token to handle trailing whitespace let lastNonWsToken; // Skip to the closing parenthesis at the matching balance level while (stream.get()?.balance !== balance - 1) { const currentToken = stream.get(); if (currentToken && currentToken.type !== csstokenizer/* .TokenType.Whitespace */.ks.Whitespace) { lastNonWsToken = currentToken; } stream.advance(); } // Get closing parenthesis token token = stream.getOrFail(); // Save pseudo-class selector argument end position (after last non-whitespace token) const argumentEnd = lastNonWsToken ? lastNonWsToken.end : token.start; // Extract pseudo-class selector argument raw value (trimmed) // TODO: Consider parsing inner selectors (like :not(.class)) const argumentRaw = raw.slice(argumentStart, argumentEnd); // Specify pseudo-class selector argument node value result.argument.value = argumentRaw; // Include pseudo-class selector argument node location if needed if (options.isLocIncluded) { result.argument.start = baseOffset + argumentStart; result.argument.end = baseOffset + argumentStart + argumentRaw.length; } } // Expect close parenthesis token stream.expect(csstokenizer/* .TokenType.CloseParenthesis */.ks.CloseParenthesis); } // Include pseudo-class selector end location if needed if (options.isLocIncluded) { result.end = baseOffset + token.end; } // Append pseudo-class selector node to the current complex selector node complexSelector.children.push(result); // Advance pseudo-class selector name token (if ident) or closing parenthesis token (if function) stream.advance(); } } ;// CONCATENATED MODULE: ./node_modules/.pnpm/@adguard+agtree@4.2.1/node_modules/@adguard/agtree/dist/parser/cosmetic/selector/handlers/type-selector-handler.js /* * AGTree v4.2.1 (build date: Wed, 12 Aug 2026 01:31:02 GMT) * (c) 2026 Adguard Software Ltd. * Released under the MIT license * https://github.com/AdguardTeam/tsurlfilter/tree/master/packages/agtree#readme */ /** * Handles type selector parsing in selector list. */ class TypeSelectorHandler { /** * Handles type selector parsing by creating a type selector node * and appending it to the current complex selector node. * * @param context Selector list parser context. * * @throws If the type selector is syntactically incorrect. */ static handle(context) { const { options, baseOffset, stream, complexSelector, isTypeSelectorSet, } = context; // Get type selector token const token = stream.getOrFail(); // Throw error if type selector is already set if (isTypeSelectorSet) { throw new adblock_syntax_error/* .AdblockSyntaxError */.q('Type selector is already set for the compound selector', baseOffset + token.start, baseOffset + token.end); } // Throw error if type selector isn't first in the given compound selector if ( // It should be first on current complex selector complexSelector.children.length !== 0 // Or should be first on current compound selector (after combinator) && complexSelector.children[complexSelector.children.length - 1].type !== 'SelectorCombinator') { throw new adblock_syntax_error/* .AdblockSyntaxError */.q('Type selector must be first in the compound selector', baseOffset + token.start, baseOffset + token.end); } // Extract type selector value const value = stream.fragment(); // Construct type selector node const result = { type: 'TypeSelector', value, }; // Include type selector node locations if needed if (options.isLocIncluded) { result.start = baseOffset + token.start; result.end = baseOffset + token.start + value.length; } // Append type selector node to the current complex selector node complexSelector.children.push(result); // Advance type selector token stream.advance(); // Mark that type name is set context.isTypeSelectorSet = true; } } ;// CONCATENATED MODULE: ./node_modules/.pnpm/@adguard+agtree@4.2.1/node_modules/@adguard/agtree/dist/parser/cosmetic/selector/selector-list-parser.js /* * AGTree v4.2.1 (build date: Wed, 12 Aug 2026 01:31:02 GMT) * (c) 2026 Adguard Software Ltd. * Released under the MIT license * https://github.com/AdguardTeam/tsurlfilter/tree/master/packages/agtree#readme */ /** * Class responsible for parsing selector lists. * * Please note that the parser will parse any selector list if it is syntactically correct. * For example, it will parse this:. * ```adblock * div[attr1="value1"] > h1[attr2="value2"], span[attr3="value3"] * ``` * * But it didn't check if the given attribute or pseudo-class is valid or not.. * * @see {@link https://www.w3.org/TR/selectors-4/#selector-list}' */ class SelectorListParser extends base_parser/* .BaseParser */.V { /** * Common error messages used in the parser for unexpected tokens. */ static UNEXPECTED_TOKEN_WITH_VALUE_ERROR = "Unexpected token '%s' with value '%s'"; /** * Parses a selector list. * * @param raw Raw input to parse. * @param options Global parser options. * @param baseOffset Starting offset of the input. Node locations are calculated relative to this offset. * * @returns Node of the parsed selector list. * * @throws If the selector list is syntactically incorrect. * * @example * ``` * div[attr1="value1"] > h1[attr2="value2"], span[attr3="value3"] * ``` */ static parse(raw, options = parser_options/* .defaultParserOptions */.n, baseOffset = 0) { // Construct the stream const stream = new css_token_stream/* .CssTokenStream */.d(raw, baseOffset); // Skip whitespaces before first token stream.skipWhitespace(); // Construct selector list parser context const context = { raw, options, baseOffset, stream, // Get first token token: stream.getOrFail(), // Construct selector list node result: { type: 'SelectorList', children: [], }, // Construct first complex selector node complexSelector: { type: 'ComplexSelector', children: [], }, // Track if type selector set in the current compound selector isTypeSelectorSet: false, }; // Include locations for (if needed): // - start and end for the selector list node // - start for the first complex selector node if (options.isLocIncluded) { context.result.start = baseOffset; context.result.end = baseOffset + raw.length; context.complexSelector.start = baseOffset + context.token.start; } // Traverse the stream while (!stream.isEof()) { // Get next token context.token = stream.getOrFail(); switch (context.token.type) { // Tag selector case csstokenizer/* .TokenType.Ident */.ks.Ident: { TypeSelectorHandler.handle(context); break; } // ID selector case csstokenizer/* .TokenType.Hash */.ks.Hash: { IdSelectorHandler.handle(context); break; } // Attribute selector case csstokenizer/* .TokenType.OpenSquareBracket */.ks.OpenSquareBracket: { AttributeSelectorHandler.handle(context); break; } // Pseudo-class selector case csstokenizer/* .TokenType.Colon */.ks.Colon: { PseudoClassSelectorHandler.handle(context); break; } // Universal type selector ('*'), Class selector ('.'), Combinators ('>', '+', '~') case csstokenizer/* .TokenType.Delim */.ks.Delim: { // Get delimiter value const delimiter = stream.fragment(); switch (delimiter) { // Universal type selector ('*') case constants/* .ASTERISK */.Ln: { TypeSelectorHandler.handle(context); break; } // Class selector ('.) case constants/* .DOT */.y0: { ClassSelectorHandler.handle(context); break; } // Combinators ('>', '+', '~') case constants/* .GREATER_THAN */.vz: case constants/* .PLUS */.uu: case constants/* .TILDE */.wR: { CompoundSelectorHandler.handle(context, delimiter); break; } default: { throw new adblock_syntax_error/* .AdblockSyntaxError */.q((0,sprintf.sprintf)(SelectorListParser.UNEXPECTED_TOKEN_WITH_VALUE_ERROR, (0,csstokenizer/* .getFormattedTokenName */.bZ)(context.token.type), delimiter), baseOffset + context.token.start, baseOffset + context.token.end); } } break; } // End of current compound selector (whitespace combinator - descendant) case csstokenizer/* .TokenType.Whitespace */.ks.Whitespace: { CompoundSelectorHandler.handle(context, constants/* .SPACE */.t6); break; } // End of current complex selector case csstokenizer/* .TokenType.Comma */.ks.Comma: { ComplexSelectorHandler.handle(context, false); break; } default: { throw new adblock_syntax_error/* .AdblockSyntaxError */.q((0,sprintf.sprintf)(SelectorListParser.UNEXPECTED_TOKEN_WITH_VALUE_ERROR, (0,csstokenizer/* .getFormattedTokenName */.bZ)(context.token.type), stream.fragment()), baseOffset + context.token.start, baseOffset + context.token.end); } } } // Finish last complex selector ComplexSelectorHandler.handle(context); return context.result; } } ;// CONCATENATED MODULE: ./node_modules/.pnpm/@adguard+agtree@4.2.1/node_modules/@adguard/agtree/dist/parser/cosmetic/html-filtering-body/html-filtering-body-parser.js /* * AGTree v4.2.1 (build date: Wed, 12 Aug 2026 01:31:02 GMT) * (c) 2026 Adguard Software Ltd. * Released under the MIT license * https://github.com/AdguardTeam/tsurlfilter/tree/master/packages/agtree#readme */ /** * Class responsible for parsing HTML filtering rule body. * * Please note that the parser will parse any HTML filtering rule body if it is syntactically correct. * For example, it will parse this:. * ```adblock * span[special-attr="Example"] * div:special-pseudo(Example) * ``` * * But it didn't check if the pseudo selector `special-pseudo` or if * the attribute selector `special-attr` actually supported by any adblocker.. * * @see {@link https://www.w3.org/TR/selectors-4} * @see {@link https://adguard.com/kb/general/ad-filtering/create-own-filters/#html-filtering-rules} * @see {@link https://github.com/gorhill/uBlock/wiki/Static-filter-syntax#html-filters} */ class HtmlFilteringBodyParser extends base_parser/* .BaseParser */.V { /** * Parses a HTML filtering rule body. * * @param raw Raw input to parse. * @param options Global parser options. * @param baseOffset Starting offset of the input. Node locations are calculated relative to this offset. * * @returns Node of the parsed HTML filtering rule body. * * @throws If the body is syntactically incorrect. * * @example * ``` * span[tag-content="Example"] * div:has-text(Example) * ``` */ static parse(raw, options = parser_options/* .defaultParserOptions */.n, baseOffset = 0) { // If HTML filtering rules parsing is disabled, return raw value node let result; if (options.parseHtmlFilteringRuleBodies) { result = { type: 'HtmlFilteringRuleBody', selectorList: SelectorListParser.parse(raw, options, baseOffset), }; } else { result = { type: 'Value', value: raw, }; } // Include body locations if needed if (options.isLocIncluded) { result.start = baseOffset; result.end = baseOffset + raw.length; } return result; } } }, 91090(__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) { __webpack_require__.d(__webpack_exports__, { V: () => (UboHtmlFilteringBodyParser) }); /* import */ var sprintf_js__rspack_import_0 = __webpack_require__(37155); /* import */ var _adguard_css_tokenizer__rspack_import_1 = __webpack_require__(83747); /* import */ var _errors_adblock_syntax_error_js__rspack_import_7 = __webpack_require__(10631); /* import */ var _utils_constants_js__rspack_import_6 = __webpack_require__(53097); /* import */ var _base_parser_js__rspack_import_2 = __webpack_require__(79963); /* import */ var _css_css_token_stream_js__rspack_import_5 = __webpack_require__(44148); /* import */ var _misc_value_parser_js__rspack_import_8 = __webpack_require__(29090); /* import */ var _options_js__rspack_import_3 = __webpack_require__(64626); /* import */ var _html_filtering_body_parser_js__rspack_import_4 = __webpack_require__(15683); /* * AGTree v4.2.1 (build date: Wed, 12 Aug 2026 01:31:02 GMT) * (c) 2026 Adguard Software Ltd. * Released under the MIT license * https://github.com/AdguardTeam/tsurlfilter/tree/master/packages/agtree#readme */ /** * `UboHtmlFilteringBodyParser` is responsible for parsing the body of * an uBlock-style HTML filtering rule, and also uBlock-style response header removal rule. * * Please note that the parser will parse any HTML filtering rule if it is syntactically correct. * For example, it will parse this:. * ```adblock * example.com##^script:pseudo(content) * example.com##^responseheader(header-name) * ``` * * But it didn't check if the pseudo selector `pseudo` or if * the header name `header-name` actually supported by any adblocker.. * * @see {@link https://www.w3.org/TR/selectors-4} * @see {@link https://github.com/gorhill/uBlock/wiki/Static-filter-syntax#html-filters} * @see {@link https://github.com/gorhill/uBlock/wiki/Static-filter-syntax#response-header-filtering} */ class UboHtmlFilteringBodyParser extends _base_parser_js__rspack_import_2/* .BaseParser */.V { /** * Parses the body of an uBlock-style HTML filtering rule * and also uBlock-style response header removal rule. * * @param raw Raw input to parse. * @param options Global parser options. * @param baseOffset Starting offset of the input. Node locations are calculated relative to this offset. * * @returns Node of the parsed HTML filtering rule body. * * @throws If the body is syntactically incorrect. * * @example * ``` * div:has-text(Example) * responseheader(header-name) * ``` */ static parse(raw, options = _options_js__rspack_import_3/* .defaultParserOptions */.n, baseOffset = 0) { // First, check if it's a response header removal rule and return if so const responseHeaderBody = UboHtmlFilteringBodyParser.parseResponseHeaderRule(raw, options, baseOffset); if (responseHeaderBody !== null) { return responseHeaderBody; } return _html_filtering_body_parser_js__rspack_import_4/* .HtmlFilteringBodyParser.parse */.F.parse(raw, options, baseOffset); } /** * Parses uBlock-style response header removal rule body. * * @param raw Raw input to parse. * @param options Global parser options. * @param baseOffset Starting offset of the input. Node locations are calculated relative to this offset. * * @returns Node of the parsed response header removal rule body * or `null` if the body is not a response header removal rule. * * @throws If the body is syntactically incorrect. * * @example * ``` * responseheader(header-name) * ``` * * @note This method returns `HtmlFilteringRuleBody` because, * response header removal rule syntax is same as uBlock-style * HTML filtering rule syntax. */ static parseResponseHeaderRule(raw, options = _options_js__rspack_import_3/* .defaultParserOptions */.n, baseOffset = 0) { // If HTML filtering rules parsing is disabled, return null if (!options.parseHtmlFilteringRuleBodies) { return null; } // Construct the stream const stream = new _css_css_token_stream_js__rspack_import_5/* .CssTokenStream */.d(raw, baseOffset); // Skip whitespaces before function stream.skipWhitespace(); // Get token let token = stream.get(); // Token should be a function if (!token || token.type !== _adguard_css_tokenizer__rspack_import_1/* .TokenType.Function */.ks.Function) { return null; } // Save the function start position const { start } = token; // Extract function name raw value (without opening parenthesis) const functionNameRaw = raw.slice(token.start, token.end - 1); // Check if it's `responseheader` function if (functionNameRaw !== _utils_constants_js__rspack_import_6/* .UBO_RESPONSEHEADER_FN */.Bt) { return null; } // Advance function token stream.advance(); // Skip whitespaces after opening parenthesis stream.skipWhitespace(); // Get argument token token = stream.getOrFail(); // Save argument start position (starts after opening parenthesis and whitespaces) const argumentStart = token.start; // Skip until balanced (search for closing parenthesis) stream.skipUntilBalanced(); // Get closing parenthesis token token = stream.getOrFail(); // Save argument end position (ends before closing parenthesis) const argumentEnd = token.start; // Extract argument raw value const argumentRaw = raw.slice(argumentStart, argumentEnd).trimEnd(); // Throw if the argument is empty if (argumentRaw.length === 0) { throw new _errors_adblock_syntax_error_js__rspack_import_7/* .AdblockSyntaxError */.q(`Empty parameter for '${_utils_constants_js__rspack_import_6/* .UBO_RESPONSEHEADER_FN */.Bt}' function`, argumentStart + baseOffset, argumentEnd + baseOffset); } // Expect closing parenthesis stream.expect(_adguard_css_tokenizer__rspack_import_1/* .TokenType.CloseParenthesis */.ks.CloseParenthesis); // Advance closing parenthesis token stream.advance(); // Skip whitespaces after closing parenthesis stream.skipWhitespace(); // Expect the end of the rule - so nothing should be left in the stream if (!stream.isEof()) { token = stream.getOrFail(); throw new _errors_adblock_syntax_error_js__rspack_import_7/* .AdblockSyntaxError */.q((0,sprintf_js__rspack_import_0.sprintf)("Expected end of rule, but got '%s'", (0,_adguard_css_tokenizer__rspack_import_1/* .getFormattedTokenName */.bZ)(token.type)), token.start + baseOffset, token.end + baseOffset); } // Construct pseudo-class selector node const pseudoClassSelectorNode = { type: 'PseudoClassSelector', name: _misc_value_parser_js__rspack_import_8/* .ValueParser.parse */.J.parse(functionNameRaw, options, start + baseOffset), argument: _misc_value_parser_js__rspack_import_8/* .ValueParser.parse */.J.parse(argumentRaw, options, argumentStart + baseOffset), }; // Construct complex selector node const complexSelectorNode = { type: 'ComplexSelector', children: [pseudoClassSelectorNode], }; // Construct selector list node const selectorList = { type: 'SelectorList', children: [complexSelectorNode], }; // Construct body node const result = { type: 'HtmlFilteringRuleBody', selectorList, }; // Get last non-whitespace token const lastNonWsToken = stream.lookbehindForNonWs(); // It shouldn't be null here, but just to be safe if it is // it means that raw is empty or contains only whitespaces if (!lastNonWsToken) { return null; } // Include locations info if needed if (options.isLocIncluded) { result.start = baseOffset; result.end = raw.length + baseOffset; selectorList.start = start + baseOffset; selectorList.end = lastNonWsToken.end + baseOffset; complexSelectorNode.start = selectorList.start; complexSelectorNode.end = selectorList.end; pseudoClassSelectorNode.start = complexSelectorNode.start; pseudoClassSelectorNode.end = complexSelectorNode.end; } return result; } } }, 51175(__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) { __webpack_require__.d(__webpack_exports__, { g: () => (tokenizeFnBalanced), u: () => (tokenizeBalanced) }); /* import */ var sprintf_js__rspack_import_0 = __webpack_require__(37155); /* import */ var _adguard_css_tokenizer__rspack_import_1 = __webpack_require__(83747); /* import */ var _errors_adblock_syntax_error_js__rspack_import_2 = __webpack_require__(10631); /* import */ var _constants_js__rspack_import_3 = __webpack_require__(57545); /* * AGTree v4.2.1 (build date: Wed, 12 Aug 2026 01:31:02 GMT) * (c) 2026 Adguard Software Ltd. * Released under the MIT license * https://github.com/AdguardTeam/tsurlfilter/tree/master/packages/agtree#readme */ /** * @file Tokenizer helpers for balanced pairs. */ /** * Map of opening tokens to their corresponding closing tokens. */ const standardTokenPairs = new Map([ [_adguard_css_tokenizer__rspack_import_1/* .TokenType.Function */.ks.Function, _adguard_css_tokenizer__rspack_import_1/* .TokenType.CloseParenthesis */.ks.CloseParenthesis], [_adguard_css_tokenizer__rspack_import_1/* .TokenType.OpenParenthesis */.ks.OpenParenthesis, _adguard_css_tokenizer__rspack_import_1/* .TokenType.CloseParenthesis */.ks.CloseParenthesis], [_adguard_css_tokenizer__rspack_import_1/* .TokenType.OpenSquareBracket */.ks.OpenSquareBracket, _adguard_css_tokenizer__rspack_import_1/* .TokenType.CloseSquareBracket */.ks.CloseSquareBracket], [_adguard_css_tokenizer__rspack_import_1/* .TokenType.OpenCurlyBracket */.ks.OpenCurlyBracket, _adguard_css_tokenizer__rspack_import_1/* .TokenType.CloseCurlyBracket */.ks.CloseCurlyBracket], ]); /** * Map of opening tokens to their corresponding closing tokens just for function calls. This makes possible a more * lightweight and tolerant check for balanced pairs in some cases. */ const functionTokenPairs = new Map([ [_adguard_css_tokenizer__rspack_import_1/* .TokenType.Function */.ks.Function, _adguard_css_tokenizer__rspack_import_1/* .TokenType.CloseParenthesis */.ks.CloseParenthesis], [_adguard_css_tokenizer__rspack_import_1/* .TokenType.OpenParenthesis */.ks.OpenParenthesis, _adguard_css_tokenizer__rspack_import_1/* .TokenType.CloseParenthesis */.ks.CloseParenthesis], ]); /** * Helper function to tokenize and ensure balanced pairs. * * @param raw Raw CSS string to tokenize. * @param onToken Callback which will be invoked for each token, extended with a `balance` parameter. * @param onError Error callback which is called when a parsing error is found (optional). * @param functionHandlers Custom function handlers (optional). * @param tokenPairs Map of opening tokens to their corresponding closing tokens. * * @throws If the input is not balanced. * * @todo Consider adding a `tolerant` flag if error throwing seems too aggressive in the future. */ const tokenizeWithBalancedPairs = (raw, onToken, onError = () => { }, functionHandlers, tokenPairs = standardTokenPairs) => { const stack = []; const values = new Set(tokenPairs.values()); (0,_adguard_css_tokenizer__rspack_import_1/* .tokenizeExtended */.jz)(raw, (type, start, end, props, stop) => { if (tokenPairs.has(type)) { // If the token is an opening token, push its corresponding closing token to the stack. // It is safe to use non-null assertion here, because we have checked that the token exists in the map. // eslint-disable-next-line @typescript-eslint/no-non-null-assertion stack.push(tokenPairs.get(type)); } else if (values.has(type)) { // If the token is a closing token, check if it matches the last opening token, and if so, pop it. if (stack[stack.length - 1] === type) { stack.pop(); } else { throw new _errors_adblock_syntax_error_js__rspack_import_2/* .AdblockSyntaxError */.q((0,sprintf_js__rspack_import_0.sprintf)(_constants_js__rspack_import_3/* .ERROR_MESSAGES.EXPECTED_TOKEN_BUT_GOT */.U.EXPECTED_TOKEN_BUT_GOT, (0,_adguard_css_tokenizer__rspack_import_1/* .getFormattedTokenName */.bZ)(stack[stack.length - 1]), (0,_adguard_css_tokenizer__rspack_import_1/* .getFormattedTokenName */.bZ)(type)), start, raw.length); } } onToken(type, start, end, props, stack.length, stop); }, onError, functionHandlers); // If the stack is not empty, then there are some opening tokens that were not closed. if (stack.length > 0) { throw new _errors_adblock_syntax_error_js__rspack_import_2/* .AdblockSyntaxError */.q((0,sprintf_js__rspack_import_0.sprintf)(_constants_js__rspack_import_3/* .ERROR_MESSAGES.EXPECTED_TOKEN_BUT_GOT */.U.EXPECTED_TOKEN_BUT_GOT, (0,_adguard_css_tokenizer__rspack_import_1/* .getFormattedTokenName */.bZ)(stack[stack.length - 1]), _constants_js__rspack_import_3/* .END_OF_INPUT */.F), raw.length - 1, raw.length); } }; /** * Tokenize and ensure balanced pairs for standard CSS. * * @param raw Raw CSS string to tokenize. * @param onToken Callback which will be invoked for each token, extended with a `balance` parameter. * @param onError Error callback which is called when a parsing error is found (optional). * @param functionHandlers Custom function handlers (optional). * * @throws If the input is not balanced. */ const tokenizeBalanced = (raw, onToken, onError = () => { }, functionHandlers) => { tokenizeWithBalancedPairs(raw, onToken, onError, functionHandlers); }; /** * Tokenize and ensure balanced pairs for function calls. * * @param raw Raw CSS string to tokenize. * @param onToken Callback which will be invoked for each token, extended with a `balance` parameter. * @param onError Error callback which is called when a parsing error is found (optional). * @param functionHandlers Custom function handlers (optional). * * @throws If the input is not balanced. */ const tokenizeFnBalanced = (raw, onToken, onError = () => { }, functionHandlers) => { tokenizeWithBalancedPairs(raw, onToken, onError, functionHandlers, functionTokenPairs); }; }, 57545(__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) { __webpack_require__.d(__webpack_exports__, { F: () => (END_OF_INPUT), U: () => (ERROR_MESSAGES) }); /* * AGTree v4.2.1 (build date: Wed, 12 Aug 2026 01:31:02 GMT) * (c) 2026 Adguard Software Ltd. * Released under the MIT license * https://github.com/AdguardTeam/tsurlfilter/tree/master/packages/agtree#readme */ /** * @file Error messages for CSS token stream and balancer. */ const END_OF_INPUT = 'end of input'; const ERROR_MESSAGES = { EXPECTED_ANY_TOKEN_BUT_GOT: "Expected a token, but got '%s'", EXPECTED_TOKEN_BUT_GOT: "Expected '%s', but got '%s'", EXPECTED_TOKEN_WITH_BALANCE_BUT_GOT: "Expected '%s' with balance '%d', but got '%d'", EXPECTED_TOKEN_WITH_VALUE_BUT_GOT: "Expected '%s' with value '%s', but got '%s'", }; }, 44148(__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) { __webpack_require__.d(__webpack_exports__, { d: () => (CssTokenStream) }); /* import */ var sprintf_js__rspack_import_0 = __webpack_require__(37155); /* import */ var _adguard_css_tokenizer__rspack_import_1 = __webpack_require__(83747); /* import */ var _converter_data_css_js__rspack_import_6 = __webpack_require__(63829); /* import */ var _errors_adblock_syntax_error_js__rspack_import_4 = __webpack_require__(10631); /* import */ var _utils_constants_js__rspack_import_2 = __webpack_require__(53097); /* import */ var _balancing_js__rspack_import_3 = __webpack_require__(51175); /* import */ var _constants_js__rspack_import_5 = __webpack_require__(57545); /* * AGTree v4.2.1 (build date: Wed, 12 Aug 2026 01:31:02 GMT) * (c) 2026 Adguard Software Ltd. * Released under the MIT license * https://github.com/AdguardTeam/tsurlfilter/tree/master/packages/agtree#readme */ /** * @file CSS token stream. */ /** * Represents a stream of CSS tokens. */ class CssTokenStream { /** * The tokens in the stream. */ tokens = []; /** * The source string. */ source = _utils_constants_js__rspack_import_2/* .EMPTY */.wg; /** * The current index in the stream. */ index = 0; /** * The base offset of the source string. */ baseOffset; /** * Initializes a new instance of the TokenStream class. * * @param source The source string to tokenize. * @param baseOffset The base offset of the source string. */ constructor(source, baseOffset = 0) { this.source = source; // Tokenize the source string with the CSS tokenizer and add balance level to each token. // 'onToken' callback is invoked when a token is found in the source string. // Passed parameters: // - type: type of the token // - start: start index of the token // - end: end index of the token // - props: additional properties of the token, if any (we don't use it here, this is why we use underscore) // - balance: balance level of the token try { (0,_balancing_js__rspack_import_3/* .tokenizeBalanced */.u)(source, (type, start, end, _, balance) => { this.tokens.push({ type, start, end, balance, }); }); } catch (error) { // If the error is an AdblockSyntaxError, adjust the error positions to the base offset if (error instanceof _errors_adblock_syntax_error_js__rspack_import_4/* .AdblockSyntaxError */.q) { error.start += baseOffset; error.end += baseOffset; throw error; } } this.index = 0; this.baseOffset = baseOffset; } /** * Gets the number of tokens in the stream. * * @returns The number of tokens in the stream. */ get length() { return this.tokens.length; } /** * Checks if the end of the token stream is reached. * * @returns True if the end of the stream is reached, otherwise false. */ isEof() { return this.index >= this.tokens.length; } /** * Gets the token at the specified index. * * @param index The index of the token to retrieve. * * @returns The token at the specified index or undefined if the index is out of bounds. */ get(index = this.index) { return this.tokens[index]; } /** * Gets the token at the specified index or throws if no token is found at the specified index. * * @param index The index of the token to retrieve. * * @returns The token at the specified index or undefined if the index is out of bounds. * * @throws If no token is found at the specified index. */ getOrFail(index = this.index) { const token = this.get(index); if (!token) { throw new _errors_adblock_syntax_error_js__rspack_import_4/* .AdblockSyntaxError */.q((0,sprintf_js__rspack_import_0.sprintf)(_constants_js__rspack_import_5/* .ERROR_MESSAGES.EXPECTED_ANY_TOKEN_BUT_GOT */.U.EXPECTED_ANY_TOKEN_BUT_GOT, _constants_js__rspack_import_5/* .END_OF_INPUT */.F), this.baseOffset + this.source.length - 1, this.baseOffset + this.source.length); } return token; } /** * Gets the source fragment of the token at the specified index. * * @param index The index of the token to retrieve the fragment for. * * @returns The source fragment of the token or an empty string if the index is out of bounds. */ fragment(index = this.index) { const token = this.get(index); if (token) { return this.source.slice(token.start, token.end); } return _utils_constants_js__rspack_import_2/* .EMPTY */.wg; } /** * Moves the index to the next token and returns it. * * @returns The next token or undefined if the end of the stream is reached. */ advance() { if (this.isEof()) { return undefined; } this.index += 1; return this.tokens[this.index]; } /** * Looks ahead in the stream without changing the index. * * @param index The relative index to look ahead to, starting from the current index. * * @returns The next token or undefined if the end of the stream is reached. */ lookahead(index = 1) { return this.tokens[this.index + Math.max(1, index)]; } /** * Looks behind in the stream without changing the index. * * @param index The relative index to look behind to, starting from the current index. * * @returns The previous token or undefined if the current token is the first in the stream. */ lookbehind(index = 1) { if (this.index === 0) { return undefined; } return this.tokens[this.index - Math.max(1, index)]; } /** * Looks behind in the stream for the previous non-whitespace token without changing the index. * * @returns The previous non-whitespace token or undefined if it could not be found. */ lookbehindForNonWs() { for (let i = this.index - 1; i >= 0; i -= 1) { if (this.tokens[i].type !== _adguard_css_tokenizer__rspack_import_1/* .TokenType.Whitespace */.ks.Whitespace) { return this.tokens[i]; } } return undefined; } /** * Skips whitespace tokens in the stream. */ skipWhitespace() { while (this.get()?.type === _adguard_css_tokenizer__rspack_import_1/* .TokenType.Whitespace */.ks.Whitespace) { this.index += 1; } } /** * Skips tokens until the current balance level is reached. * * @returns The number of tokens skipped. */ skipUntilBalanced() { if (this.isEof()) { return 0; } // It is safe to use ! here, because we check for EOF above // eslint-disable-next-line @typescript-eslint/no-non-null-assertion const currentBalance = this.get().balance; // If the current balance is 0, do nothing if (currentBalance === 0) { return 0; } // Otherwise, skip tokens until the balance is the current balance - 1 let skipped = 0; while (!this.isEof() && this.get()?.balance !== currentBalance - 1) { this.index += 1; skipped += 1; } return skipped; } /** * Skips tokens until a token with the specified type or the end of the stream is reached. * * @param type The type of token to skip until. * @param balance The balance level of the token to skip until. * * @returns The number of tokens skipped. */ skipUntil(type, balance) { let skipped = 0; while (!this.isEof() && (this.get()?.type !== type || (balance !== undefined && this.get()?.balance !== balance))) { this.index += 1; skipped += 1; } return skipped; } /** * Skips tokens until a token with the specified type or the end of the stream is reached. This is an extended * version of skipUntil that also returns the number of tokens skipped without calculating leading and trailing * whitespace tokens. * * @param type The type of token to skip until. * @param balance The balance level of the token to skip until. * * @returns An array containing the number of tokens skipped and the number of tokens skipped without leading and * trailing whitespace tokens. */ skipUntilExt(type, balance) { let i = this.index; let firstNonWsToken = -1; // -1 means no non-whitespace token found yet let lastNonWsToken = -1; // -1 means no non-whitespace token found yet while (i < this.tokens.length) { const currentToken = this.tokens[i]; if (currentToken.type === _adguard_css_tokenizer__rspack_import_1/* .TokenType.Whitespace */.ks.Whitespace) { i += 1; continue; } else if (currentToken.type === type && currentToken.balance === balance) { break; } if (firstNonWsToken === -1) { firstNonWsToken = i; } lastNonWsToken = i; i += 1; } const skipped = i - this.index; this.index = i; return { skipped, // if firstNonWsToken is -1, then lastNonWsToken is also -1 skippedTrimmed: firstNonWsToken === -1 ? 0 : lastNonWsToken - firstNonWsToken + 1, }; } /** * Expects that the end of the stream is not reached. */ expectNotEof() { if (this.isEof()) { throw new _errors_adblock_syntax_error_js__rspack_import_4/* .AdblockSyntaxError */.q('Unexpected end of input', this.baseOffset + this.source.length - 1, this.baseOffset + this.source.length); } } /** * Expects the current token to have a specific type and optional value and balance level. * * @param type The expected token type. * @param data Optional expectation data. * * @throws If the end of the stream is reached or if the token type or expectation data does not match. */ expect(type, data) { const token = this.get(); if (!token) { throw new _errors_adblock_syntax_error_js__rspack_import_4/* .AdblockSyntaxError */.q((0,sprintf_js__rspack_import_0.sprintf)(_constants_js__rspack_import_5/* .ERROR_MESSAGES.EXPECTED_TOKEN_BUT_GOT */.U.EXPECTED_TOKEN_BUT_GOT, (0,_adguard_css_tokenizer__rspack_import_1/* .getFormattedTokenName */.bZ)(type), _constants_js__rspack_import_5/* .END_OF_INPUT */.F), this.baseOffset + this.source.length - 1, this.baseOffset + this.source.length); } if (token.type !== type) { throw new _errors_adblock_syntax_error_js__rspack_import_4/* .AdblockSyntaxError */.q((0,sprintf_js__rspack_import_0.sprintf)(_constants_js__rspack_import_5/* .ERROR_MESSAGES.EXPECTED_TOKEN_BUT_GOT */.U.EXPECTED_TOKEN_BUT_GOT, (0,_adguard_css_tokenizer__rspack_import_1/* .getFormattedTokenName */.bZ)(type), (0,_adguard_css_tokenizer__rspack_import_1/* .getFormattedTokenName */.bZ)(token.type)), this.baseOffset + token.start, this.baseOffset + token.end); } if (data?.balance !== undefined && token.balance !== data.balance) { throw new _errors_adblock_syntax_error_js__rspack_import_4/* .AdblockSyntaxError */.q((0,sprintf_js__rspack_import_0.sprintf)(_constants_js__rspack_import_5/* .ERROR_MESSAGES.EXPECTED_TOKEN_WITH_BALANCE_BUT_GOT */.U.EXPECTED_TOKEN_WITH_BALANCE_BUT_GOT, (0,_adguard_css_tokenizer__rspack_import_1/* .getFormattedTokenName */.bZ)(type), data.balance, token.balance), this.baseOffset + token.start, this.baseOffset + token.end); } if (data?.value && this.fragment() !== data.value) { throw new _errors_adblock_syntax_error_js__rspack_import_4/* .AdblockSyntaxError */.q((0,sprintf_js__rspack_import_0.sprintf)(_constants_js__rspack_import_5/* .ERROR_MESSAGES.EXPECTED_TOKEN_WITH_VALUE_BUT_GOT */.U.EXPECTED_TOKEN_WITH_VALUE_BUT_GOT, (0,_adguard_css_tokenizer__rspack_import_1/* .getFormattedTokenName */.bZ)(type), data.value, this.fragment()), this.baseOffset + token.start, this.baseOffset + token.end); } } /** * Gets the balance level of the token at the specified index. * * @param index The index of the token to retrieve the balance level for. * * @returns The balance level of the token or 0 if the index is out of bounds. */ getBalance(index = this.index) { return this.tokens[index]?.balance || 0; } /** * Checks whether the token stream contains any Extended CSS elements, such as `:contains()`, etc. * * @returns `true` if the stream contains any Extended CSS elements, otherwise `false`. */ hasAnySelectorExtendedCssNode() { return this.hasAnySelectorExtendedCssNodeInternal(_converter_data_css_js__rspack_import_6/* .EXT_CSS_PSEUDO_CLASSES */.Ss); } /** * Strictly checks whether the token stream contains any Extended CSS elements, such as `:contains()`. * * Some Extended CSS elements are natively supported by browsers, like `:has()`. * This method is used to check for Extended CSS elements that are not natively supported by browsers, * this is why it called "strict", because it strictly checks for Extended CSS elements. * * @returns `true` if the stream contains any Extended CSS elements, otherwise `false`. */ hasAnySelectorExtendedCssNodeStrict() { return this.hasAnySelectorExtendedCssNodeInternal(_converter_data_css_js__rspack_import_6/* .EXT_CSS_PSEUDO_CLASSES_STRICT */.ig); } /** * _Lightweight_ static check for native CSS pseudo-classes — `:has()`, `:is()`, `:not()`. * * This method uses `tokenizeExtended` directly with early stopping, * avoiding the overhead of: * - full tokenization with balance tracking; * - storing all tokens in memory; * - processing remaining tokens after a match is found. * * Use this method when you only need to detect native pseudo-classes * and don't need the full `CssTokenStream` functionality. * * @param selector CSS selector string to check. * * @returns True if the selector contains `:has()`, `:is()`, or `:not()`, * otherwise false. */ static hasNativeCssPseudoClass(selector) { let found = false; try { (0,_adguard_css_tokenizer__rspack_import_1/* .tokenizeExtended */.jz)(selector, (type, start, end, _props, stop) => { if (type === _adguard_css_tokenizer__rspack_import_1/* .TokenType.Function */.ks.Function) { // Omit trailing '(' from function name const name = selector.slice(start, end - 1); if (_converter_data_css_js__rspack_import_6/* .NATIVE_CSS_PSEUDO_CLASSES.has */.Y_.has(name)) { found = true; stop(); } } }); } catch { // Invalid CSS, treat as not containing native pseudo-classes return false; } return found; } /** * Checks whether the token stream contains any Extended CSS elements, such as `:has()`, `:contains()`, etc. * * @param pseudos Set of pseudo-classes to check for. * * @returns `true` if the stream contains any Extended CSS elements, otherwise `false`. */ hasAnySelectorExtendedCssNodeInternal(pseudos) { for (let i = 0; i < this.tokens.length; i += 1) { const token = this.tokens[i]; if (token.type === _adguard_css_tokenizer__rspack_import_1/* .TokenType.Function */.ks.Function) { const name = this.source.slice(token.start, token.end - 1); // omit the last parenthesis if (pseudos.has(name)) { return true; } } else if (token.type === _adguard_css_tokenizer__rspack_import_1/* .TokenType.OpenSquareBracket */.ks.OpenSquareBracket) { let j = i + 1; // skip whitespace while (j < this.tokens.length && this.tokens[j].type === _adguard_css_tokenizer__rspack_import_1/* .TokenType.Whitespace */.ks.Whitespace) { j += 1; } if (j < this.tokens.length && this.tokens[j].type === _adguard_css_tokenizer__rspack_import_1/* .TokenType.Ident */.ks.Ident) { const attr = this.source.slice(this.tokens[j].start, this.tokens[j].end); // [-ext-=...] or [-abp-=...] if (attr.startsWith(_converter_data_css_js__rspack_import_6/* .LEGACY_EXT_CSS_ATTRIBUTE_PREFIX */.at) || attr.startsWith(_converter_data_css_js__rspack_import_6/* .ABP_EXT_CSS_PREFIX */.PY)) { return true; } } // do not check these tokens again i = j; } } return false; } } }, 70254(__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) { // EXPORTS __webpack_require__.d(__webpack_exports__, { y: () => (/* binding */ DomainListParser) }); // EXTERNAL MODULE: ./node_modules/.pnpm/@adguard+agtree@4.2.1/node_modules/@adguard/agtree/dist/nodes/index.js var nodes = __webpack_require__(79864); // EXTERNAL MODULE: ./node_modules/.pnpm/@adguard+agtree@4.2.1/node_modules/@adguard/agtree/dist/utils/constants.js var constants = __webpack_require__(53097); // EXTERNAL MODULE: ./node_modules/.pnpm/@adguard+agtree@4.2.1/node_modules/@adguard/agtree/dist/parser/base-parser.js var base_parser = __webpack_require__(79963); // EXTERNAL MODULE: ./node_modules/.pnpm/@adguard+agtree@4.2.1/node_modules/@adguard/agtree/dist/parser/options.js var parser_options = __webpack_require__(64626); // EXTERNAL MODULE: ./node_modules/.pnpm/@adguard+agtree@4.2.1/node_modules/@adguard/agtree/dist/errors/adblock-syntax-error.js var adblock_syntax_error = __webpack_require__(10631); // EXTERNAL MODULE: ./node_modules/.pnpm/@adguard+agtree@4.2.1/node_modules/@adguard/agtree/dist/utils/string.js var string = __webpack_require__(16875); ;// CONCATENATED MODULE: ./node_modules/.pnpm/@adguard+agtree@4.2.1/node_modules/@adguard/agtree/dist/parser/misc/list-items-parser.js /* * AGTree v4.2.1 (build date: Wed, 12 Aug 2026 01:31:02 GMT) * (c) 2026 Adguard Software Ltd. * Released under the MIT license * https://github.com/AdguardTeam/tsurlfilter/tree/master/packages/agtree#readme */ /** * Prefixes for error messages which are used for parsing of value lists. */ const LIST_PARSE_ERROR_PREFIX = { EMPTY_ITEM: 'Empty value specified in the list', NO_MULTIPLE_NEGATION: 'Exception marker cannot be followed by another exception marker', NO_SEPARATOR_AFTER_NEGATION: 'Exception marker cannot be followed by a separator', NO_SEPARATOR_AT_THE_BEGINNING: 'Value list cannot start with a separator', NO_SEPARATOR_AT_THE_END: 'Value list cannot end with a separator', NO_WHITESPACE_AFTER_NEGATION: 'Exception marker cannot be followed by whitespace', }; /** * Parser for list items in modifiers. */ class ListItemsParser { /** * Parses a `raw` modifier value which may be represented as a list of items separated by `separator`. * Needed for $app, $denyallow, $domain, $method. * * @template T Type of the list items. * * @param raw Raw input to parse. * @param options Global parser options. * @param baseOffset Starting offset of the input. Node locations are calculated relative to this offset. * @param separator Separator character (default: comma). * @param type Type of the list items (default: {@link ListItemNodeType.Domain}). * * @returns List of parsed items. * * @throws An {@link AdblockSyntaxError} if the list is syntactically invalid. * * @example * - parses an app list — `com.example.app|Example.exe` * - parses a domain list — `example.com,example.org,~example.org` or `example.com|~example.org` * - parses a method list — `~post|~put` */ static parse(raw, options = parser_options/* .defaultParserOptions */.n, baseOffset = 0, separator = constants/* .COMMA */.KE, type = nodes/* .ListItemNodeType.Unknown */.WR.Unknown) { // Function body here const rawListItems = []; let offset = 0; // Skip whitespace before the list offset = string/* .StringUtils.skipWS */.$x.skipWS(raw, offset); // If the first character is a separator, then the list is invalid // and no need to continue parsing if (raw[offset] === separator) { throw new adblock_syntax_error/* .AdblockSyntaxError */.q(LIST_PARSE_ERROR_PREFIX.NO_SEPARATOR_AT_THE_BEGINNING, baseOffset + offset, baseOffset + raw.length); } // If the last character is a separator, then the list item is invalid // and no need to continue parsing const realEndIndex = string/* .StringUtils.skipWSBack */.$x.skipWSBack(raw); if (raw[realEndIndex] === separator) { throw new adblock_syntax_error/* .AdblockSyntaxError */.q(LIST_PARSE_ERROR_PREFIX.NO_SEPARATOR_AT_THE_END, baseOffset + realEndIndex, baseOffset + realEndIndex + 1); } // Split list items by unescaped separators while (offset < raw.length) { // Skip whitespace before the list item offset = string/* .StringUtils.skipWS */.$x.skipWS(raw, offset); const exception = raw[offset] === constants/* .NEGATION_MARKER */.bP; const itemStart = exception ? offset + 1 : offset; let separatorStartIndex = -1; // item possibly a regex if (raw[itemStart] === constants/* .REGEX_MARKER */.Vb) { // try to find the next slash let i = itemStart + 1; let insideCharacterClass = false; let escaped = false; while (i < raw.length) { if (escaped) { escaped = false; } else if (raw[i] === constants/* .ESCAPE_CHARACTER */.Kx) { escaped = true; } else if (raw[i] === constants/* .OPEN_SQUARE_BRACKET */.cU) { insideCharacterClass = true; } else if (raw[i] === constants/* .CLOSE_SQUARE_BRACKET */.A1) { insideCharacterClass = false; } else if (!insideCharacterClass && raw[i] === constants/* .REGEX_MARKER */.Vb) { // check if slash followed by optional space followed by the separator const j = string/* .StringUtils.skipWS */.$x.skipWS(raw, i + 1); if (raw[j] === separator) { separatorStartIndex = j; break; } } i += 1; } if (separatorStartIndex === -1) { separatorStartIndex = raw.length; } } else { separatorStartIndex = string/* .StringUtils.findNextUnescapedCharacter */.$x.findNextUnescapedCharacter(raw, separator, itemStart); } const itemEnd = separatorStartIndex === -1 ? string/* .StringUtils.skipWSBack */.$x.skipWSBack(raw) + 1 : string/* .StringUtils.skipWSBack */.$x.skipWSBack(raw, separatorStartIndex - 1) + 1; // Skip the exception marker if (exception) { const item = raw[itemStart]; // Exception marker cannot be followed by another exception marker if (item === constants/* .NEGATION_MARKER */.bP) { throw new adblock_syntax_error/* .AdblockSyntaxError */.q(LIST_PARSE_ERROR_PREFIX.NO_MULTIPLE_NEGATION, baseOffset + itemStart, baseOffset + itemStart + 1); } // Exception marker cannot be followed by a separator if (item === separator) { throw new adblock_syntax_error/* .AdblockSyntaxError */.q(LIST_PARSE_ERROR_PREFIX.NO_SEPARATOR_AFTER_NEGATION, baseOffset + itemStart, baseOffset + itemStart + 1); } // Exception marker cannot be followed by whitespace if (string/* .StringUtils.isWhitespace */.$x.isWhitespace(item)) { throw new adblock_syntax_error/* .AdblockSyntaxError */.q(LIST_PARSE_ERROR_PREFIX.NO_WHITESPACE_AFTER_NEGATION, baseOffset + itemStart, baseOffset + itemStart + 1); } } // List item can't be empty // Note we use '<=' instead of '===' because we have bidirectional trim // This is needed to handle cases like 'example.com, ,example.org' if (itemEnd <= itemStart) { throw new adblock_syntax_error/* .AdblockSyntaxError */.q(LIST_PARSE_ERROR_PREFIX.EMPTY_ITEM, baseOffset + itemStart, baseOffset + raw.length); } const listItem = { type, value: raw.slice(itemStart, itemEnd), exception, }; if (options.isLocIncluded) { listItem.start = baseOffset + itemStart; listItem.end = baseOffset + itemEnd; } // Collect list item rawListItems.push(listItem); // Increment the offset to the next list item (or the end of the string) offset = separatorStartIndex === -1 ? raw.length : separatorStartIndex + 1; } return rawListItems; } } ;// CONCATENATED MODULE: ./node_modules/.pnpm/@adguard+agtree@4.2.1/node_modules/@adguard/agtree/dist/parser/misc/domain-list-parser.js /* * AGTree v4.2.1 (build date: Wed, 12 Aug 2026 01:31:02 GMT) * (c) 2026 Adguard Software Ltd. * Released under the MIT license * https://github.com/AdguardTeam/tsurlfilter/tree/master/packages/agtree#readme */ /** * `DomainListParser` is responsible for parsing a domain list. * * @see {@link https://help.eyeo.com/adblockplus/how-to-write-filters#elemhide_domains} * * @example * - If the rule is `example.com,~example.net##.ads`, the domain list is `example.com,~example.net`. * - If the rule is `ads.js^$script,domains=example.com|~example.org`, the domain list is `example.com|~example.org`. * This parser is responsible for parsing these domain lists. */ class DomainListParser extends base_parser/* .BaseParser */.V { /** * Parses a domain list, eg. `example.com,example.org,~example.org`. * * @param raw Raw input to parse. * @param options Global parser options. * @param baseOffset Starting offset of the input. Node locations are calculated relative to this offset. * @param separator Separator character (default: comma). * * @returns Domain list AST. * * @throws An {@link AdblockSyntaxError} if the domain list is syntactically invalid. * @throws An {@link Error} if the options are invalid. */ static parse(raw, options = parser_options/* .defaultParserOptions */.n, baseOffset = 0, separator = constants/* .COMMA */.KE) { if (separator !== constants/* .COMMA */.KE && separator !== constants/* .PIPE */.L5) { throw new Error(`Invalid separator: ${separator}`); } const result = { type: nodes/* .ListNodeType.DomainList */.h6.DomainList, separator, children: ListItemsParser.parse(raw, options, baseOffset, separator, nodes/* .ListItemNodeType.Domain */.WR.Domain), }; if (options.isLocIncluded) { result.start = baseOffset; result.end = baseOffset + raw.length; } return result; } } }, 48609(__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) { __webpack_require__.d(__webpack_exports__, { Z: () => (NodeType), f: () => (LogicalExpressionParser) }); /* import */ var _errors_adblock_syntax_error_js__rspack_import_4 = __webpack_require__(10631); /* import */ var _nodes_index_js__rspack_import_0 = __webpack_require__(79864); /* import */ var _utils_constants_js__rspack_import_3 = __webpack_require__(53097); /* import */ var _utils_string_js__rspack_import_2 = __webpack_require__(16875); /* import */ var _base_parser_js__rspack_import_1 = __webpack_require__(79963); /* import */ var _options_js__rspack_import_5 = __webpack_require__(64626); /* * AGTree v4.2.1 (build date: Wed, 12 Aug 2026 01:31:02 GMT) * (c) 2026 Adguard Software Ltd. * Released under the MIT license * https://github.com/AdguardTeam/tsurlfilter/tree/master/packages/agtree#readme */ /** * Possible token types in the logical expression. */ const TokenType = { Variable: 0, Operator: 1, Parenthesis: 2, }; /** * Possible node types in the logical expression. */ const NodeType = { Variable: 'Variable', Operator: 'Operator', Parenthesis: 'Parenthesis', }; /** * Precedence of the operators, larger number means higher precedence. */ const OPERATOR_PRECEDENCE = { [_nodes_index_js__rspack_import_0/* .OperatorValue.Not */.oC.Not]: 3, [_nodes_index_js__rspack_import_0/* .OperatorValue.And */.oC.And]: 2, [_nodes_index_js__rspack_import_0/* .OperatorValue.Or */.oC.Or]: 1, }; /** * `LogicalExpressionParser` is responsible for parsing logical expressions. * * @example * From the following rule: * ```adblock * !#if (adguard_ext_android_cb || adguard_ext_safari) * ``` * this parser will parse the expression `(adguard_ext_android_cb || adguard_ext_safari)`. */ // TODO: Refactor this class class LogicalExpressionParser extends _base_parser_js__rspack_import_1/* .BaseParser */.V { /** * Split the expression into tokens. * * @param raw Source code of the expression. * @param baseOffset Starting offset of the input. Node locations are calculated relative to this offset. * * @returns Token list. * * @throws {AdblockSyntaxError} If the expression is invalid. */ static tokenize(raw, baseOffset = 0) { const tokens = []; let offset = 0; while (offset < raw.length) { const char = raw[offset]; if (_utils_string_js__rspack_import_2/* .StringUtils.isWhitespace */.$x.isWhitespace(char)) { // Ignore whitespace offset += 1; } else if (_utils_string_js__rspack_import_2/* .StringUtils.isLetter */.$x.isLetter(char)) { // Save the start offset of the variable name const nameStart = offset; // Variable name shouldn't start with a number or underscore, // but can contain them while (offset + 1 < raw.length && (_utils_string_js__rspack_import_2/* .StringUtils.isAlphaNumeric */.$x.isAlphaNumeric(raw[offset + 1]) || raw[offset + 1] === _utils_constants_js__rspack_import_3/* .UNDERSCORE */.fB)) { offset += 1; } tokens.push({ type: TokenType.Variable, start: nameStart, end: offset + 1, }); offset += 1; } else if (char === _utils_constants_js__rspack_import_3/* .OPEN_PARENTHESIS */.Cx || char === _utils_constants_js__rspack_import_3/* .CLOSE_PARENTHESIS */.s1) { // Parenthesis tokens.push({ type: TokenType.Parenthesis, start: offset, end: offset + 1, }); offset += 1; } else if (char === _utils_constants_js__rspack_import_3/* .AMPERSAND */.e0 || char === _utils_constants_js__rspack_import_3/* .PIPE */.L5) { // Parse operator if (offset + 1 < raw.length && raw[offset + 1] === char) { tokens.push({ type: TokenType.Operator, start: offset, end: offset + 2, }); offset += 2; } else { throw new _errors_adblock_syntax_error_js__rspack_import_4/* .AdblockSyntaxError */.q(`Unexpected character "${char}"`, baseOffset + offset, baseOffset + offset + 1); } } else if (char === _utils_constants_js__rspack_import_3/* .EXCLAMATION_MARK */.Ec) { tokens.push({ type: TokenType.Operator, start: offset, end: offset + 1, }); offset += 1; } else { throw new _errors_adblock_syntax_error_js__rspack_import_4/* .AdblockSyntaxError */.q(`Unexpected character "${char}"`, baseOffset + offset, baseOffset + offset + 1); } } return tokens; } /** * Parses a logical expression. * * @param raw Raw input to parse. * @param options Global parser options. * @param baseOffset Starting offset of the input. Node locations are calculated relative to this offset. * * @returns Parsed expression. * * @throws {AdblockSyntaxError} If the expression is invalid. */ // TODO: Create a separate TokenStream class static parse(raw, options = _options_js__rspack_import_5/* .defaultParserOptions */.n, baseOffset = 0) { // Tokenize the source (produces an array of tokens) const tokens = LogicalExpressionParser.tokenize(raw, baseOffset); // Current token index let tokenIndex = 0; /** * Consumes a token of the expected type. * * @param type Expected token type. * * @returns The consumed token. */ function consume(type) { const token = tokens[tokenIndex]; if (!token) { throw new _errors_adblock_syntax_error_js__rspack_import_4/* .AdblockSyntaxError */.q(`Expected token of type "${type}", but reached end of input`, baseOffset, baseOffset + raw.length); } // We only use this function internally, so we can safely ignore this // from the coverage report // istanbul ignore next if (token.type !== type) { throw new _errors_adblock_syntax_error_js__rspack_import_4/* .AdblockSyntaxError */.q(`Expected token of type "${type}", but got "${token.type}"`, baseOffset + token.start, baseOffset + token.end); } tokenIndex += 1; return token; } /** * Parses a variable. * * @returns Variable node. */ function parseVariable() { const token = consume(TokenType.Variable); const result = { type: NodeType.Variable, name: raw.slice(token.start, token.end), }; if (options.isLocIncluded) { result.start = baseOffset + token.start; result.end = baseOffset + token.end; } return result; } /** * Parses a binary expression. * * @param left Left-hand side of the expression. * @param minPrecedence Minimum precedence of the operator. * * @returns Binary expression node. */ function parseBinaryExpression(left, minPrecedence = 0) { let node = left; let operatorToken; while (tokens[tokenIndex]) { operatorToken = tokens[tokenIndex]; if (!operatorToken || operatorToken.type !== TokenType.Operator) { break; } // It is safe to cast here, because we already checked the type const operator = raw.slice(operatorToken.start, operatorToken.end); const precedence = OPERATOR_PRECEDENCE[operator]; if (precedence < minPrecedence) { break; } tokenIndex += 1; // eslint-disable-next-line @typescript-eslint/no-use-before-define const right = parseExpression(precedence + 1); const newNode = { type: NodeType.Operator, operator, left: node, right, }; if (options.isLocIncluded) { newNode.start = node.start ?? baseOffset + operatorToken.start; newNode.end = right.end ?? baseOffset + operatorToken.end; } node = newNode; } return node; } /** * Parses a parenthesized expression. * * @returns Parenthesized expression node. */ function parseParenthesizedExpression() { consume(TokenType.Parenthesis); // eslint-disable-next-line @typescript-eslint/no-use-before-define const expression = parseExpression(); consume(TokenType.Parenthesis); const result = { type: NodeType.Parenthesis, expression, }; if (options.isLocIncluded) { result.start = expression.start; result.end = expression.end; } return result; } /** * Parses an expression. * * @param minPrecedence Minimum precedence of the operator. * * @returns Expression node. */ function parseExpression(minPrecedence = 0) { let node; const token = tokens[tokenIndex]; const value = raw.slice(token.start, token.end); if (token.type === TokenType.Variable) { node = parseVariable(); } else if (token.type === TokenType.Operator && value === _nodes_index_js__rspack_import_0/* .OperatorValue.Not */.oC.Not) { tokenIndex += 1; const expression = parseExpression(OPERATOR_PRECEDENCE[_nodes_index_js__rspack_import_0/* .OperatorValue.Not */.oC.Not]); node = { type: NodeType.Operator, operator: _nodes_index_js__rspack_import_0/* .OperatorValue.Not */.oC.Not, left: expression, }; if (options.isLocIncluded) { if (expression.end) { node.start = baseOffset + token.start; // no need to shift the node location, because it's already shifted node.end = expression.end; } else { node.start = baseOffset + token.start; node.end = baseOffset + token.end; } } } else if (token.type === TokenType.Parenthesis && value === _utils_constants_js__rspack_import_3/* .OPEN_PARENTHESIS */.Cx) { node = parseParenthesizedExpression(); } else { throw new _errors_adblock_syntax_error_js__rspack_import_4/* .AdblockSyntaxError */.q(`Unexpected token "${value}"`, baseOffset + token.start, baseOffset + token.end); } return parseBinaryExpression(node, minPrecedence); } const expression = parseExpression(); if (tokenIndex !== tokens.length) { throw new _errors_adblock_syntax_error_js__rspack_import_4/* .AdblockSyntaxError */.q(`Unexpected token "${tokens[tokenIndex].type}"`, baseOffset + tokens[tokenIndex].start, baseOffset + tokens[tokenIndex].end); } return expression; } } }, 24704(__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) { // EXPORTS __webpack_require__.d(__webpack_exports__, { l: () => (/* binding */ ModifierListParser) }); // EXTERNAL MODULE: ./node_modules/.pnpm/@adguard+agtree@4.2.1/node_modules/@adguard/agtree/dist/utils/constants.js var constants = __webpack_require__(53097); // EXTERNAL MODULE: ./node_modules/.pnpm/@adguard+agtree@4.2.1/node_modules/@adguard/agtree/dist/utils/string.js var string = __webpack_require__(16875); // EXTERNAL MODULE: ./node_modules/.pnpm/@adguard+agtree@4.2.1/node_modules/@adguard/agtree/dist/parser/base-parser.js var base_parser = __webpack_require__(79963); // EXTERNAL MODULE: ./node_modules/.pnpm/@adguard+agtree@4.2.1/node_modules/@adguard/agtree/dist/parser/options.js var parser_options = __webpack_require__(64626); // EXTERNAL MODULE: ./node_modules/.pnpm/@adguard+agtree@4.2.1/node_modules/@adguard/agtree/dist/errors/adblock-syntax-error.js var adblock_syntax_error = __webpack_require__(10631); // EXTERNAL MODULE: ./node_modules/.pnpm/@adguard+agtree@4.2.1/node_modules/@adguard/agtree/dist/parser/misc/value-parser.js var value_parser = __webpack_require__(29090); ;// CONCATENATED MODULE: ./node_modules/.pnpm/@adguard+agtree@4.2.1/node_modules/@adguard/agtree/dist/parser/misc/modifier-parser.js /* * AGTree v4.2.1 (build date: Wed, 12 Aug 2026 01:31:02 GMT) * (c) 2026 Adguard Software Ltd. * Released under the MIT license * https://github.com/AdguardTeam/tsurlfilter/tree/master/packages/agtree#readme */ /** * `ModifierParser` is responsible for parsing modifiers. * * @example * `match-case`, `~third-party`, `domain=example.com|~example.org` */ class ModifierParser extends base_parser/* .BaseParser */.V { /** * Parses a modifier. * * @param raw Raw input to parse. * @param options Global parser options. * @param baseOffset Starting offset of the input. Node locations are calculated relative to this offset. * * @returns Parsed modifier. * * @throws An error if modifier name or value is empty. */ static parse(raw, options = parser_options/* .defaultParserOptions */.n, baseOffset = 0) { let offset = 0; // Skip leading whitespace offset = string/* .StringUtils.skipWS */.$x.skipWS(raw, offset); // Save the offset of the first character of the modifier (whole modifier) const modifierStart = offset; // Check if the modifier is an exception let exception = false; if (raw[offset] === constants/* .NEGATION_MARKER */.bP) { offset += constants/* .NEGATION_MARKER.length */.bP.length; exception = true; } // Skip whitespace after the exception marker (if any) offset = string/* .StringUtils.skipWS */.$x.skipWS(raw, offset); // Save the offset of the first character of the modifier name const modifierNameStart = offset; // Find assignment operator const assignmentIndex = string/* .StringUtils.findNextUnescapedCharacter */.$x.findNextUnescapedCharacter(raw, constants/* .MODIFIER_ASSIGN_OPERATOR */.li); // Find the end of the modifier const modifierEnd = Math.max(string/* .StringUtils.skipWSBack */.$x.skipWSBack(raw) + 1, modifierNameStart); // Modifier name can't be empty if (modifierNameStart === modifierEnd) { throw new adblock_syntax_error/* .AdblockSyntaxError */.q('Modifier name cannot be empty', baseOffset, baseOffset + raw.length); } let modifier; let value; // If there is no assignment operator, the whole modifier is the name // without a value if (assignmentIndex === -1) { modifier = value_parser/* .ValueParser.parse */.J.parse(raw.slice(modifierNameStart, modifierEnd), options, baseOffset + modifierNameStart); } else { // If there is an assignment operator, first we need to find the // end of the modifier name, then we can parse the value const modifierNameEnd = string/* .StringUtils.skipWSBack */.$x.skipWSBack(raw, assignmentIndex - 1) + 1; modifier = value_parser/* .ValueParser.parse */.J.parse(raw.slice(modifierNameStart, modifierNameEnd), options, baseOffset + modifierNameStart); // Value can't be empty if (assignmentIndex + 1 === modifierEnd) { throw new adblock_syntax_error/* .AdblockSyntaxError */.q('Modifier value cannot be empty', baseOffset, baseOffset + raw.length); } // Skip whitespace after the assignment operator const valueStart = string/* .StringUtils.skipWS */.$x.skipWS(raw, assignmentIndex + constants/* .MODIFIER_ASSIGN_OPERATOR.length */.li.length); value = value_parser/* .ValueParser.parse */.J.parse(raw.slice(valueStart, modifierEnd), options, baseOffset + valueStart); } const result = { type: 'Modifier', name: modifier, value, exception, }; if (options.isLocIncluded) { result.start = baseOffset + modifierStart; result.end = baseOffset + modifierEnd; } return result; } } ;// CONCATENATED MODULE: ./node_modules/.pnpm/@adguard+agtree@4.2.1/node_modules/@adguard/agtree/dist/parser/misc/modifier-list.js /* * AGTree v4.2.1 (build date: Wed, 12 Aug 2026 01:31:02 GMT) * (c) 2026 Adguard Software Ltd. * Released under the MIT license * https://github.com/AdguardTeam/tsurlfilter/tree/master/packages/agtree#readme */ /** * `ModifierListParser` is responsible for parsing modifier lists. Please note that the name is not * uniform, "modifiers" are also known as "options". * * @see {@link https://kb.adguard.com/en/general/how-to-create-your-own-ad-filters#basic-rules-modifiers} * @see {@link https://kb.adguard.com/en/general/how-to-create-your-own-ad-filters#non-basic-rules-modifiers} * @see {@link https://help.eyeo.com/adblockplus/how-to-write-filters#options} */ class ModifierListParser extends base_parser/* .BaseParser */.V { /** * Parses the cosmetic rule modifiers, eg. `third-party,domain=example.com|~example.org`. * * _Note:_ you should remove `$` separator before passing the raw modifiers to this function, * or it will be parsed in the first modifier. * * @param raw Raw input to parse. * @param options Global parser options. * @param baseOffset Starting offset of the input. Node locations are calculated relative to this offset. * * @returns Parsed modifiers interface. */ static parse(raw, options = parser_options/* .defaultParserOptions */.n, baseOffset = 0) { const result = { type: 'ModifierList', children: [], }; if (options.isLocIncluded) { result.start = baseOffset; result.end = baseOffset + raw.length; } let offset = string/* .StringUtils.skipWS */.$x.skipWS(raw); let separatorIndex = -1; // Split modifiers by unescaped commas while (offset < raw.length) { // Skip whitespace before the modifier offset = string/* .StringUtils.skipWS */.$x.skipWS(raw, offset); const modifierStart = offset; // Check if this modifier has a regexp pattern // Look for the `=` sign to find where the modifier value starts let useSimpleSearch = false; const equalsIndex = raw.indexOf('=', offset); if (equalsIndex !== -1 && equalsIndex < raw.length - 1) { const valueStart = equalsIndex + 1; // Check if value starts with / (potential regex) if (raw[valueStart] === '/' && raw[valueStart + 1] !== '/') { // Look for a closing / for the regex pattern // Search through the rest of the string for an unescaped / let firstClosingSlashIndex = -1; for (let i = valueStart + 1; i < raw.length; i += 1) { if (raw[i] === '/' && raw[i - 1] !== '\\') { firstClosingSlashIndex = i; break; } } if (firstClosingSlashIndex === -1) { // No closing slash found anywhere - incomplete regex pattern // Use simple search to allow it to work when it's the last modifier useSimpleSearch = true; } else { // Found a closing slash - check if there are MORE slashes after it // If yes, this might be a complex pattern like replace=/pattern/replacement/flags // and we should use simple search to avoid breaking it let hasMoreSlashes = false; for (let i = firstClosingSlashIndex + 1; i < raw.length; i += 1) { if (raw[i] === '/' && raw[i - 1] !== '\\') { hasMoreSlashes = true; break; } } // Use simple search if there are more slashes (complex pattern) if (hasMoreSlashes) { useSimpleSearch = true; } } } else { // Value doesn't start with `/`, so it's not a regexp pattern. // Use simple search to avoid treating slashes in values // as regex markers, e.g. `redirect=googlesyndication.com/adsbygoogle.js`. useSimpleSearch = true; } } // Find the index of the first unescaped comma let nextSeparator; if (useSimpleSearch) { // Use simple search for incomplete regex patterns nextSeparator = string/* .StringUtils.findNextUnescapedCharacter */.$x.findNextUnescapedCharacter(raw, constants/* .MODIFIERS_SEPARATOR */.b9, offset); } else { // Use regex-aware search to handle complete regex patterns nextSeparator = string/* .StringUtils.findUnescapedNonStringNonRegexChar */.$x.findUnescapedNonStringNonRegexChar(raw, constants/* .MODIFIERS_SEPARATOR */.b9, offset); } separatorIndex = nextSeparator; const modifierEnd = separatorIndex === -1 ? raw.length : string/* .StringUtils.skipWSBack */.$x.skipWSBack(raw, separatorIndex - 1) + 1; // Parse the modifier const modifier = ModifierParser.parse(raw.slice(modifierStart, modifierEnd), options, baseOffset + modifierStart); result.children.push(modifier); // Increment the offset to the next modifier (or the end of the string) offset = separatorIndex === -1 ? raw.length : separatorIndex + 1; } // Check if there are any modifiers after the last separator if (separatorIndex !== -1) { const modifierStart = string/* .StringUtils.skipWS */.$x.skipWS(raw, separatorIndex + 1); result.children.push(ModifierParser.parse(raw.slice(modifierStart, raw.length), options, baseOffset + modifierStart)); } return result; } } }, 43939(__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) { __webpack_require__.d(__webpack_exports__, { D: () => (ParameterListParser) }); /* import */ var _utils_constants_js__rspack_import_2 = __webpack_require__(53097); /* import */ var _utils_string_js__rspack_import_3 = __webpack_require__(16875); /* import */ var _base_parser_js__rspack_import_0 = __webpack_require__(79963); /* import */ var _options_js__rspack_import_1 = __webpack_require__(64626); /* import */ var _value_parser_js__rspack_import_4 = __webpack_require__(29090); /* * AGTree v4.2.1 (build date: Wed, 12 Aug 2026 01:31:02 GMT) * (c) 2026 Adguard Software Ltd. * Released under the MIT license * https://github.com/AdguardTeam/tsurlfilter/tree/master/packages/agtree#readme */ /** * Parser for parameter lists. */ class ParameterListParser extends _base_parser_js__rspack_import_0/* .BaseParser */.V { /** * Parses a raw parameter list. * * @param raw Raw input to parse. * @param options Global parser options. * @param baseOffset Starting offset of the input. Node locations are calculated relative to this offset. * @param separator Separator character (default: comma). * * @returns Parameter list AST. */ static parse(raw, options = _options_js__rspack_import_1/* .defaultParserOptions */.n, baseOffset = 0, separator = _utils_constants_js__rspack_import_2/* .COMMA */.KE) { // Prepare the parameter list node const params = { type: 'ParameterList', children: [], }; const { length } = raw; if (options.isLocIncluded) { params.start = baseOffset; params.end = baseOffset + length; } let offset = 0; // Parse parameters: skip whitespace before and after each parameter, and // split parameters by the separator character. while (offset < length) { // Skip whitespace before parameter offset = _utils_string_js__rspack_import_3/* .StringUtils.skipWS */.$x.skipWS(raw, offset); // Parameter may only contain whitespace // In this case, we reached the end of the parameter list if (raw[offset] === separator || offset === length) { // Add a null for empty parameter params.children.push(null); // Skip separator offset += 1; } else { // Get parameter start position const paramStart = offset; // Get next unescaped separator position const nextSeparator = _utils_string_js__rspack_import_3/* .StringUtils.findUnescapedNonStringNonRegexChar */.$x.findUnescapedNonStringNonRegexChar(raw, separator, offset); // Get parameter end position const paramEnd = nextSeparator !== -1 ? _utils_string_js__rspack_import_3/* .StringUtils.skipWSBack */.$x.skipWSBack(raw, nextSeparator - 1) : _utils_string_js__rspack_import_3/* .StringUtils.skipWSBack */.$x.skipWSBack(raw); // Add parameter to the list const param = _value_parser_js__rspack_import_4/* .ValueParser.parse */.J.parse(raw.slice(paramStart, paramEnd + 1), options, baseOffset + paramStart); params.children.push(param); // Set offset to the next separator position + 1 offset = nextSeparator !== -1 ? nextSeparator + 1 : length; } } // If the last character was a separator, add an additional null parameter if (raw[length - 1] === separator) { params.children.push(null); } return params; } } }, 29090(__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) { __webpack_require__.d(__webpack_exports__, { J: () => (ValueParser) }); /* import */ var _base_parser_js__rspack_import_0 = __webpack_require__(79963); /* import */ var _options_js__rspack_import_1 = __webpack_require__(64626); /* * AGTree v4.2.1 (build date: Wed, 12 Aug 2026 01:31:02 GMT) * (c) 2026 Adguard Software Ltd. * Released under the MIT license * https://github.com/AdguardTeam/tsurlfilter/tree/master/packages/agtree#readme */ /** * Value parser. * This parser is very simple, it just exists to provide a consistent interface for parsing. */ class ValueParser extends _base_parser_js__rspack_import_0/* .BaseParser */.V { /** * Parses a value. * * @param raw Raw input to parse. * @param options Global parser options. * @param baseOffset Starting offset of the input. Node locations are calculated relative to this offset. * * @returns Value node. */ static parse(raw, options = _options_js__rspack_import_1/* .defaultParserOptions */.n, baseOffset = 0) { const result = { type: 'Value', value: raw, }; if (options.isLocIncluded) { result.start = baseOffset; result.end = baseOffset + raw.length; } return result; } } }, 72192(__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) { __webpack_require__.d(__webpack_exports__, { i: () => (NetworkRuleParser) }); /* import */ var _errors_adblock_syntax_error_js__rspack_import_5 = __webpack_require__(10631); /* import */ var _nodes_index_js__rspack_import_7 = __webpack_require__(79864); /* import */ var _utils_adblockers_js__rspack_import_8 = __webpack_require__(22380); /* import */ var _utils_constants_js__rspack_import_3 = __webpack_require__(53097); /* import */ var _utils_string_js__rspack_import_2 = __webpack_require__(16875); /* import */ var _base_parser_js__rspack_import_0 = __webpack_require__(79963); /* import */ var _misc_modifier_list_js__rspack_import_6 = __webpack_require__(24704); /* import */ var _misc_value_parser_js__rspack_import_4 = __webpack_require__(29090); /* import */ var _options_js__rspack_import_1 = __webpack_require__(64626); /* * AGTree v4.2.1 (build date: Wed, 12 Aug 2026 01:31:02 GMT) * (c) 2026 Adguard Software Ltd. * Released under the MIT license * https://github.com/AdguardTeam/tsurlfilter/tree/master/packages/agtree#readme */ /** * `NetworkRuleParser` is responsible for parsing network rules. * * Please note that this will parse all syntactically correct network rules. * Modifier compatibility is not checked at the parser level. * * @see {@link https://kb.adguard.com/en/general/how-to-create-your-own-ad-filters#basic-rules} * @see {@link https://help.eyeo.com/adblockplus/how-to-write-filters#basic} */ class NetworkRuleParser extends _base_parser_js__rspack_import_0/* .BaseParser */.V { /** * Parses a network rule (also known as basic rule). * * @param raw Raw input to parse. * @param options Global parser options. * @param baseOffset Starting offset of the input. Node locations are calculated relative to this offset. * * @returns Network rule AST. * * @throws If the rule is syntactically incorrect. */ static parse(raw, options = _options_js__rspack_import_1/* .defaultParserOptions */.n, baseOffset = 0) { let offset = 0; // Skip leading whitespace offset = _utils_string_js__rspack_import_2/* .StringUtils.skipWS */.$x.skipWS(raw, offset); // Handle exception rules let exception = false; // Rule starts with exception marker, eg @@||example.com, // where @@ is the exception marker if (raw.startsWith(_utils_constants_js__rspack_import_3/* .NETWORK_RULE_EXCEPTION_MARKER */.rF, offset)) { offset += _utils_constants_js__rspack_import_3/* .NETWORK_RULE_EXCEPTION_MARKER_LEN */.Lb; exception = true; } // Save the start of the pattern const patternStart = offset; // Find corresponding (last) separator ($) character (if any) const separatorIndex = NetworkRuleParser.findNetworkRuleSeparatorIndex(raw); // Save the end of the pattern const patternEnd = separatorIndex === -1 ? _utils_string_js__rspack_import_2/* .StringUtils.skipWSBack */.$x.skipWSBack(raw) + 1 : _utils_string_js__rspack_import_2/* .StringUtils.skipWSBack */.$x.skipWSBack(raw, separatorIndex - 1) + 1; // Parse pattern const pattern = _misc_value_parser_js__rspack_import_4/* .ValueParser.parse */.J.parse(raw.slice(patternStart, patternEnd), options, baseOffset + patternStart); // Parse modifiers (if any) let modifiers; // Get a last non-whitespace index const lastNonWsIndex = _utils_string_js__rspack_import_2/* .StringUtils.skipWSBack */.$x.skipWSBack(raw); // Find start and end index of the modifiers const modifiersStart = separatorIndex + 1; const modifiersEnd = _utils_string_js__rspack_import_2/* .StringUtils.skipWSBack */.$x.skipWSBack(raw) + 1; if (separatorIndex !== -1) { // Check for empty modifiers if (separatorIndex === lastNonWsIndex) { throw new _errors_adblock_syntax_error_js__rspack_import_5/* .AdblockSyntaxError */.q('Empty modifiers are not allowed', baseOffset + separatorIndex, baseOffset + raw.length); } modifiers = _misc_modifier_list_js__rspack_import_6/* .ModifierListParser.parse */.l.parse(raw.slice(modifiersStart, modifiersEnd), options, baseOffset + modifiersStart); } // Throw error if there is no pattern and no modifiers if (pattern.value.length === 0 && (modifiers === undefined || modifiers.children.length === 0)) { throw new _errors_adblock_syntax_error_js__rspack_import_5/* .AdblockSyntaxError */.q('Network rule must have a pattern or modifiers', baseOffset, baseOffset + raw.length); } const result = { type: _nodes_index_js__rspack_import_7/* .NetworkRuleType.NetworkRule */.vY.NetworkRule, category: _nodes_index_js__rspack_import_7/* .RuleCategory.Network */.$O.Network, syntax: _utils_adblockers_js__rspack_import_8/* .AdblockSyntax.Common */.YG.Common, exception, pattern, modifiers, }; if (options.includeRaws) { result.raws = { text: raw, }; } if (options.isLocIncluded) { result.start = baseOffset; result.end = baseOffset + raw.length; } return result; } /** * Finds the index of the separator character in a network rule. * * @param rule Network rule to check. * * @returns The index of the separator character, or -1 if there is no separator. */ static findNetworkRuleSeparatorIndex(rule) { // As we are looking for the last separator, we start from the end of the string for (let i = rule.length - 1; i >= 0; i -= 1) { // If we find a potential separator, we should check // - if it's not escaped // - if it's not followed by a regex marker, for example: `example.org^$removeparam=/regex$/` // eslint-disable-next-line max-len if (rule[i] === _utils_constants_js__rspack_import_3/* .NETWORK_RULE_SEPARATOR */.Xj && rule[i + 1] !== _utils_constants_js__rspack_import_3/* .REGEX_MARKER */.Vb && rule[i - 1] !== _utils_constants_js__rspack_import_3/* .ESCAPE_CHARACTER */.Kx) { return i; } } return -1; } } }, 64626(__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) { __webpack_require__.d(__webpack_exports__, { n: () => (defaultParserOptions) }); /* * AGTree v4.2.1 (build date: Wed, 12 Aug 2026 01:31:02 GMT) * (c) 2026 Adguard Software Ltd. * Released under the MIT license * https://github.com/AdguardTeam/tsurlfilter/tree/master/packages/agtree#readme */ /** * @file Common options for all parsers. */ /** * Default parser options. */ const defaultParserOptions = Object.freeze({ tolerant: false, isLocIncluded: true, parseAbpSpecificRules: true, parseUboSpecificRules: true, includeRaws: true, ignoreComments: false, parseHostRules: false, parseHtmlFilteringRuleBodies: false, }); }, 53550(__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) { // EXPORTS __webpack_require__.d(__webpack_exports__, { G: () => (/* binding */ RuleParser) }); // EXTERNAL MODULE: ./node_modules/.pnpm/@adguard+agtree@4.2.1/node_modules/@adguard/agtree/dist/errors/adblock-syntax-error.js var adblock_syntax_error = __webpack_require__(10631); // EXTERNAL MODULE: ./node_modules/.pnpm/@adguard+agtree@4.2.1/node_modules/@adguard/agtree/dist/nodes/index.js var nodes = __webpack_require__(79864); // EXTERNAL MODULE: ./node_modules/.pnpm/@adguard+agtree@4.2.1/node_modules/@adguard/agtree/dist/utils/adblockers.js var adblockers = __webpack_require__(22380); // EXTERNAL MODULE: ./node_modules/.pnpm/@adguard+agtree@4.2.1/node_modules/@adguard/agtree/dist/parser/base-parser.js var base_parser = __webpack_require__(79963); // EXTERNAL MODULE: ./node_modules/.pnpm/@adguard+agtree@4.2.1/node_modules/@adguard/agtree/dist/parser/comment/comment-parser.js + 9 modules var comment_parser = __webpack_require__(83102); // EXTERNAL MODULE: ./node_modules/.pnpm/@adguard+agtree@4.2.1/node_modules/@adguard/agtree/dist/parser/cosmetic/cosmetic-rule-parser.js + 6 modules var cosmetic_rule_parser = __webpack_require__(36573); // EXTERNAL MODULE: ./node_modules/.pnpm/is-ip@3.1.0/node_modules/is-ip/index.js var is_ip = __webpack_require__(4371); // EXTERNAL MODULE: ./node_modules/.pnpm/tldts@5.7.112/node_modules/tldts/dist/es6/index.js + 12 modules var es6 = __webpack_require__(86136); // EXTERNAL MODULE: ./node_modules/.pnpm/@adguard+agtree@4.2.1/node_modules/@adguard/agtree/dist/utils/string.js var string = __webpack_require__(16875); // EXTERNAL MODULE: ./node_modules/.pnpm/@adguard+agtree@4.2.1/node_modules/@adguard/agtree/dist/parser/misc/value-parser.js var value_parser = __webpack_require__(29090); // EXTERNAL MODULE: ./node_modules/.pnpm/@adguard+agtree@4.2.1/node_modules/@adguard/agtree/dist/parser/options.js var parser_options = __webpack_require__(64626); ;// CONCATENATED MODULE: ./node_modules/.pnpm/@adguard+agtree@4.2.1/node_modules/@adguard/agtree/dist/parser/network/host-rule-parser.js /* * AGTree v4.2.1 (build date: Wed, 12 Aug 2026 01:31:02 GMT) * (c) 2026 Adguard Software Ltd. * Released under the MIT license * https://github.com/AdguardTeam/tsurlfilter/tree/master/packages/agtree#readme */ /* eslint-disable no-param-reassign */ /** * `HostRuleParser` is responsible for parsing hosts-like rules. * * HostRule is a structure for simple host-level rules (i.e. /etc/hosts syntax). * It also supports "just domain" syntax. In this case, the IP will be set to 0.0.0.0. * * Rules syntax looks like this:. * ```text * IP_address canonical_hostname [aliases...] * ``` * * @see {@link http://man7.org/linux/man-pages/man5/hosts.5.html} * * @example * `192.168.1.13 bar.mydomain.org bar` -- ipv4 * `ff02::1 ip6-allnodes` -- ipv6 * `::1 localhost ip6-localhost ip6-loopback` -- ipv6 aliases * `example.org` -- "just domain" syntax */ class HostRuleParser extends base_parser/* .BaseParser */.V { /** * Default IP address for host rules without explicit IP. */ static NULL_IP = '0.0.0.0'; /** * Comment marker character. */ static COMMENT_MARKER = '#'; /** * Parses an etc/hosts-like rule. * * @param raw Raw input to parse. * @param options Global parser options. * @param baseOffset Starting offset of the input. Node locations are calculated relative to this offset. * * @returns Host rule node. * * @throws If the input contains invalid data. */ static parse(raw, options = parser_options/* .defaultParserOptions */.n, baseOffset = 0) { let offset = string/* .StringUtils.skipWS */.$x.skipWS(raw, 0); const parts = []; let lastPartStartIndex = offset; let comment = null; const rawLength = raw.length; const parsePartIfNeeded = (startIndex, endIndex) => { if (startIndex < endIndex) { parts.push(value_parser/* .ValueParser.parse */.J.parse(raw.slice(startIndex, endIndex), options, baseOffset + startIndex)); } }; while (offset < rawLength) { if (string/* .StringUtils.isWhitespace */.$x.isWhitespace(raw[offset])) { parsePartIfNeeded(lastPartStartIndex, offset); offset = string/* .StringUtils.skipWS */.$x.skipWS(raw, offset); lastPartStartIndex = offset; } else if (raw[offset] === HostRuleParser.COMMENT_MARKER) { const commentStart = offset; offset = string/* .StringUtils.skipWS */.$x.skipWS(raw, offset + 1); comment = value_parser/* .ValueParser.parse */.J.parse(raw.slice(offset), options, baseOffset + commentStart); offset = rawLength; lastPartStartIndex = offset; } else { offset += 1; } } parsePartIfNeeded(lastPartStartIndex, offset); const partsLength = parts.length; if (partsLength < 1) { throw new Error('Host rule must have at least one domain name or an IP address and a domain name'); } const result = { category: nodes/* .RuleCategory.Network */.$O.Network, type: nodes/* .NetworkRuleType.HostRule */.vY.HostRule, syntax: adblockers/* .AdblockSyntax.Common */.YG.Common, }; if (partsLength === 1) { // "Just domain" syntax, e.g. `example.org` // In this case, domain should be valid and IP will be set to 0.0.0.0 by default if ((0,es6/* .getDomain */.FB)(parts[0].value) !== parts[0].value) { throw new Error(`Not a valid domain: ${parts[0].value}`); } result.ip = { type: 'Value', value: HostRuleParser.NULL_IP, }; result.hostnames = { type: 'HostnameList', children: parts, }; } else if (partsLength > 1) { // IP + domain list syntax const [ip, ...hostnames] = parts; if (!is_ip(ip.value)) { throw new Error(`Invalid IP address: ${ip.value}`); } for (const { value } of hostnames) { if ((0,es6/* .getHostname */.EW)(value) !== value) { throw new Error(`Not a valid hostname: ${value}`); } } result.ip = ip; result.hostnames = { type: 'HostnameList', children: hostnames, }; } if (comment) { result.comment = comment; } if (options.includeRaws) { result.raws = { text: raw, }; } return result; } } // EXTERNAL MODULE: ./node_modules/.pnpm/@adguard+agtree@4.2.1/node_modules/@adguard/agtree/dist/parser/network/network-rule-parser.js var network_rule_parser = __webpack_require__(72192); ;// CONCATENATED MODULE: ./node_modules/.pnpm/@adguard+agtree@4.2.1/node_modules/@adguard/agtree/dist/parser/rule-parser.js /* * AGTree v4.2.1 (build date: Wed, 12 Aug 2026 01:31:02 GMT) * (c) 2026 Adguard Software Ltd. * Released under the MIT license * https://github.com/AdguardTeam/tsurlfilter/tree/master/packages/agtree#readme */ /* eslint-disable no-param-reassign */ /** * `RuleParser` is responsible for parsing the rules. * * It automatically determines the category and syntax of the rule, so you can pass any kind of rule to it. */ class RuleParser extends base_parser/* .BaseParser */.V { /** * Helper method to parse host rules if the `parseHostRules` option is enabled, otherwise it will * parse network rules. * * @param raw Raw input to parse. * @param options Global parser options. * @param baseOffset Starting offset of the input. Node locations are calculated relative to this offset. * * @returns Host rule or network rule node. */ static parseHostOrNetworkRule(raw, options, baseOffset) { if (options.parseHostRules) { try { return HostRuleParser.parse(raw, options, baseOffset); } catch (error) { // Ignore the error, and fall back to network rule parser } } return network_rule_parser/* .NetworkRuleParser.parse */.i.parse(raw, options, baseOffset); } /** * Parse an adblock rule. You can pass any kind of rule to this method, since it will automatically determine * the category and syntax. If the rule is syntactically invalid, then an error will be thrown. If the * syntax / compatibility cannot be determined clearly, then the value of the `syntax` property will be * `Common`. * * For example, let's have this network rule: * ```adblock * ||example.org^$important * ``` * The `syntax` property will be `Common`, since the rule is syntactically correct in every adblockers, but we * cannot determine at parsing level whether `important` is an existing option or not, nor if it exists, then * which adblocker supports it. This is why the `syntax` property is simply `Common` at this point. * The concrete COMPATIBILITY of the rule will be determined later, in a different, higher-level layer, called * "Compatibility table". * * But we can determinate the concrete syntax of this rule: * ```adblock * example.org#%#//scriptlet("scriptlet0", "arg0") * ``` * since it is clearly an AdGuard-specific rule and no other adblockers uses this syntax natively. However, we also * cannot determine the COMPATIBILITY of this rule, as it is not clear at this point whether the `scriptlet0` * scriptlet is supported by AdGuard or not. This is also the task of the "Compatibility table". Here, we simply * mark the rule with the `AdGuard` syntax in this case. * * @param raw Raw input to parse. * @param options Global parser options. * @param baseOffset Starting offset of the input. Node locations are calculated relative to this offset. * * @returns Adblock rule node. * * @throws If the input matches a pattern but syntactically invalid. * * @example * Take a look at the following example: * ```js * // Parse a network rule * const ast1 = RuleParser.parse("||example.org^$important"); * * // Parse another network rule * const ast2 = RuleParser.parse("/ads.js^$important,third-party,domain=example.org|~example.com"); * * // Parse a cosmetic rule * const ast2 = RuleParser.parse("example.org##.banner"); * * // Parse another cosmetic rule * const ast3 = RuleParser.parse("example.org#?#.banner:-abp-has(.ad)"); * * // Parse a comment rule * const ast4 = RuleParser.parse("! Comment"); * * // Parse an empty rule * const ast5 = RuleParser.parse(""); * * // Parse a comment rule (with metadata) * const ast6 = RuleParser.parse("! Title: Example"); * * // Parse a pre-processor rule * const ast7 = RuleParser.parse("!#if (adguard)"); * ``` */ static parse(raw, options = parser_options/* .defaultParserOptions */.n, baseOffset = 0) { try { // Empty lines / rules (handle it just for convenience) if (raw.trim().length === 0) { const result = { type: 'EmptyRule', category: nodes/* .RuleCategory.Empty */.$O.Empty, syntax: adblockers/* .AdblockSyntax.Common */.YG.Common, }; if (options.includeRaws) { result.raws = { text: raw, }; } if (options.isLocIncluded) { result.start = baseOffset; result.end = baseOffset + raw.length; } return result; } // Try to parse the rule with all sub-parsers. If a rule doesn't match // the pattern of a parser, then it will return `null`. For example, a // network rule will not match the pattern of a comment rule, since it // doesn't start with comment marker. But if the rule matches the // pattern of a parser, then it will return the AST of the rule, or // throw an error if the rule is syntactically invalid. if (options.ignoreComments) { if (comment_parser/* .CommentParser.isCommentRule */.B.isCommentRule(raw)) { const result = { type: 'EmptyRule', category: nodes/* .RuleCategory.Empty */.$O.Empty, syntax: adblockers/* .AdblockSyntax.Common */.YG.Common, }; if (options.includeRaws) { result.raws = { text: raw, }; } if (options.isLocIncluded) { result.start = baseOffset; result.end = baseOffset + raw.length; } return result; } return cosmetic_rule_parser/* .CosmeticRuleParser.parse */.R.parse(raw, options, baseOffset) || RuleParser.parseHostOrNetworkRule(raw, options, baseOffset); } return comment_parser/* .CommentParser.parse */.B.parse(raw, options, baseOffset) || cosmetic_rule_parser/* .CosmeticRuleParser.parse */.R.parse(raw, options, baseOffset) || RuleParser.parseHostOrNetworkRule(raw, options, baseOffset); } catch (error) { // If tolerant mode is disabled or the error is not known, then simply // re-throw the error if (!options.tolerant || !(error instanceof Error)) { throw error; } // If tolerant mode is enabled and we have an onParseError callback, // call it for any error instances if (options.onParseError) { options.onParseError(error); } const errorNode = { type: 'InvalidRuleError', name: error.name, message: error.message, }; // If the error is an AdblockSyntaxError, then we can add the // location of the error to the result if (error instanceof adblock_syntax_error/* .AdblockSyntaxError */.q) { errorNode.start = error.start; errorNode.end = error.end; } // Otherwise, return an invalid rule (tolerant mode) const result = { type: 'InvalidRule', category: nodes/* .RuleCategory.Invalid */.$O.Invalid, syntax: adblockers/* .AdblockSyntax.Common */.YG.Common, raw, error: errorNode, }; if (options.includeRaws) { result.raws = { text: raw, }; } if (options.isLocIncluded) { result.start = baseOffset; result.end = baseOffset + raw.length; } return result; } } } }, 22380(__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) { __webpack_require__.d(__webpack_exports__, { C6: () => (AdblockProduct), YG: () => (AdblockSyntax) }); /* * AGTree v4.2.1 (build date: Wed, 12 Aug 2026 01:31:02 GMT) * (c) 2026 Adguard Software Ltd. * Released under the MIT license * https://github.com/AdguardTeam/tsurlfilter/tree/master/packages/agtree#readme */ /** * @file Possible adblock syntaxes are listed here. */ /** * Adblock products (specific adblockers, excludes 'Common'). */ const AdblockProduct = { /** * Adblock Plus. * * @see {@link https://adblockplus.org/} */ Abp: 'AdblockPlus', /** * UBlock Origin.. * * @see {@link https://github.com/gorhill/uBlock} */ Ubo: 'UblockOrigin', /** * AdGuard. * * @see {@link https://adguard.com/} */ Adg: 'AdGuard', }; /** * Possible adblock syntaxes (supported by this library). */ const AdblockSyntax = { /** * Common syntax, which is supported by more than one adblocker (or by all adblockers). * * We typically use this syntax when we cannot determine the concrete syntax of the rule, * because the syntax is used by more than one adblocker natively. * * @example * - `||example.org^$important` is a common syntax, since it is used by all adblockers natively, and * we cannot determine at parsing level whether `important` is a valid option or not, and if it is valid, * then which adblocker supports it. */ Common: 'Common', /** * Adblock Plus syntax. * * @see {@link https://adblockplus.org/} * * @example * - `example.org#$#abort-on-property-read alert` is an Adblock Plus syntax, since it is not used by any other * adblockers directly (probably supported by some on-the-fly conversion, but this is not the native syntax). */ Abp: AdblockProduct.Abp, /** * UBlock Origin syntax.. * * @see {@link https://github.com/gorhill/uBlock} * * @example * - `example.com##+js(set, atob, noopFunc)` is an uBlock Origin syntax, since it is not used by any other * adblockers directly (probably supported by some on-the-fly conversion, but this is not the native syntax). */ Ubo: AdblockProduct.Ubo, /** * AdGuard syntax. * * @see {@link https://adguard.com/} * * @example * - `example.org#%#//scriptlet("abort-on-property-read", "alert")` is an AdGuard syntax, since it is not used * by any other adblockers directly (probably supported by some on-the-fly conversion, but this is not the native * syntax). */ Adg: AdblockProduct.Adg, }; /** * Map of adblock products to their human-readable names. */ const PRODUCT_HUMAN_READABLE_NAME_MAP = new Map([ [AdblockProduct.Abp, 'AdBlock / Adblock Plus'], [AdblockProduct.Ubo, 'uBlock Origin'], [AdblockProduct.Adg, 'AdGuard'], ]); /** * Returns the human-readable name for the given adblock product. * * @param product Adblock product. * * @returns Human-readable product name, e.g., 'Adblock Plus', 'uBlock Origin', 'AdGuard'. * * @throws Error if the product is unknown. * * @example * ```typescript * getHumanReadableProductName(AdblockProduct.Abp); // 'Adblock Plus' * getHumanReadableProductName(AdblockProduct.Ubo); // 'uBlock Origin' * getHumanReadableProductName(AdblockProduct.Adg); // 'AdGuard' * ``` */ const getHumanReadableProductName = (product) => { const name = PRODUCT_HUMAN_READABLE_NAME_MAP.get(product); if (!name) { throw new Error(`Unknown product: ${product}`); } return name; }; }, 53097(__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) { __webpack_require__.d(__webpack_exports__, { A1: () => (CLOSE_SQUARE_BRACKET), AT: () => (SMALL_LETTER_Z), Ae: () => (CSS_MEDIA_MARKER), BH: () => (AGLINT_COMMAND_PREFIX), BR: () => (HINT_MARKER_LEN), Bt: () => (UBO_RESPONSEHEADER_FN), C: () => (HASHMARK), CR: () => (CR), Cx: () => (OPEN_PARENTHESIS), Ec: () => (EXCLAMATION_MARK), Ez: () => (AGLINT_CONFIG_COMMENT_MARKER), FF: () => (FF), H3: () => (SMALL_LETTER_A), I6: () => (UBO_MATCHES_PATH_OPERATOR), I8: () => (SEMICOLON), IF: () => (IF), JD: () => (ADG_PATH_MODIFIER), KE: () => (COMMA), KT: () => (CRLF), Kx: () => (ESCAPE_CHARACTER), L5: () => (PIPE), LF: () => (LF), Lb: () => (NETWORK_RULE_EXCEPTION_MARKER_LEN), Ln: () => (ASTERISK), NW: () => (ADG_DOMAINS_MODIFIER), Nb: () => (QUESTION_MARK), PD: () => (PREPROCESSOR_MARKER), Pe: () => (ADG_APP_MODIFIER), Rq: () => (UBO_SCRIPTLET_MASK), UT: () => (EQUALS), Vb: () => (REGEX_MARKER), Vs: () => (UBO_SCRIPTLET_MASK_LEGACY), Vw: () => (ADG_URL_MODIFIER), Xj: () => (NETWORK_RULE_SEPARATOR), _h: () => (UBO_HTML_MASK), b9: () => (MODIFIERS_SEPARATOR), bP: () => (NEGATION_MARKER), bs: () => (WILDCARD), cP: () => (CARET), cU: () => (OPEN_SQUARE_BRACKET), e0: () => (AMPERSAND), fB: () => (UNDERSCORE), fW: () => (PIPE_MODIFIER_SEPARATOR), fi: () => (DOUBLE_QUOTE), g9: () => (NUMBER_9), hk: () => (CAPITAL_LETTER_Z), j6: () => (HINT_MARKER), li: () => (MODIFIER_ASSIGN_OPERATOR), nC: () => (NUMBER_0), nj: () => (DOLLAR_SIGN), nx: () => (PREPROCESSOR_MARKER_LEN), o: () => (SLASH), oH: () => (COLON), oo: () => (COMMA_DOMAIN_LIST_SEPARATOR), ot: () => (CAPITAL_LETTER_A), pi: () => (CSS_BLOCK_CLOSE), rF: () => (NETWORK_RULE_EXCEPTION_MARKER), rM: () => (INCLUDE), r_: () => (BACKSLASH), s1: () => (CLOSE_PARENTHESIS), sA: () => (PREPROCESSOR_SEPARATOR), sV: () => (OPEN_CURLY_BRACKET), t6: () => (SPACE), ur: () => (SINGLE_QUOTE), us: () => (SAFARI_CB_AFFINITY), uu: () => (PLUS), vr: () => (CSS_NOT_PSEUDO), vz: () => (GREATER_THAN), w1: () => (BACKTICK_QUOTE), wH: () => (AT_SIGN), wR: () => (TILDE), wU: () => (CLOSE_CURLY_BRACKET), wg: () => (EMPTY), wn: () => (TAB), x$: () => (ADG_SCRIPTLET_MASK), y0: () => (DOT), zW: () => (CSS_BLOCK_OPEN) }); /* * AGTree v4.2.1 (build date: Wed, 12 Aug 2026 01:31:02 GMT) * (c) 2026 Adguard Software Ltd. * Released under the MIT license * https://github.com/AdguardTeam/tsurlfilter/tree/master/packages/agtree#readme */ /** * @file Constant values used by all parts of the library. */ // TODO: remove unused constants // General /** * Empty string. */ const EMPTY = ''; const SPACE = ' '; const TAB = '\t'; const COLON = ':'; const COMMA = ','; const DOT = '.'; const SEMICOLON = ';'; const AMPERSAND = '&'; const ASTERISK = '*'; const AT_SIGN = '@'; const CARET = '^'; const DOLLAR_SIGN = '$'; const EQUALS = '='; const EXCLAMATION_MARK = '!'; const GREATER_THAN = '>'; const HASHMARK = '#'; const PIPE = '|'; const PLUS = '+'; const QUESTION_MARK = '?'; const SLASH = '/'; const TILDE = '~'; const UNDERSCORE = '_'; // Escape characters const BACKSLASH = '\\'; const ESCAPE_CHARACTER = BACKSLASH; // Newlines const CR = '\r'; const FF = '\f'; const LF = '\n'; const CRLF = CR + LF; const NEWLINE = (/* unused pure expression or super */ null && (LF)); // Quotes const BACKTICK_QUOTE = '`'; const DOUBLE_QUOTE = '"'; const SINGLE_QUOTE = '\''; // Brackets const OPEN_PARENTHESIS = '('; const CLOSE_PARENTHESIS = ')'; const OPEN_SQUARE_BRACKET = '['; const CLOSE_SQUARE_BRACKET = ']'; const OPEN_CURLY_BRACKET = '{'; const CLOSE_CURLY_BRACKET = '}'; // Letters const SMALL_LETTER_A = 'a'; const SMALL_LETTER_B = 'b'; const SMALL_LETTER_C = 'c'; const SMALL_LETTER_D = 'd'; const SMALL_LETTER_E = 'e'; const SMALL_LETTER_F = 'f'; const SMALL_LETTER_G = 'g'; const SMALL_LETTER_H = 'h'; const SMALL_LETTER_I = 'i'; const SMALL_LETTER_J = 'j'; const SMALL_LETTER_K = 'k'; const SMALL_LETTER_L = 'l'; const SMALL_LETTER_M = 'm'; const SMALL_LETTER_N = 'n'; const SMALL_LETTER_O = 'o'; const SMALL_LETTER_P = 'p'; const SMALL_LETTER_Q = 'q'; const SMALL_LETTER_R = 'r'; const SMALL_LETTER_S = 's'; const SMALL_LETTER_T = 't'; const SMALL_LETTER_U = 'u'; const SMALL_LETTER_V = 'v'; const SMALL_LETTER_W = 'w'; const SMALL_LETTER_X = 'x'; const SMALL_LETTER_Y = 'y'; const SMALL_LETTER_Z = 'z'; /** * Set of all small letters. */ const SMALL_LETTERS = new Set([ SMALL_LETTER_A, SMALL_LETTER_B, SMALL_LETTER_C, SMALL_LETTER_D, SMALL_LETTER_E, SMALL_LETTER_F, SMALL_LETTER_G, SMALL_LETTER_H, SMALL_LETTER_I, SMALL_LETTER_J, SMALL_LETTER_K, SMALL_LETTER_L, SMALL_LETTER_M, SMALL_LETTER_N, SMALL_LETTER_O, SMALL_LETTER_P, SMALL_LETTER_Q, SMALL_LETTER_R, SMALL_LETTER_S, SMALL_LETTER_T, SMALL_LETTER_U, SMALL_LETTER_V, SMALL_LETTER_W, SMALL_LETTER_X, SMALL_LETTER_Y, SMALL_LETTER_Z, ]); // Capital letters const CAPITAL_LETTER_A = 'A'; const CAPITAL_LETTER_B = 'B'; const CAPITAL_LETTER_C = 'C'; const CAPITAL_LETTER_D = 'D'; const CAPITAL_LETTER_E = 'E'; const CAPITAL_LETTER_F = 'F'; const CAPITAL_LETTER_G = 'G'; const CAPITAL_LETTER_H = 'H'; const CAPITAL_LETTER_I = 'I'; const CAPITAL_LETTER_J = 'J'; const CAPITAL_LETTER_K = 'K'; const CAPITAL_LETTER_L = 'L'; const CAPITAL_LETTER_M = 'M'; const CAPITAL_LETTER_N = 'N'; const CAPITAL_LETTER_O = 'O'; const CAPITAL_LETTER_P = 'P'; const CAPITAL_LETTER_Q = 'Q'; const CAPITAL_LETTER_R = 'R'; const CAPITAL_LETTER_S = 'S'; const CAPITAL_LETTER_T = 'T'; const CAPITAL_LETTER_U = 'U'; const CAPITAL_LETTER_V = 'V'; const CAPITAL_LETTER_W = 'W'; const CAPITAL_LETTER_X = 'X'; const CAPITAL_LETTER_Y = 'Y'; const CAPITAL_LETTER_Z = 'Z'; /** * Set of all capital letters. */ const CAPITAL_LETTERS = new Set([ CAPITAL_LETTER_A, CAPITAL_LETTER_B, CAPITAL_LETTER_C, CAPITAL_LETTER_D, CAPITAL_LETTER_E, CAPITAL_LETTER_F, CAPITAL_LETTER_G, CAPITAL_LETTER_H, CAPITAL_LETTER_I, CAPITAL_LETTER_J, CAPITAL_LETTER_K, CAPITAL_LETTER_L, CAPITAL_LETTER_M, CAPITAL_LETTER_N, CAPITAL_LETTER_O, CAPITAL_LETTER_P, CAPITAL_LETTER_Q, CAPITAL_LETTER_R, CAPITAL_LETTER_S, CAPITAL_LETTER_T, CAPITAL_LETTER_U, CAPITAL_LETTER_V, CAPITAL_LETTER_W, CAPITAL_LETTER_X, CAPITAL_LETTER_Y, CAPITAL_LETTER_Z, ]); // Numbers as strings const NUMBER_0 = '0'; const NUMBER_1 = '1'; const NUMBER_2 = '2'; const NUMBER_3 = '3'; const NUMBER_4 = '4'; const NUMBER_5 = '5'; const NUMBER_6 = '6'; const NUMBER_7 = '7'; const NUMBER_8 = '8'; const NUMBER_9 = '9'; /** * Set of all numbers as strings. */ const NUMBERS = new Set([ NUMBER_0, NUMBER_1, NUMBER_2, NUMBER_3, NUMBER_4, NUMBER_5, NUMBER_6, NUMBER_7, NUMBER_8, NUMBER_9, ]); const REGEX_MARKER = '/'; const ADG_SCRIPTLET_MASK = '//scriptlet'; const UBO_SCRIPTLET_MASK = '+js'; const UBO_SCRIPTLET_MASK_LEGACY = 'script:inject'; const UBO_HTML_MASK = '^'; const UBO_MATCHES_PATH_OPERATOR = 'matches-path'; const UBO_RESPONSEHEADER_FN = 'responseheader'; const ADG_PATH_MODIFIER = 'path'; const ADG_DOMAINS_MODIFIER = 'domain'; const ADG_APP_MODIFIER = 'app'; const ADG_URL_MODIFIER = 'url'; // Modifiers are separated by ",". For example: "script,domain=example.com" const MODIFIERS_SEPARATOR = ','; const MODIFIER_ASSIGN_OPERATOR = '='; const NEGATION_MARKER = '~'; /** * The wildcard symbol — `*`. */ const WILDCARD = ASTERISK; /** * Classic domain separator. * * @example * ```adblock * ! Domains are separated by ",": * example.com,~example.org##.ads * ``` */ const COMMA_DOMAIN_LIST_SEPARATOR = ','; /** * Modifier separator for $app, $denyallow, $domain, $method. * * @example * ```adblock * ! Domains are separated by "|": * ads.js^$script,domains=example.com|~example.org * ``` */ const PIPE_MODIFIER_SEPARATOR = '|'; const CSS_MEDIA_MARKER = '@media'; const CSS_NOT_PSEUDO = 'not'; const CSS_BLOCK_OPEN = '{'; const CSS_BLOCK_CLOSE = '}'; const HINT_MARKER = '!+'; const HINT_MARKER_LEN = HINT_MARKER.length; const NETWORK_RULE_EXCEPTION_MARKER = '@@'; const NETWORK_RULE_EXCEPTION_MARKER_LEN = NETWORK_RULE_EXCEPTION_MARKER.length; const NETWORK_RULE_SEPARATOR = '$'; const AGLINT_COMMAND_PREFIX = 'aglint'; const AGLINT_CONFIG_COMMENT_MARKER = '--'; const PREPROCESSOR_MARKER = '!#'; const PREPROCESSOR_MARKER_LEN = PREPROCESSOR_MARKER.length; const PREPROCESSOR_SEPARATOR = ' '; const SAFARI_CB_AFFINITY = 'safari_cb_affinity'; const IF = 'if'; const INCLUDE = 'include'; }, 77342(__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) { __webpack_require__.d(__webpack_exports__, { m: () => (CosmeticRuleSeparatorUtils) }); /* import */ var _nodes_index_js__rspack_import_1 = __webpack_require__(79864); /* import */ var _constants_js__rspack_import_0 = __webpack_require__(53097); /* * AGTree v4.2.1 (build date: Wed, 12 Aug 2026 01:31:02 GMT) * (c) 2026 Adguard Software Ltd. * Released under the MIT license * https://github.com/AdguardTeam/tsurlfilter/tree/master/packages/agtree#readme */ /** * @file Cosmetic rule separator finder and categorizer. */ /** * Utility class for cosmetic rule separators. */ class CosmeticRuleSeparatorUtils { /** * Checks whether the specified separator is an exception. * * @param separator Separator to check. * * @returns `true` if the separator is an exception, `false` otherwise. */ static isException(separator) { // Simply check the second character return separator[1] === _constants_js__rspack_import_0/* .AT_SIGN */.wH; } /** * Checks whether the specified separator is marks an Extended CSS cosmetic rule. * * @param separator Separator to check. * * @returns `true` if the separator is marks an Extended CSS cosmetic rule, `false` otherwise. */ static isExtendedCssMarker(separator) { return (separator === _nodes_index_js__rspack_import_1/* .CosmeticRuleSeparator.ExtendedElementHiding */.p5.ExtendedElementHiding || separator === _nodes_index_js__rspack_import_1/* .CosmeticRuleSeparator.ExtendedElementHidingException */.p5.ExtendedElementHidingException || separator === _nodes_index_js__rspack_import_1/* .CosmeticRuleSeparator.AdgExtendedCssInjection */.p5.AdgExtendedCssInjection || separator === _nodes_index_js__rspack_import_1/* .CosmeticRuleSeparator.AdgExtendedCssInjectionException */.p5.AdgExtendedCssInjectionException); } /** * Looks for the cosmetic rule separator in the rule. This is a simplified version that * masks the recursive function. * * @param rule Raw rule. * * @returns Separator result or null if no separator was found. */ static find(rule) { /** * Helper function to create results of the `find` method. * * @param start Start position. * @param separator Separator type. * * @returns Cosmetic rule separator node. */ // eslint-disable-next-line max-len function createResult(start, separator) { return { separator, start, end: start + separator.length, }; } for (let i = 0; i < rule.length; i += 1) { if (rule[i] === '#') { if (rule[i + 1] === '#' && rule[i - 1] !== _constants_js__rspack_import_0/* .SPACE */.t6) { // ## return createResult(i, _nodes_index_js__rspack_import_1/* .CosmeticRuleSeparator.ElementHiding */.p5.ElementHiding); } if (rule[i + 1] === '?' && rule[i + 2] === '#') { // #?# return createResult(i, _nodes_index_js__rspack_import_1/* .CosmeticRuleSeparator.ExtendedElementHiding */.p5.ExtendedElementHiding); } if (rule[i + 1] === '%' && rule[i + 2] === '#') { // #%# return createResult(i, _nodes_index_js__rspack_import_1/* .CosmeticRuleSeparator.AdgJsInjection */.p5.AdgJsInjection); } if (rule[i + 1] === '$') { if (rule[i + 2] === '#') { // #$# return createResult(i, _nodes_index_js__rspack_import_1/* .CosmeticRuleSeparator.AdgCssInjection */.p5.AdgCssInjection); } if (rule[i + 2] === '?' && rule[i + 3] === '#') { // #$?# return createResult(i, _nodes_index_js__rspack_import_1/* .CosmeticRuleSeparator.AdgExtendedCssInjection */.p5.AdgExtendedCssInjection); } } // Exceptions if (rule[i + 1] === '@') { if (rule[i + 2] === '#' && rule[i - 1] !== _constants_js__rspack_import_0/* .SPACE */.t6) { // #@# return createResult(i, _nodes_index_js__rspack_import_1/* .CosmeticRuleSeparator.ElementHidingException */.p5.ElementHidingException); } if (rule[i + 2] === '?' && rule[i + 3] === '#') { // #@?# return createResult(i, _nodes_index_js__rspack_import_1/* .CosmeticRuleSeparator.ExtendedElementHidingException */.p5.ExtendedElementHidingException); } if (rule[i + 2] === '%' && rule[i + 3] === '#') { // #@%# return createResult(i, _nodes_index_js__rspack_import_1/* .CosmeticRuleSeparator.AdgJsInjectionException */.p5.AdgJsInjectionException); } if (rule[i + 2] === '$') { if (rule[i + 3] === '#') { // #@$# return createResult(i, _nodes_index_js__rspack_import_1/* .CosmeticRuleSeparator.AdgCssInjectionException */.p5.AdgCssInjectionException); } if (rule[i + 3] === '?' && rule[i + 4] === '#') { // #@$?# return createResult(i, _nodes_index_js__rspack_import_1/* .CosmeticRuleSeparator.AdgExtendedCssInjectionException */.p5.AdgExtendedCssInjectionException); } } } } if (rule[i] === '$') { if (rule[i + 1] === '$') { // $$ return createResult(i, _nodes_index_js__rspack_import_1/* .CosmeticRuleSeparator.AdgHtmlFiltering */.p5.AdgHtmlFiltering); } if (rule[i + 1] === '@' && rule[i + 2] === '$') { // $@$ return createResult(i, _nodes_index_js__rspack_import_1/* .CosmeticRuleSeparator.AdgHtmlFilteringException */.p5.AdgHtmlFilteringException); } } } return null; } } }, 41666(__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) { __webpack_require__.d(__webpack_exports__, { o: () => (deepFreeze) }); /* * AGTree v4.2.1 (build date: Wed, 12 Aug 2026 01:31:02 GMT) * (c) 2026 Adguard Software Ltd. * Released under the MIT license * https://github.com/AdguardTeam/tsurlfilter/tree/master/packages/agtree#readme */ /** * Simple deep freeze implementation. * It freezes the object and all its properties recursively. * * @template T Type of the object to freeze. * * @see {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/freeze#deep_freezing} * * @param object Object to freeze. * * @returns Frozen object. */ const deepFreeze = (object) => { // Retrieve the property names defined on object const propNames = Reflect.ownKeys(object); // Freeze properties before freezing self for (const name of propNames) { const value = object[name]; if ((value && typeof value === 'object') || typeof value === 'function') { deepFreeze(value); } } return Object.freeze(object); }; }, 89934(__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) { __webpack_require__.d(__webpack_exports__, { Aw: () => (DomainUtils) }); /* import */ var tldts__rspack_import_0 = __webpack_require__(86136); /* import */ var _constants_js__rspack_import_1 = __webpack_require__(53097); /* * AGTree v4.2.1 (build date: Wed, 12 Aug 2026 01:31:02 GMT) * (c) 2026 Adguard Software Ltd. * Released under the MIT license * https://github.com/AdguardTeam/tsurlfilter/tree/master/packages/agtree#readme */ /** * @file Utility functions for domain and hostname validation. */ /** * Marker for a wildcard top-level domain — `.*`. * * @example * `example.*` — matches with any TLD, e.g. `example.org`, `example.com`, etc. */ const WILDCARD_TLD = _constants_js__rspack_import_1/* .DOT */.y0 + _constants_js__rspack_import_1/* .WILDCARD */.bs; /** * Marker for a wildcard subdomain — `*.`. * * @example * `*.example.org` — matches with any subdomain, e.g. `foo.example.org` or `bar.example.org` */ const WILDCARD_SUBDOMAIN = _constants_js__rspack_import_1/* .WILDCARD */.bs + _constants_js__rspack_import_1/* .DOT */.y0; /** * Utility functions for domain and hostname validation. */ class DomainUtils { /** * Check if the input is a valid domain or hostname. * * @param domain Domain to check. * * @returns `true` if the domain is valid, `false` otherwise. */ static isValidDomainOrHostname(domain) { let domainToCheck = domain; // Wildcard-only domain, typically a generic rule if (domainToCheck === _constants_js__rspack_import_1/* .WILDCARD */.bs) { return true; } // https://adguard.com/kb/general/ad-filtering/create-own-filters/#wildcard-for-tld if (domainToCheck.endsWith(WILDCARD_TLD)) { // Remove the wildcard TLD domainToCheck = domainToCheck.substring(0, domainToCheck.length - WILDCARD_TLD.length); } if (domainToCheck.startsWith(WILDCARD_SUBDOMAIN)) { // Remove the wildcard subdomain domainToCheck = domainToCheck.substring(WILDCARD_SUBDOMAIN.length); } // Parse the domain with tldts const tldtsResult = (0,tldts__rspack_import_0/* .parse */.qg)(domainToCheck); // Check if the domain is valid return domainToCheck === tldtsResult.domain || domainToCheck === tldtsResult.hostname; } } }, 68999(__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) { __webpack_require__.d(__webpack_exports__, { Qj: () => (QuoteUtils), XA: () => (QuoteType), iO: () => (QUOTE_SET) }); /* import */ var _constants_js__rspack_import_0 = __webpack_require__(53097); /* * AGTree v4.2.1 (build date: Wed, 12 Aug 2026 01:31:02 GMT) * (c) 2026 Adguard Software Ltd. * Released under the MIT license * https://github.com/AdguardTeam/tsurlfilter/tree/master/packages/agtree#readme */ /** * @file Utility functions for working with quotes. */ /** * Set of all possible quote characters supported by the library. */ const QUOTE_SET = new Set([ _constants_js__rspack_import_0/* .SINGLE_QUOTE */.ur, _constants_js__rspack_import_0/* .DOUBLE_QUOTE */.fi, _constants_js__rspack_import_0/* .BACKTICK_QUOTE */.w1, ]); /** * Possible quote types for scriptlet parameters. */ const QuoteType = { /** * No quotes at all. */ None: 'none', /** * Single quotes (`'`). */ Single: 'single', /** * Double quotes (`"`). */ Double: 'double', /** * Backtick quotes (`` ` ``). */ Backtick: 'backtick', }; /** * Utility functions for working with quotes. */ class QuoteUtils { /** * Escape all unescaped occurrences of the character. * * @param string String to escape. * @param char Character to escape. * * @returns Escaped string. */ static escapeUnescapedOccurrences(string, char) { let result = _constants_js__rspack_import_0/* .EMPTY */.wg; for (let i = 0; i < string.length; i += 1) { if (string[i] === char && (i === 0 || string[i - 1] !== _constants_js__rspack_import_0/* .ESCAPE_CHARACTER */.Kx)) { result += _constants_js__rspack_import_0/* .ESCAPE_CHARACTER */.Kx; } result += string[i]; } return result; } /** * Unescape all single escaped occurrences of the character. * * @param string String to unescape. * @param char Character to unescape. * * @returns Unescaped string. */ static unescapeSingleEscapedOccurrences(string, char) { let result = _constants_js__rspack_import_0/* .EMPTY */.wg; for (let i = 0; i < string.length; i += 1) { if (string[i] === char && string[i - 1] === _constants_js__rspack_import_0/* .ESCAPE_CHARACTER */.Kx && (i === 1 || string[i - 2] !== _constants_js__rspack_import_0/* .ESCAPE_CHARACTER */.Kx)) { result = result.slice(0, -1); } result += string[i]; } return result; } /** * Get quote type of the string. * * @param string String to check. * * @returns Quote type of the string. */ static getStringQuoteType(string) { // Don't check 1-character strings to avoid false positives if (string.length > 1) { if (string.startsWith(_constants_js__rspack_import_0/* .SINGLE_QUOTE */.ur) && string.endsWith(_constants_js__rspack_import_0/* .SINGLE_QUOTE */.ur)) { return QuoteType.Single; } if (string.startsWith(_constants_js__rspack_import_0/* .DOUBLE_QUOTE */.fi) && string.endsWith(_constants_js__rspack_import_0/* .DOUBLE_QUOTE */.fi)) { return QuoteType.Double; } if (string.startsWith(_constants_js__rspack_import_0/* .BACKTICK_QUOTE */.w1) && string.endsWith(_constants_js__rspack_import_0/* .BACKTICK_QUOTE */.w1)) { return QuoteType.Backtick; } } return QuoteType.None; } /** * Set quote type of the string. * * @param string String to set quote type of. * @param quoteType Quote type to set. * * @returns String with the specified quote type. */ static setStringQuoteType(string, quoteType) { const actualQuoteType = QuoteUtils.getStringQuoteType(string); switch (quoteType) { case QuoteType.None: if (actualQuoteType === QuoteType.Single) { return QuoteUtils.escapeUnescapedOccurrences(string.slice(1, -1), _constants_js__rspack_import_0/* .SINGLE_QUOTE */.ur); } if (actualQuoteType === QuoteType.Double) { return QuoteUtils.escapeUnescapedOccurrences(string.slice(1, -1), _constants_js__rspack_import_0/* .DOUBLE_QUOTE */.fi); } if (actualQuoteType === QuoteType.Backtick) { return QuoteUtils.escapeUnescapedOccurrences(string.slice(1, -1), _constants_js__rspack_import_0/* .BACKTICK_QUOTE */.w1); } return string; case QuoteType.Single: if (actualQuoteType === QuoteType.None) { return _constants_js__rspack_import_0/* .SINGLE_QUOTE */.ur + QuoteUtils.escapeUnescapedOccurrences(string, _constants_js__rspack_import_0/* .SINGLE_QUOTE */.ur) + _constants_js__rspack_import_0/* .SINGLE_QUOTE */.ur; } if (actualQuoteType === QuoteType.Double) { return _constants_js__rspack_import_0/* .SINGLE_QUOTE */.ur + QuoteUtils.escapeUnescapedOccurrences(QuoteUtils.unescapeSingleEscapedOccurrences(string.slice(1, -1), _constants_js__rspack_import_0/* .DOUBLE_QUOTE */.fi), _constants_js__rspack_import_0/* .SINGLE_QUOTE */.ur) + _constants_js__rspack_import_0/* .SINGLE_QUOTE */.ur; } if (actualQuoteType === QuoteType.Backtick) { return _constants_js__rspack_import_0/* .SINGLE_QUOTE */.ur + QuoteUtils.escapeUnescapedOccurrences(QuoteUtils.unescapeSingleEscapedOccurrences(string.slice(1, -1), _constants_js__rspack_import_0/* .BACKTICK_QUOTE */.w1), _constants_js__rspack_import_0/* .SINGLE_QUOTE */.ur) + _constants_js__rspack_import_0/* .SINGLE_QUOTE */.ur; } return string; case QuoteType.Double: if (actualQuoteType === QuoteType.None) { return _constants_js__rspack_import_0/* .DOUBLE_QUOTE */.fi + QuoteUtils.escapeUnescapedOccurrences(string, _constants_js__rspack_import_0/* .DOUBLE_QUOTE */.fi) + _constants_js__rspack_import_0/* .DOUBLE_QUOTE */.fi; } if (actualQuoteType !== QuoteType.Double) { // eslint-disable-next-line max-len return _constants_js__rspack_import_0/* .DOUBLE_QUOTE */.fi + QuoteUtils.escapeUnescapedOccurrences(QuoteUtils.unescapeSingleEscapedOccurrences(string.slice(1, -1), _constants_js__rspack_import_0/* .SINGLE_QUOTE */.ur), _constants_js__rspack_import_0/* .DOUBLE_QUOTE */.fi) + _constants_js__rspack_import_0/* .DOUBLE_QUOTE */.fi; } return string; case QuoteType.Backtick: if (actualQuoteType === QuoteType.None) { // eslint-disable-next-line max-len return _constants_js__rspack_import_0/* .BACKTICK_QUOTE */.w1 + QuoteUtils.escapeUnescapedOccurrences(string, _constants_js__rspack_import_0/* .BACKTICK_QUOTE */.w1) + _constants_js__rspack_import_0/* .BACKTICK_QUOTE */.w1; } if (actualQuoteType !== QuoteType.Backtick) { // eslint-disable-next-line max-len return _constants_js__rspack_import_0/* .BACKTICK_QUOTE */.w1 + QuoteUtils.escapeUnescapedOccurrences(QuoteUtils.unescapeSingleEscapedOccurrences(string.slice(1, -1), _constants_js__rspack_import_0/* .SINGLE_QUOTE */.ur), _constants_js__rspack_import_0/* .BACKTICK_QUOTE */.w1) + _constants_js__rspack_import_0/* .BACKTICK_QUOTE */.w1; } return string; default: return string; } } /** * Removes bounding quotes from a string, if any. * * @param string Input string. * * @returns String without quotes. */ static removeQuotes(string) { if ( // We should check for string length to avoid false positives string.length > 1 && (string[0] === _constants_js__rspack_import_0/* .SINGLE_QUOTE */.ur || string[0] === _constants_js__rspack_import_0/* .DOUBLE_QUOTE */.fi || string[0] === _constants_js__rspack_import_0/* .BACKTICK_QUOTE */.w1) && string[0] === string[string.length - 1]) { return string.slice(1, -1); } return string; } /** * Removes bounding quotes from a string, if any, and unescapes the escaped quotes, * like transforming `'abc\'def'` to `abc'def`. * * @param string Input string. * * @returns String without quotes. */ static removeQuotesAndUnescape(string) { const quoteType = QuoteUtils.getStringQuoteType(string); switch (quoteType) { case QuoteType.Single: return QuoteUtils.unescapeSingleEscapedOccurrences(string.slice(1, -1), _constants_js__rspack_import_0/* .SINGLE_QUOTE */.ur); case QuoteType.Double: return QuoteUtils.unescapeSingleEscapedOccurrences(string.slice(1, -1), _constants_js__rspack_import_0/* .DOUBLE_QUOTE */.fi); case QuoteType.Backtick: return QuoteUtils.unescapeSingleEscapedOccurrences(string.slice(1, -1), _constants_js__rspack_import_0/* .BACKTICK_QUOTE */.w1); default: return string; } } /** * Wraps given `strings` with `quote` (defaults to single quote `'`) * and joins them with `separator` (defaults to comma+space `, `). * * @param strings Strings to quote and join. * @param quoteType Quote to use. * @param separator Separator to use. * * @returns String with joined items. * * @example * ['abc', 'def']: strings[] -> "'abc', 'def'": string */ static quoteAndJoinStrings(strings, quoteType = QuoteType.Single, separator = `${_constants_js__rspack_import_0/* .COMMA */.KE}${_constants_js__rspack_import_0/* .SPACE */.t6}`) { return strings .map((s) => QuoteUtils.setStringQuoteType(s, quoteType)) .join(separator); } /** * Convert `""` to `\"` within strings inside of attribute selectors, * because it is not compatible with the standard CSS syntax. * * @see {@link https://kb.adguard.com/en/general/how-to-create-your-own-ad-filters#tag-content} * @see {@link https://kb.adguard.com/en/general/how-to-create-your-own-ad-filters#wildcard} * * @param selector CSS selector string. * * @returns Escaped CSS selector. * * @example * ```ts * QuoteUtils.escapeAttributeDoubleQuotes('[attr="value with "" quotes"]'); * QuoteUtils.escapeAttributeDoubleQuotes('div[attr="value with "" quotes"] > span'); * ``` * * @note In the legacy syntax, `""` is used to escape double quotes, but it cannot be used * in the standard CSS syntax, so we use conversion functions to handle this. * @note This function is intended to be used on whole attribute selector or whole selector strings. */ static escapeAttributeDoubleQuotes(selector) { const nestingBlockPairs = new Map([ [_constants_js__rspack_import_0/* .OPEN_PARENTHESIS */.Cx, _constants_js__rspack_import_0/* .CLOSE_PARENTHESIS */.s1], [_constants_js__rspack_import_0/* .OPEN_SQUARE_BRACKET */.cU, _constants_js__rspack_import_0/* .CLOSE_SQUARE_BRACKET */.A1], [_constants_js__rspack_import_0/* .SINGLE_QUOTE */.ur, _constants_js__rspack_import_0/* .SINGLE_QUOTE */.ur], [_constants_js__rspack_import_0/* .DOUBLE_QUOTE */.fi, _constants_js__rspack_import_0/* .DOUBLE_QUOTE */.fi], [_constants_js__rspack_import_0/* .BACKTICK_QUOTE */.w1, _constants_js__rspack_import_0/* .BACKTICK_QUOTE */.w1], ]); const nestingBlockStack = []; const buffer = []; for (let i = 0; i < selector.length; i += 1) { const char = selector[i]; // Check if we are inside of an attribute selector's value if ( // nesting will be 2 levels deep if we are inside of attribute selector's value nestingBlockStack.length === 2 // and the outer block is an attribute selector && nestingBlockStack[0] === _constants_js__rspack_import_0/* .CLOSE_SQUARE_BRACKET */.A1 // and the inner block is a double quote && nestingBlockStack[1] === _constants_js__rspack_import_0/* .DOUBLE_QUOTE */.fi) { // We found `""` inside of attribute selector's value if (char === _constants_js__rspack_import_0/* .DOUBLE_QUOTE */.fi && selector[i + 1] === _constants_js__rspack_import_0/* .DOUBLE_QUOTE */.fi) { // Convert `""` to `\"` buffer.push(_constants_js__rspack_import_0/* .ESCAPE_CHARACTER */.Kx); buffer.push(_constants_js__rspack_import_0/* .DOUBLE_QUOTE */.fi); // Skip the next double quote i += 1; continue; } // Normal character inside of attribute selector's value buffer.push(char); continue; } // Handle entering nesting blocks if (nestingBlockPairs.has(char) && selector[i - 1] !== _constants_js__rspack_import_0/* .ESCAPE_CHARACTER */.Kx) { nestingBlockStack.push(nestingBlockPairs.get(char)); buffer.push(char); continue; } // Handle exiting nesting blocks if (nestingBlockStack.length > 0 && char === nestingBlockStack[nestingBlockStack.length - 1] && selector[i - 1] !== _constants_js__rspack_import_0/* .ESCAPE_CHARACTER */.Kx) { nestingBlockStack.pop(); buffer.push(char); continue; } // Normal character buffer.push(char); } return buffer.join(_constants_js__rspack_import_0/* .EMPTY */.wg); } /** * Convert escaped double quotes `\"` to `""` within strings inside of attribute selectors, * because it is not compatible with the standard CSS syntax. * * @see {@link https://kb.adguard.com/en/general/how-to-create-your-own-ad-filters#tag-content} * @see {@link https://kb.adguard.com/en/general/how-to-create-your-own-ad-filters#wildcard} * * @param selector CSS selector string. * * @returns Unescaped CSS selector. * * @example * ```ts * QuoteUtils.unescapeAttributeDoubleQuotes('[attr="value with \\" quotes"]'); * QuoteUtils.unescapeAttributeDoubleQuotes('div[attr="value with \\" quotes"] > span'); * ``` * * @note In the legacy syntax, `""` is used to escape double quotes, but it cannot be used * in the standard CSS syntax, so we use conversion functions to handle this. * @note This function is intended to be used on whole attribute selector or whole selector strings. */ static unescapeAttributeDoubleQuotes(selector) { const nestingBlockPairs = new Map([ [_constants_js__rspack_import_0/* .OPEN_PARENTHESIS */.Cx, _constants_js__rspack_import_0/* .CLOSE_PARENTHESIS */.s1], [_constants_js__rspack_import_0/* .OPEN_SQUARE_BRACKET */.cU, _constants_js__rspack_import_0/* .CLOSE_SQUARE_BRACKET */.A1], [_constants_js__rspack_import_0/* .SINGLE_QUOTE */.ur, _constants_js__rspack_import_0/* .SINGLE_QUOTE */.ur], [_constants_js__rspack_import_0/* .DOUBLE_QUOTE */.fi, _constants_js__rspack_import_0/* .DOUBLE_QUOTE */.fi], [_constants_js__rspack_import_0/* .BACKTICK_QUOTE */.w1, _constants_js__rspack_import_0/* .BACKTICK_QUOTE */.w1], ]); const nestingBlockStack = []; const buffer = []; for (let i = 0; i < selector.length; i += 1) { const char = selector[i]; // Check if we are inside of an attribute selector's value if ( // nesting will be 2 levels deep if we are inside of attribute selector's value nestingBlockStack.length === 2 // and the outer block is an attribute selector && nestingBlockStack[0] === _constants_js__rspack_import_0/* .CLOSE_SQUARE_BRACKET */.A1 // and the inner block is a double quote && nestingBlockStack[1] === _constants_js__rspack_import_0/* .DOUBLE_QUOTE */.fi) { // We found `\"` inside of attribute selector's value if (char === _constants_js__rspack_import_0/* .ESCAPE_CHARACTER */.Kx && selector[i + 1] === _constants_js__rspack_import_0/* .DOUBLE_QUOTE */.fi) { // Convert `\"` to `""` buffer.push(_constants_js__rspack_import_0/* .DOUBLE_QUOTE */.fi); buffer.push(_constants_js__rspack_import_0/* .DOUBLE_QUOTE */.fi); // Skip the next double quote i += 1; continue; } // Normal character inside of attribute selector's value buffer.push(char); continue; } // Handle entering nesting blocks if (nestingBlockPairs.has(char) && selector[i - 1] !== _constants_js__rspack_import_0/* .ESCAPE_CHARACTER */.Kx) { nestingBlockStack.push(nestingBlockPairs.get(char)); buffer.push(char); continue; } // Handle exiting nesting blocks if (nestingBlockStack.length > 0 && char === nestingBlockStack[nestingBlockStack.length - 1] && selector[i - 1] !== _constants_js__rspack_import_0/* .ESCAPE_CHARACTER */.Kx) { nestingBlockStack.pop(); buffer.push(char); continue; } // Normal character buffer.push(char); } return buffer.join(_constants_js__rspack_import_0/* .EMPTY */.wg); } } }, 64539(__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) { __webpack_require__.d(__webpack_exports__, { Cg: () => (ADBLOCK_URL_START), Fx: () => (ADBLOCK_URL_SEPARATOR), Lp: () => (RegExpUtils) }); /* import */ var glob_to_regexp__rspack_import_0 = __webpack_require__(68874); /* import */ var _constants_js__rspack_import_1 = __webpack_require__(53097); /* * AGTree v4.2.1 (build date: Wed, 12 Aug 2026 01:31:02 GMT) * (c) 2026 Adguard Software Ltd. * Released under the MIT license * https://github.com/AdguardTeam/tsurlfilter/tree/master/packages/agtree#readme */ /** * @file Regular expression utilities. */ // Special RegExp constants const REGEX_START = _constants_js__rspack_import_1/* .CARET */.cP; // '^' const REGEX_END = _constants_js__rspack_import_1/* .DOLLAR_SIGN */.nj; // '$' const REGEX_ANY_CHARACTERS = _constants_js__rspack_import_1/* .DOT */.y0 + _constants_js__rspack_import_1/* .ASTERISK */.Ln; // '.*' // Special adblock pattern symbols and their RegExp equivalents const ADBLOCK_URL_START = _constants_js__rspack_import_1/* .PIPE */.L5 + _constants_js__rspack_import_1/* .PIPE */.L5; // '||' const ADBLOCK_URL_START_REGEX = '^(http|https|ws|wss)://([a-z0-9-_.]+\\.)?'; const ADBLOCK_URL_SEPARATOR = _constants_js__rspack_import_1/* .CARET */.cP; // '^' const ADBLOCK_URL_SEPARATOR_REGEX = '([^ a-zA-Z0-9.%_-]|$)'; const ADBLOCK_WILDCARD = _constants_js__rspack_import_1/* .ASTERISK */.Ln; // '*' const ADBLOCK_WILDCARD_REGEX = REGEX_ANY_CHARACTERS; // Negation wrapper for RegExp patterns const REGEX_NEGATION_PREFIX = '^((?!'; const REGEX_NEGATION_SUFFIX = ').)*$'; /** * Special RegExp symbols. * * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions#special-escape */ const SPECIAL_REGEX_SYMBOLS = new Set([ _constants_js__rspack_import_1/* .ASTERISK */.Ln, _constants_js__rspack_import_1/* .CARET */.cP, _constants_js__rspack_import_1/* .CLOSE_CURLY_BRACKET */.wU, _constants_js__rspack_import_1/* .CLOSE_PARENTHESIS */.s1, _constants_js__rspack_import_1/* .CLOSE_SQUARE_BRACKET */.A1, _constants_js__rspack_import_1/* .DOLLAR_SIGN */.nj, _constants_js__rspack_import_1/* .DOT */.y0, _constants_js__rspack_import_1/* .ESCAPE_CHARACTER */.Kx, _constants_js__rspack_import_1/* .OPEN_CURLY_BRACKET */.sV, _constants_js__rspack_import_1/* .OPEN_PARENTHESIS */.Cx, _constants_js__rspack_import_1/* .OPEN_SQUARE_BRACKET */.cU, _constants_js__rspack_import_1/* .PIPE */.L5, _constants_js__rspack_import_1/* .PLUS */.uu, _constants_js__rspack_import_1/* .QUESTION_MARK */.Nb, _constants_js__rspack_import_1/* .SLASH */.o, ]); /** * Utility functions for working with RegExp patterns. */ class RegExpUtils { /** * Checks whether a string possibly is a RegExp pattern. * Flags are not supported. * * Note: it does not perform a full validation of the pattern, * it just checks if the string starts and ends with a slash. * * @param pattern Pattern to check. * * @returns `true` if the string is a RegExp pattern, `false` otherwise. */ static isRegexPattern(pattern) { const trimmedPattern = pattern.trim(); // Avoid false positives return trimmedPattern.length > _constants_js__rspack_import_1/* .REGEX_MARKER.length */.Vb.length * 2 && trimmedPattern.startsWith(_constants_js__rspack_import_1/* .REGEX_MARKER */.Vb) && trimmedPattern.endsWith(_constants_js__rspack_import_1/* .REGEX_MARKER */.Vb) && trimmedPattern[_constants_js__rspack_import_1/* .REGEX_MARKER.length */.Vb.length - 2] !== _constants_js__rspack_import_1/* .ESCAPE_CHARACTER */.Kx; } /** * Checks whether a string is a negated RegExp pattern. * * @param pattern Pattern to check. * * @returns `true` if the string is a negated RegExp pattern, `false` otherwise. */ static isNegatedRegexPattern(pattern) { if (pattern.startsWith(_constants_js__rspack_import_1/* .REGEX_MARKER */.Vb) && pattern.endsWith(_constants_js__rspack_import_1/* .REGEX_MARKER */.Vb)) { const innerPattern = pattern.slice(_constants_js__rspack_import_1/* .REGEX_MARKER.length */.Vb.length, pattern.length - _constants_js__rspack_import_1/* .REGEX_MARKER.length */.Vb.length); return innerPattern.startsWith(REGEX_NEGATION_PREFIX) && innerPattern.endsWith(REGEX_NEGATION_SUFFIX); } return pattern.startsWith(REGEX_NEGATION_PREFIX) && pattern.endsWith(REGEX_NEGATION_SUFFIX); } /** * Removes negation from a RegExp pattern. * * @param pattern RegExp pattern to remove negation from. * * @returns RegExp pattern without negation. */ static removeNegationFromRegexPattern(pattern) { let result = pattern.trim(); const slashes = RegExpUtils.isRegexPattern(result); if (slashes) { result = result.substring(_constants_js__rspack_import_1/* .REGEX_MARKER.length */.Vb.length, result.length - _constants_js__rspack_import_1/* .REGEX_MARKER.length */.Vb.length); } if (result.startsWith(REGEX_NEGATION_PREFIX) && result.endsWith(REGEX_NEGATION_SUFFIX)) { result = result.substring(REGEX_NEGATION_PREFIX.length, result.length - REGEX_NEGATION_SUFFIX.length); } return slashes ? `${_constants_js__rspack_import_1/* .REGEX_MARKER */.Vb}${result}${_constants_js__rspack_import_1/* .REGEX_MARKER */.Vb}` : result; } /** * Negates a RegExp pattern. Technically, this method wraps the pattern in `^((?!` and `).)*$`. * * RegExp modifiers are not supported. * * @param pattern Pattern to negate (can be wrapped in slashes or not). * * @returns Negated RegExp pattern. */ static negateRegexPattern(pattern) { let result = pattern.trim(); let slashes = false; // Remove the leading and trailing slashes (/) if (RegExpUtils.isRegexPattern(result)) { result = result.substring(_constants_js__rspack_import_1/* .REGEX_MARKER.length */.Vb.length, result.length - _constants_js__rspack_import_1/* .REGEX_MARKER.length */.Vb.length); slashes = true; } // Only negate the pattern if it's not already negated if (!(result.startsWith(REGEX_NEGATION_PREFIX) && result.endsWith(REGEX_NEGATION_SUFFIX))) { // Remove leading caret (^) if (result.startsWith(REGEX_START)) { result = result.substring(REGEX_START.length); } // Remove trailing dollar sign ($) if (result.endsWith(REGEX_END)) { result = result.substring(0, result.length - REGEX_END.length); } // Wrap the pattern in the negation result = `${REGEX_NEGATION_PREFIX}${result}${REGEX_NEGATION_SUFFIX}`; } // Add the leading and trailing slashes back if they were there if (slashes) { result = `${_constants_js__rspack_import_1/* .REGEX_MARKER */.Vb}${result}${_constants_js__rspack_import_1/* .REGEX_MARKER */.Vb}`; } return result; } /** * Ensures that a pattern is wrapped in slashes. * * @param pattern Pattern to ensure slashes for. * * @returns Pattern with slashes. */ static ensureSlashes(pattern) { let result = pattern; if (!result.startsWith(_constants_js__rspack_import_1/* .REGEX_MARKER */.Vb)) { result = `${_constants_js__rspack_import_1/* .REGEX_MARKER */.Vb}${result}`; } if (!result.endsWith(_constants_js__rspack_import_1/* .REGEX_MARKER */.Vb)) { result += _constants_js__rspack_import_1/* .REGEX_MARKER */.Vb; } return result; } /** * Converts a basic adblock rule pattern to a RegExp pattern. Based on * https://github.com/AdguardTeam/tsurlfilter/blob/9b26e0b4a0e30b87690bc60f7cf377d112c3085c/packages/tsurlfilter/src/rules/simple-regex.ts#L219. * * @see {@link https://kb.adguard.com/en/general/how-to-create-your-own-ad-filters#basic-rules} * * @param pattern Pattern to convert. * * @returns RegExp equivalent of the pattern. */ static patternToRegexp(pattern) { const trimmed = pattern.trim(); // Return regex for any character sequence if the pattern is just |, ||, * or empty if (trimmed === ADBLOCK_URL_START || trimmed === _constants_js__rspack_import_1/* .PIPE */.L5 || trimmed === ADBLOCK_WILDCARD || trimmed === _constants_js__rspack_import_1/* .EMPTY */.wg) { return REGEX_ANY_CHARACTERS; } // If the pattern is already a RegExp, just return it, but remove the leading and trailing slashes if (RegExpUtils.isRegexPattern(pattern)) { return pattern.substring(_constants_js__rspack_import_1/* .REGEX_MARKER.length */.Vb.length, pattern.length - _constants_js__rspack_import_1/* .REGEX_MARKER.length */.Vb.length); } let result = _constants_js__rspack_import_1/* .EMPTY */.wg; let offset = 0; let len = trimmed.length; // Handle leading pipes if (trimmed[0] === _constants_js__rspack_import_1/* .PIPE */.L5) { if (trimmed[1] === _constants_js__rspack_import_1/* .PIPE */.L5) { // Replace adblock url start (||) with its RegExp equivalent result += ADBLOCK_URL_START_REGEX; offset = ADBLOCK_URL_START.length; } else { // Replace single pipe (|) with the RegExp start symbol (^) result += REGEX_START; offset = REGEX_START.length; } } // Handle trailing pipes let trailingPipe = false; if (trimmed.endsWith(_constants_js__rspack_import_1/* .PIPE */.L5)) { trailingPipe = true; len -= _constants_js__rspack_import_1/* .PIPE.length */.L5.length; } // Handle the rest of the pattern, if any for (; offset < len; offset += 1) { if (trimmed[offset] === ADBLOCK_WILDCARD) { // Replace adblock wildcard (*) with its RegExp equivalent result += ADBLOCK_WILDCARD_REGEX; } else if (trimmed[offset] === ADBLOCK_URL_SEPARATOR) { // Replace adblock url separator (^) with its RegExp equivalent result += ADBLOCK_URL_SEPARATOR_REGEX; } else if (SPECIAL_REGEX_SYMBOLS.has(trimmed[offset])) { // Escape special RegExp symbols (we handled pipe (|) and asterisk (*) already) result += _constants_js__rspack_import_1/* .ESCAPE_CHARACTER */.Kx + trimmed[offset]; } else { // Just add any other character result += trimmed[offset]; } } // Handle trailing pipes if (trailingPipe) { // Replace trailing pipe (|) with the RegExp end symbol ($) result += REGEX_END; } return result; } /** * Creates a length-matching regular expression string: /^(?=.{min,max}$).*\/s * Where: * - (?=.{min,max}$) is a lookahead that ensures the string length is between min and max * - .* matches any character (including newlines, due to the 's' flag). * * @param min Minimum length or `null` for no minimum (default to `0`). * @param max Maximum length or `null` for no maximum (default to no maximum). * * @returns Length-matching regular expression string. */ static getLengthRegexp(min, max) { return `/^(?=.{${min ?? 0},${max ?? ''}}$).*/s`; } /** * Converts a glob pattern to a RegExp string with slashes and 's' flag. * * @param glob Glob pattern to convert. * * @returns RegExp string. * * @example * // Returns '/^foo.*bar$/s' * RegExpUtils.globToRegExp('foo*bar'); */ static globToRegExp(glob) { return `${_constants_js__rspack_import_1/* .REGEX_MARKER */.Vb + glob_to_regexp__rspack_import_0(glob).source + _constants_js__rspack_import_1/* .REGEX_MARKER */.Vb}s`; } } }, 16875(__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) { __webpack_require__.d(__webpack_exports__, { $x: () => (StringUtils) }); /* import */ var _constants_js__rspack_import_0 = __webpack_require__(53097); /* * AGTree v4.2.1 (build date: Wed, 12 Aug 2026 01:31:02 GMT) * (c) 2026 Adguard Software Ltd. * Released under the MIT license * https://github.com/AdguardTeam/tsurlfilter/tree/master/packages/agtree#readme */ /** * @file Utility functions for string manipulation. */ const SINGLE_QUOTE_MARKER = "'"; const DOUBLE_QUOTE_MARKER = '"'; /** * Utility functions for string manipulation. */ class StringUtils { /** * Finds the first occurrence of a character that: * - isn't preceded by an escape character. * * @param pattern Source pattern. * @param searchedCharacter Searched character. * @param start Start index. * @param escapeCharacter Escape character, \ by default. * @param end End index (excluded). * * @returns Index or -1 if the character not found. */ static findNextUnescapedCharacter(pattern, searchedCharacter, start = 0, escapeCharacter = _constants_js__rspack_import_0/* .ESCAPE_CHARACTER */.Kx, end = pattern.length) { for (let i = start; i < end; i += 1) { // The searched character cannot be preceded by an escape if (pattern[i] === searchedCharacter && pattern[i - 1] !== escapeCharacter) { return i; } } return -1; } /** * Finds the first occurrence in backward direction of a character that isn't preceded by an escape character. * * @param pattern Source pattern. * @param searchedCharacter Searched character. * @param start Start index. * @param escapeCharacter Escape character, \ by default. * @param end End index (Included). * * @returns Index or -1 if the character not found. */ static findNextUnescapedCharacterBackwards(pattern, searchedCharacter, start = pattern.length - 1, escapeCharacter = _constants_js__rspack_import_0/* .ESCAPE_CHARACTER */.Kx, end = 0) { for (let i = start; i >= end; i -= 1) { // The searched character cannot be preceded by an escape if (pattern[i] === searchedCharacter && pattern[i - 1] !== escapeCharacter) { return i; } } return -1; } /** * Finds the last occurrence of a character that: * - isn't preceded by an escape character. * * @param pattern Source pattern. * @param searchedCharacter Searched character. * @param escapeCharacter Escape character, \ by default. * * @returns Index or -1 if the character not found. */ static findLastUnescapedCharacter(pattern, searchedCharacter, escapeCharacter = _constants_js__rspack_import_0/* .ESCAPE_CHARACTER */.Kx) { for (let i = pattern.length - 1; i >= 0; i -= 1) { // The searched character cannot be preceded by an escape if (pattern[i] === searchedCharacter && pattern[i - 1] !== escapeCharacter) { return i; } } return -1; } /** * Finds the next occurrence of a character that: * - isn't preceded by an escape character * - isn't followed by the specified character. * * @param pattern Source pattern. * @param start Start index. * @param searchedCharacter Searched character. * @param notFollowedBy Searched character not followed by this character. * @param escapeCharacter Escape character, \ by default. * * @returns Index or -1 if the character not found. */ static findNextUnescapedCharacterThatNotFollowedBy(pattern, start, searchedCharacter, notFollowedBy, escapeCharacter = _constants_js__rspack_import_0/* .ESCAPE_CHARACTER */.Kx) { for (let i = start; i < pattern.length; i += 1) { // The searched character cannot be preceded by an escape if (pattern[i] === searchedCharacter && pattern[i + 1] !== notFollowedBy && pattern[i - 1] !== escapeCharacter) { return i; } } return -1; } /** * Finds the last occurrence of a character that: * - isn't preceded by an escape character * - isn't followed by the specified character. * * @param pattern Source pattern. * @param searchedCharacter Searched character. * @param notFollowedBy Searched character not followed by this character. * @param escapeCharacter Escape character, \ by default. * * @returns Index or -1 if the character not found. */ static findLastUnescapedCharacterThatNotFollowedBy(pattern, searchedCharacter, notFollowedBy, escapeCharacter = _constants_js__rspack_import_0/* .ESCAPE_CHARACTER */.Kx) { for (let i = pattern.length - 1; i >= 0; i -= 1) { // The searched character cannot be preceded by an escape if (pattern[i] === searchedCharacter && pattern[i + 1] !== notFollowedBy && pattern[i - 1] !== escapeCharacter) { return i; } } return -1; } /** * Finds the next occurrence of a character that: * - isn't part of any string literal ('literal' or "literal") * - isn't part of any RegExp expression (/regexp/). * * @param pattern Source pattern. * @param searchedCharacter Searched character. * @param start Start index. * * @returns Index or -1 if the character not found. */ static findUnescapedNonStringNonRegexChar(pattern, searchedCharacter, start = 0) { let open = null; for (let i = start; i < pattern.length; i += 1) { if ((pattern[i] === SINGLE_QUOTE_MARKER || pattern[i] === DOUBLE_QUOTE_MARKER || pattern[i] === _constants_js__rspack_import_0/* .REGEX_MARKER */.Vb) && pattern[i - 1] !== _constants_js__rspack_import_0/* .ESCAPE_CHARACTER */.Kx) { if (open === pattern[i]) { open = null; } else if (open === null) { open = pattern[i]; } } else if (open === null && pattern[i] === searchedCharacter && pattern[i - 1] !== _constants_js__rspack_import_0/* .ESCAPE_CHARACTER */.Kx) { return i; } } return -1; } /** * Finds the last occurrence of a character that is: * - not part of any string literal ('literal' or "literal") * - not part of any RegExp expression (/regexp/) * - not preceded by an escape character. * * Searches backwards from the end of the pattern. * * @param pattern Source pattern. * @param searchedCharacter Searched character. * @param escapeCharacter Escape character, `\` by default. * * @returns Index of the character or -1 if the character not found. */ static findLastUnescapedNonStringNonRegexChar(pattern, searchedCharacter, escapeCharacter = _constants_js__rspack_import_0/* .ESCAPE_CHARACTER */.Kx) { let open = null; // Search backwards through the pattern for (let i = pattern.length - 1; i >= 0; i -= 1) { if ((pattern[i] === SINGLE_QUOTE_MARKER || pattern[i] === DOUBLE_QUOTE_MARKER || pattern[i] === _constants_js__rspack_import_0/* .REGEX_MARKER */.Vb) && pattern[i - 1] !== escapeCharacter) { // When searching backwards, // we close when we see the marker and are already inside, // and open when we see it and are not inside. if (open === pattern[i]) { open = null; } else if (open === null) { open = pattern[i]; } } else if (open === null && pattern[i] === searchedCharacter && pattern[i - 1] !== escapeCharacter) { return i; } } return -1; } /** * Finds the next occurrence of a character that: * - isn't part of any string literal ('literal' or "literal") * - isn't preceded by an escape character. * * @param pattern Source pattern. * @param searchedCharacter Searched character. * @param start Start index. * @param escapeCharacter Escape character, \ by default. * * @returns Index or -1 if the character not found. */ static findNextUnquotedUnescapedCharacter(pattern, searchedCharacter, start = 0, escapeCharacter = _constants_js__rspack_import_0/* .ESCAPE_CHARACTER */.Kx) { let openQuote = null; for (let i = start; i < pattern.length; i += 1) { // Unescaped ' or " if ((pattern[i] === SINGLE_QUOTE_MARKER || pattern[i] === DOUBLE_QUOTE_MARKER) && pattern[i - 1] !== escapeCharacter) { if (!openQuote) { openQuote = pattern[i]; } else if (openQuote === pattern[i]) { openQuote = null; } } else if (pattern[i] === searchedCharacter && pattern[i - 1] !== escapeCharacter) { // Unescaped character if (!openQuote) { return i; } } } return -1; } /** * Finds the next occurrence of a character that: * - isn't "bracketed" * - isn't preceded by an escape character. * * @param pattern Source pattern. * @param searchedCharacter Searched character. * @param start Start index. * @param escapeCharacter Escape character, \ by default. * @param openBracket Open bracket, ( by default. * @param closeBracket Close bracket, ( by default. * * @returns Index or -1 if the character not found. * * @throws If the opening and closing brackets are the same. */ static findNextNotBracketedUnescapedCharacter(pattern, searchedCharacter, start = 0, escapeCharacter = _constants_js__rspack_import_0/* .ESCAPE_CHARACTER */.Kx, openBracket = '(', closeBracket = ')') { if (openBracket === closeBracket) { throw new Error('Open and close bracket cannot be the same'); } let depth = 0; for (let i = start; i < pattern.length; i += 1) { if (pattern[i] === openBracket) { depth += 1; } else if (pattern[i] === closeBracket) { depth -= 1; } else if (depth < 1 && pattern[i] === searchedCharacter && pattern[i - 1] !== escapeCharacter) { return i; } } return -1; } /** * Splits the source pattern along characters that: * - isn't part of any string literal ('literal' or "literal") * - isn't preceded by an escape character. * * @param pattern Source pattern. * @param delimeterCharacter Delimeter character. * * @returns Splitted string. */ static splitStringByUnquotedUnescapedCharacter(pattern, delimeterCharacter) { const parts = []; let delimeterIndex = -1; do { const prevDelimeterIndex = delimeterIndex; delimeterIndex = StringUtils.findNextUnquotedUnescapedCharacter(pattern, delimeterCharacter, delimeterIndex + 1); if (delimeterIndex !== -1) { parts.push(pattern.substring(prevDelimeterIndex + 1, delimeterIndex)); } else { parts.push(pattern.substring(prevDelimeterIndex + 1, pattern.length)); } } while (delimeterIndex !== -1); return parts; } /** * Splits the source pattern along characters that: * - isn't part of any string literal ('literal' or "literal") * - isn't part of any RegExp expression (/regexp/) * - isn't preceded by an escape character. * * @param pattern Source pattern. * @param delimeterCharacter Delimeter character. * * @returns Splitted string. */ static splitStringByUnescapedNonStringNonRegexChar(pattern, delimeterCharacter) { const parts = []; let delimeterIndex = -1; do { const prevDelimeterIndex = delimeterIndex; delimeterIndex = StringUtils.findUnescapedNonStringNonRegexChar(pattern, delimeterCharacter, delimeterIndex + 1); if (delimeterIndex !== -1) { parts.push(pattern.substring(prevDelimeterIndex + 1, delimeterIndex)); } else { parts.push(pattern.substring(prevDelimeterIndex + 1, pattern.length)); } } while (delimeterIndex !== -1); return parts; } /** * Splits the source pattern along characters that: * - isn't preceded by an escape character. * * @param pattern Source pattern. * @param delimeterCharacter Delimeter character. * * @returns Splitted string. */ static splitStringByUnescapedCharacter(pattern, delimeterCharacter) { const parts = []; let delimeterIndex = -1; do { const prevDelimeterIndex = delimeterIndex; delimeterIndex = StringUtils.findNextUnescapedCharacter(pattern, delimeterCharacter, delimeterIndex + 1); if (delimeterIndex !== -1) { parts.push(pattern.substring(prevDelimeterIndex + 1, delimeterIndex)); } else { parts.push(pattern.substring(prevDelimeterIndex + 1, pattern.length)); } } while (delimeterIndex !== -1); return parts; } /** * Determines whether the given character is a space or tab character. * * @param char The character to check. * * @returns True if the given character is a space or tab character, false otherwise. */ static isWhitespace(char) { return char === _constants_js__rspack_import_0/* .SPACE */.t6 || char === _constants_js__rspack_import_0/* .TAB */.wn; } /** * Checks if the given character is a digit. * * @param char The character to check. * * @returns `true` if the given character is a digit, `false` otherwise. */ static isDigit(char) { return char >= _constants_js__rspack_import_0/* .NUMBER_0 */.nC && char <= _constants_js__rspack_import_0/* .NUMBER_9 */.g9; } /** * Checks if the given character is a small letter. * * @param char The character to check. * * @returns `true` if the given character is a small letter, `false` otherwise. */ static isSmallLetter(char) { return char >= _constants_js__rspack_import_0/* .SMALL_LETTER_A */.H3 && char <= _constants_js__rspack_import_0/* .SMALL_LETTER_Z */.AT; } /** * Checks if the given character is a capital letter. * * @param char The character to check. * * @returns `true` if the given character is a capital letter, `false` otherwise. */ static isCapitalLetter(char) { return char >= _constants_js__rspack_import_0/* .CAPITAL_LETTER_A */.ot && char <= _constants_js__rspack_import_0/* .CAPITAL_LETTER_Z */.hk; } /** * Checks if the given character is a letter (small or capital). * * @param char The character to check. * * @returns `true` if the given character is a letter, `false` otherwise. */ static isLetter(char) { return StringUtils.isSmallLetter(char) || StringUtils.isCapitalLetter(char); } /** * Checks if the given character is a letter or a digit. * * @param char Character to check. * * @returns `true` if the given character is a letter or a digit, `false` otherwise. */ static isAlphaNumeric(char) { return StringUtils.isLetter(char) || StringUtils.isDigit(char); } /** * Searches for the first non-whitespace character in the source pattern. * * @param pattern Source pattern. * @param start Start index. * * @returns Index or -1 if the character not found. */ static findFirstNonWhitespaceCharacter(pattern, start = 0) { for (let i = start; i < pattern.length; i += 1) { if (!StringUtils.isWhitespace(pattern[i])) { return i; } } return -1; } /** * Searches for the last non-whitespace character in the source pattern. * * @param pattern Source pattern. * * @returns Index or -1 if the character not found. */ static findLastNonWhitespaceCharacter(pattern) { for (let i = pattern.length - 1; i >= 0; i -= 1) { if (!StringUtils.isWhitespace(pattern[i])) { return i; } } return -1; } /** * Finds the next whitespace character in the pattern. * * @param pattern Pattern to search in. * @param start Start index. * * @returns Index of the next whitespace character or the length of the pattern if not found. */ static findNextWhitespaceCharacter(pattern, start = 0) { for (let i = start; i < pattern.length; i += 1) { if (StringUtils.isWhitespace(pattern[i])) { return i; } } return pattern.length; } /** * Escapes a specified character in the string. * * @param pattern Input string. * @param character Character to escape. * @param escapeCharacter Escape character (optional). * * @returns Escaped string. */ static escapeCharacter(pattern, character, escapeCharacter = _constants_js__rspack_import_0/* .ESCAPE_CHARACTER */.Kx) { let result = _constants_js__rspack_import_0/* .EMPTY */.wg; for (let i = 0; i < pattern.length; i += 1) { if (pattern[i] === character && pattern[i - 1] !== escapeCharacter) { result += escapeCharacter; } result += pattern[i]; } return result; } /** * Searches for the next non-whitespace character in the source pattern. * * @param pattern Pattern to search. * @param start Start index. * * @returns Index of the next non-whitespace character or the length of the pattern. */ static skipWS(pattern, start = 0) { let i = start; while (i < pattern.length && StringUtils.isWhitespace(pattern[i])) { i += 1; } return Math.min(i, pattern.length); } /** * Searches for the previous non-whitespace character in the source pattern. * * @param pattern Pattern to search. * @param start Start index. * * @returns Index of the previous non-whitespace character or -1. */ static skipWSBack(pattern, start = pattern.length - 1) { let i = start; while (i >= 0 && StringUtils.isWhitespace(pattern[i])) { i -= 1; } return Math.max(i, -1); } /** * Checks if the given character is a new line character. * * @param char Character to check. * * @returns `true` if the given character is a new line character, `false` otherwise. */ static isEOL(char) { return char === _constants_js__rspack_import_0.CR || char === _constants_js__rspack_import_0.LF || char === _constants_js__rspack_import_0.FF; } /** * Splits a string along newline characters. * * @param input Input string. * * @returns Splitted string. */ static splitStringByNewLines(input) { return input.split(/\r?\n/); } /** * Splits a string by new lines and stores the new line type for each line. * * @param input The input string to be split. * * @returns An array of tuples, where each tuple contains a line of the input string and its * corresponding new line type ("lf", "crlf", or "cr"). */ static splitStringByNewLinesEx(input) { // Array to store the tuples of line and new line type const result = []; let currentLine = _constants_js__rspack_import_0/* .EMPTY */.wg; let newLineType = null; // Iterate over each character in the input string for (let i = 0; i < input.length; i += 1) { const char = input[i]; if (char === _constants_js__rspack_import_0.CR) { if (input[i + 1] === _constants_js__rspack_import_0.LF) { newLineType = 'crlf'; i += 1; } else { newLineType = 'cr'; } result.push([currentLine, newLineType]); currentLine = _constants_js__rspack_import_0/* .EMPTY */.wg; newLineType = null; } else if (char === _constants_js__rspack_import_0.LF) { newLineType = 'lf'; result.push([currentLine, newLineType]); currentLine = _constants_js__rspack_import_0/* .EMPTY */.wg; newLineType = null; } else { currentLine += char; } } if (result.length === 0 || currentLine !== _constants_js__rspack_import_0/* .EMPTY */.wg) { result.push([currentLine, newLineType]); } return result; } /** * Merges an array of tuples (line, newLineType) into a single string. * * @param input The array of tuples to be merged. * * @returns A single string containing the lines and new line characters from the input array. */ static mergeStringByNewLines(input) { let result = _constants_js__rspack_import_0/* .EMPTY */.wg; // Iterate over each tuple in the input array for (let i = 0; i < input.length; i += 1) { const [line, newLineType] = input[i]; // Add the line to the result string result += line; // Add the appropriate new line character based on the newLineType if (newLineType !== null) { if (newLineType === 'crlf') { result += _constants_js__rspack_import_0/* .CRLF */.KT; } else if (newLineType === 'cr') { result += _constants_js__rspack_import_0.CR; } else { result += _constants_js__rspack_import_0.LF; } } } return result; } /** * Helper method to parse a raw string as a number. * * @param raw Raw string to parse. * * @returns Parsed number. * * @throws If the raw string can't be parsed as a number. */ static parseNumber(raw) { const result = parseInt(raw, 10); if (Number.isNaN(result)) { throw new Error('Expected a number'); } return result; } /** * Checks if the given value is a string. * * @param value Value to check. * * @returns `true` if the value is a string, `false` otherwise. */ static isString(value) { return typeof value === 'string'; } /** * Escapes the given characters in the input string. * * @param input Input string. * @param characters Characters to escape (by default, no characters are escaped). * * @returns Escaped string. */ static escapeCharacters(input, characters = new Set()) { let result = _constants_js__rspack_import_0/* .EMPTY */.wg; for (let i = 0; i < input.length; i += 1) { if (characters.has(input[i])) { result += _constants_js__rspack_import_0/* .ESCAPE_CHARACTER */.Kx; } result += input[i]; } return result; } } }, 64505(__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) { __webpack_require__.d(__webpack_exports__, { Kg: () => (isString), b0: () => (isUndefined), kZ: () => (isNull) }); /* * AGTree v4.2.1 (build date: Wed, 12 Aug 2026 01:31:02 GMT) * (c) 2026 Adguard Software Ltd. * Released under the MIT license * https://github.com/AdguardTeam/tsurlfilter/tree/master/packages/agtree#readme */ /** * Checks whether the given value is undefined. * * @param value Value to check. * * @returns `true` if the value is 'undefined', `false` otherwise. */ const isUndefined = (value) => { return typeof value === 'undefined'; }; /** * Checks whether the given value is null. * * @param value Value to check. * * @returns `true` if the value is 'null', `false` otherwise. */ const isNull = (value) => { return value === null; }; /** * Checks whether the given value is a string. * * @param value Value to check. * * @returns `true` if the value is a string, `false` otherwise. */ const isString = (value) => { return typeof value === 'string'; }; }, 53034(__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) { __webpack_require__.d(__webpack_exports__, { Ay: () => (z), G: () => (ZodError), Yj: () => (stringType), ai: () => (numberType), eq: () => (ZodIssueCode), g1: () => (recordType), z: () => (z), zM: () => (booleanType) }); var util; (function (util) { util.assertEqual = (val) => val; function assertIs(_arg) { } util.assertIs = assertIs; function assertNever(_x) { throw new Error(); } util.assertNever = assertNever; util.arrayToEnum = (items) => { const obj = {}; for (const item of items) { obj[item] = item; } return obj; }; util.getValidEnumValues = (obj) => { const validKeys = util.objectKeys(obj).filter((k) => typeof obj[obj[k]] !== "number"); const filtered = {}; for (const k of validKeys) { filtered[k] = obj[k]; } return util.objectValues(filtered); }; util.objectValues = (obj) => { return util.objectKeys(obj).map(function (e) { return obj[e]; }); }; util.objectKeys = typeof Object.keys === "function" // eslint-disable-line ban/ban ? (obj) => Object.keys(obj) // eslint-disable-line ban/ban : (object) => { const keys = []; for (const key in object) { if (Object.prototype.hasOwnProperty.call(object, key)) { keys.push(key); } } return keys; }; util.find = (arr, checker) => { for (const item of arr) { if (checker(item)) return item; } return undefined; }; util.isInteger = typeof Number.isInteger === "function" ? (val) => Number.isInteger(val) // eslint-disable-line ban/ban : (val) => typeof val === "number" && isFinite(val) && Math.floor(val) === val; function joinValues(array, separator = " | ") { return array .map((val) => (typeof val === "string" ? `'${val}'` : val)) .join(separator); } util.joinValues = joinValues; util.jsonStringifyReplacer = (_, value) => { if (typeof value === "bigint") { return value.toString(); } return value; }; })(util || (util = {})); var objectUtil; (function (objectUtil) { objectUtil.mergeShapes = (first, second) => { return { ...first, ...second, // second overwrites first }; }; })(objectUtil || (objectUtil = {})); const ZodParsedType = util.arrayToEnum([ "string", "nan", "number", "integer", "float", "boolean", "date", "bigint", "symbol", "function", "undefined", "null", "array", "object", "unknown", "promise", "void", "never", "map", "set", ]); const getParsedType = (data) => { const t = typeof data; switch (t) { case "undefined": return ZodParsedType.undefined; case "string": return ZodParsedType.string; case "number": return isNaN(data) ? ZodParsedType.nan : ZodParsedType.number; case "boolean": return ZodParsedType.boolean; case "function": return ZodParsedType.function; case "bigint": return ZodParsedType.bigint; case "symbol": return ZodParsedType.symbol; case "object": if (Array.isArray(data)) { return ZodParsedType.array; } if (data === null) { return ZodParsedType.null; } if (data.then && typeof data.then === "function" && data.catch && typeof data.catch === "function") { return ZodParsedType.promise; } if (typeof Map !== "undefined" && data instanceof Map) { return ZodParsedType.map; } if (typeof Set !== "undefined" && data instanceof Set) { return ZodParsedType.set; } if (typeof Date !== "undefined" && data instanceof Date) { return ZodParsedType.date; } return ZodParsedType.object; default: return ZodParsedType.unknown; } }; const ZodIssueCode = util.arrayToEnum([ "invalid_type", "invalid_literal", "custom", "invalid_union", "invalid_union_discriminator", "invalid_enum_value", "unrecognized_keys", "invalid_arguments", "invalid_return_type", "invalid_date", "invalid_string", "too_small", "too_big", "invalid_intersection_types", "not_multiple_of", "not_finite", ]); const quotelessJson = (obj) => { const json = JSON.stringify(obj, null, 2); return json.replace(/"([^"]+)":/g, "$1:"); }; class ZodError extends Error { get errors() { return this.issues; } constructor(issues) { super(); this.issues = []; this.addIssue = (sub) => { this.issues = [...this.issues, sub]; }; this.addIssues = (subs = []) => { this.issues = [...this.issues, ...subs]; }; const actualProto = new.target.prototype; if (Object.setPrototypeOf) { // eslint-disable-next-line ban/ban Object.setPrototypeOf(this, actualProto); } else { this.__proto__ = actualProto; } this.name = "ZodError"; this.issues = issues; } format(_mapper) { const mapper = _mapper || function (issue) { return issue.message; }; const fieldErrors = { _errors: [] }; const processError = (error) => { for (const issue of error.issues) { if (issue.code === "invalid_union") { issue.unionErrors.map(processError); } else if (issue.code === "invalid_return_type") { processError(issue.returnTypeError); } else if (issue.code === "invalid_arguments") { processError(issue.argumentsError); } else if (issue.path.length === 0) { fieldErrors._errors.push(mapper(issue)); } else { let curr = fieldErrors; let i = 0; while (i < issue.path.length) { const el = issue.path[i]; const terminal = i === issue.path.length - 1; if (!terminal) { curr[el] = curr[el] || { _errors: [] }; // if (typeof el === "string") { // curr[el] = curr[el] || { _errors: [] }; // } else if (typeof el === "number") { // const errorArray: any = []; // errorArray._errors = []; // curr[el] = curr[el] || errorArray; // } } else { curr[el] = curr[el] || { _errors: [] }; curr[el]._errors.push(mapper(issue)); } curr = curr[el]; i++; } } } }; processError(this); return fieldErrors; } static assert(value) { if (!(value instanceof ZodError)) { throw new Error(`Not a ZodError: ${value}`); } } toString() { return this.message; } get message() { return JSON.stringify(this.issues, util.jsonStringifyReplacer, 2); } get isEmpty() { return this.issues.length === 0; } flatten(mapper = (issue) => issue.message) { const fieldErrors = {}; const formErrors = []; for (const sub of this.issues) { if (sub.path.length > 0) { fieldErrors[sub.path[0]] = fieldErrors[sub.path[0]] || []; fieldErrors[sub.path[0]].push(mapper(sub)); } else { formErrors.push(mapper(sub)); } } return { formErrors, fieldErrors }; } get formErrors() { return this.flatten(); } } ZodError.create = (issues) => { const error = new ZodError(issues); return error; }; const errorMap = (issue, _ctx) => { let message; switch (issue.code) { case ZodIssueCode.invalid_type: if (issue.received === ZodParsedType.undefined) { message = "Required"; } else { message = `Expected ${issue.expected}, received ${issue.received}`; } break; case ZodIssueCode.invalid_literal: message = `Invalid literal value, expected ${JSON.stringify(issue.expected, util.jsonStringifyReplacer)}`; break; case ZodIssueCode.unrecognized_keys: message = `Unrecognized key(s) in object: ${util.joinValues(issue.keys, ", ")}`; break; case ZodIssueCode.invalid_union: message = `Invalid input`; break; case ZodIssueCode.invalid_union_discriminator: message = `Invalid discriminator value. Expected ${util.joinValues(issue.options)}`; break; case ZodIssueCode.invalid_enum_value: message = `Invalid enum value. Expected ${util.joinValues(issue.options)}, received '${issue.received}'`; break; case ZodIssueCode.invalid_arguments: message = `Invalid function arguments`; break; case ZodIssueCode.invalid_return_type: message = `Invalid function return type`; break; case ZodIssueCode.invalid_date: message = `Invalid date`; break; case ZodIssueCode.invalid_string: if (typeof issue.validation === "object") { if ("includes" in issue.validation) { message = `Invalid input: must include "${issue.validation.includes}"`; if (typeof issue.validation.position === "number") { message = `${message} at one or more positions greater than or equal to ${issue.validation.position}`; } } else if ("startsWith" in issue.validation) { message = `Invalid input: must start with "${issue.validation.startsWith}"`; } else if ("endsWith" in issue.validation) { message = `Invalid input: must end with "${issue.validation.endsWith}"`; } else { util.assertNever(issue.validation); } } else if (issue.validation !== "regex") { message = `Invalid ${issue.validation}`; } else { message = "Invalid"; } break; case ZodIssueCode.too_small: if (issue.type === "array") message = `Array must contain ${issue.exact ? "exactly" : issue.inclusive ? `at least` : `more than`} ${issue.minimum} element(s)`; else if (issue.type === "string") message = `String must contain ${issue.exact ? "exactly" : issue.inclusive ? `at least` : `over`} ${issue.minimum} character(s)`; else if (issue.type === "number") message = `Number must be ${issue.exact ? `exactly equal to ` : issue.inclusive ? `greater than or equal to ` : `greater than `}${issue.minimum}`; else if (issue.type === "date") message = `Date must be ${issue.exact ? `exactly equal to ` : issue.inclusive ? `greater than or equal to ` : `greater than `}${new Date(Number(issue.minimum))}`; else message = "Invalid input"; break; case ZodIssueCode.too_big: if (issue.type === "array") message = `Array must contain ${issue.exact ? `exactly` : issue.inclusive ? `at most` : `less than`} ${issue.maximum} element(s)`; else if (issue.type === "string") message = `String must contain ${issue.exact ? `exactly` : issue.inclusive ? `at most` : `under`} ${issue.maximum} character(s)`; else if (issue.type === "number") message = `Number must be ${issue.exact ? `exactly` : issue.inclusive ? `less than or equal to` : `less than`} ${issue.maximum}`; else if (issue.type === "bigint") message = `BigInt must be ${issue.exact ? `exactly` : issue.inclusive ? `less than or equal to` : `less than`} ${issue.maximum}`; else if (issue.type === "date") message = `Date must be ${issue.exact ? `exactly` : issue.inclusive ? `smaller than or equal to` : `smaller than`} ${new Date(Number(issue.maximum))}`; else message = "Invalid input"; break; case ZodIssueCode.custom: message = `Invalid input`; break; case ZodIssueCode.invalid_intersection_types: message = `Intersection results could not be merged`; break; case ZodIssueCode.not_multiple_of: message = `Number must be a multiple of ${issue.multipleOf}`; break; case ZodIssueCode.not_finite: message = "Number must be finite"; break; default: message = _ctx.defaultError; util.assertNever(issue); } return { message }; }; let overrideErrorMap = errorMap; function setErrorMap(map) { overrideErrorMap = map; } function getErrorMap() { return overrideErrorMap; } const makeIssue = (params) => { const { data, path, errorMaps, issueData } = params; const fullPath = [...path, ...(issueData.path || [])]; const fullIssue = { ...issueData, path: fullPath, }; if (issueData.message !== undefined) { return { ...issueData, path: fullPath, message: issueData.message, }; } let errorMessage = ""; const maps = errorMaps .filter((m) => !!m) .slice() .reverse(); for (const map of maps) { errorMessage = map(fullIssue, { data, defaultError: errorMessage }).message; } return { ...issueData, path: fullPath, message: errorMessage, }; }; const EMPTY_PATH = []; function addIssueToContext(ctx, issueData) { const overrideMap = getErrorMap(); const issue = makeIssue({ issueData: issueData, data: ctx.data, path: ctx.path, errorMaps: [ ctx.common.contextualErrorMap, // contextual error map is first priority ctx.schemaErrorMap, // then schema-bound map if available overrideMap, // then global override map overrideMap === errorMap ? undefined : errorMap, // then global default map ].filter((x) => !!x), }); ctx.common.issues.push(issue); } class ParseStatus { constructor() { this.value = "valid"; } dirty() { if (this.value === "valid") this.value = "dirty"; } abort() { if (this.value !== "aborted") this.value = "aborted"; } static mergeArray(status, results) { const arrayValue = []; for (const s of results) { if (s.status === "aborted") return INVALID; if (s.status === "dirty") status.dirty(); arrayValue.push(s.value); } return { status: status.value, value: arrayValue }; } static async mergeObjectAsync(status, pairs) { const syncPairs = []; for (const pair of pairs) { const key = await pair.key; const value = await pair.value; syncPairs.push({ key, value, }); } return ParseStatus.mergeObjectSync(status, syncPairs); } static mergeObjectSync(status, pairs) { const finalObject = {}; for (const pair of pairs) { const { key, value } = pair; if (key.status === "aborted") return INVALID; if (value.status === "aborted") return INVALID; if (key.status === "dirty") status.dirty(); if (value.status === "dirty") status.dirty(); if (key.value !== "__proto__" && (typeof value.value !== "undefined" || pair.alwaysSet)) { finalObject[key.value] = value.value; } } return { status: status.value, value: finalObject }; } } const INVALID = Object.freeze({ status: "aborted", }); const DIRTY = (value) => ({ status: "dirty", value }); const OK = (value) => ({ status: "valid", value }); const isAborted = (x) => x.status === "aborted"; const isDirty = (x) => x.status === "dirty"; const isValid = (x) => x.status === "valid"; const isAsync = (x) => typeof Promise !== "undefined" && x instanceof Promise; /****************************************************************************** Copyright (c) Microsoft Corporation. Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted. THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ***************************************************************************** */ function __classPrivateFieldGet(receiver, state, kind, f) { if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter"); if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it"); return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver); } function __classPrivateFieldSet(receiver, state, value, kind, f) { if (kind === "m") throw new TypeError("Private method is not writable"); if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter"); if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it"); return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value; } typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) { var e = new Error(message); return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e; }; var errorUtil; (function (errorUtil) { errorUtil.errToObj = (message) => typeof message === "string" ? { message } : message || {}; errorUtil.toString = (message) => typeof message === "string" ? message : message === null || message === void 0 ? void 0 : message.message; })(errorUtil || (errorUtil = {})); var _ZodEnum_cache, _ZodNativeEnum_cache; class ParseInputLazyPath { constructor(parent, value, path, key) { this._cachedPath = []; this.parent = parent; this.data = value; this._path = path; this._key = key; } get path() { if (!this._cachedPath.length) { if (this._key instanceof Array) { this._cachedPath.push(...this._path, ...this._key); } else { this._cachedPath.push(...this._path, this._key); } } return this._cachedPath; } } const handleResult = (ctx, result) => { if (isValid(result)) { return { success: true, data: result.value }; } else { if (!ctx.common.issues.length) { throw new Error("Validation failed but no issues detected."); } return { success: false, get error() { if (this._error) return this._error; const error = new ZodError(ctx.common.issues); this._error = error; return this._error; }, }; } }; function processCreateParams(params) { if (!params) return {}; const { errorMap, invalid_type_error, required_error, description } = params; if (errorMap && (invalid_type_error || required_error)) { throw new Error(`Can't use "invalid_type_error" or "required_error" in conjunction with custom error map.`); } if (errorMap) return { errorMap: errorMap, description }; const customMap = (iss, ctx) => { var _a, _b; const { message } = params; if (iss.code === "invalid_enum_value") { return { message: message !== null && message !== void 0 ? message : ctx.defaultError }; } if (typeof ctx.data === "undefined") { return { message: (_a = message !== null && message !== void 0 ? message : required_error) !== null && _a !== void 0 ? _a : ctx.defaultError }; } if (iss.code !== "invalid_type") return { message: ctx.defaultError }; return { message: (_b = message !== null && message !== void 0 ? message : invalid_type_error) !== null && _b !== void 0 ? _b : ctx.defaultError }; }; return { errorMap: customMap, description }; } class ZodType { get description() { return this._def.description; } _getType(input) { return getParsedType(input.data); } _getOrReturnCtx(input, ctx) { return (ctx || { common: input.parent.common, data: input.data, parsedType: getParsedType(input.data), schemaErrorMap: this._def.errorMap, path: input.path, parent: input.parent, }); } _processInputParams(input) { return { status: new ParseStatus(), ctx: { common: input.parent.common, data: input.data, parsedType: getParsedType(input.data), schemaErrorMap: this._def.errorMap, path: input.path, parent: input.parent, }, }; } _parseSync(input) { const result = this._parse(input); if (isAsync(result)) { throw new Error("Synchronous parse encountered promise."); } return result; } _parseAsync(input) { const result = this._parse(input); return Promise.resolve(result); } parse(data, params) { const result = this.safeParse(data, params); if (result.success) return result.data; throw result.error; } safeParse(data, params) { var _a; const ctx = { common: { issues: [], async: (_a = params === null || params === void 0 ? void 0 : params.async) !== null && _a !== void 0 ? _a : false, contextualErrorMap: params === null || params === void 0 ? void 0 : params.errorMap, }, path: (params === null || params === void 0 ? void 0 : params.path) || [], schemaErrorMap: this._def.errorMap, parent: null, data, parsedType: getParsedType(data), }; const result = this._parseSync({ data, path: ctx.path, parent: ctx }); return handleResult(ctx, result); } "~validate"(data) { var _a, _b; const ctx = { common: { issues: [], async: !!this["~standard"].async, }, path: [], schemaErrorMap: this._def.errorMap, parent: null, data, parsedType: getParsedType(data), }; if (!this["~standard"].async) { try { const result = this._parseSync({ data, path: [], parent: ctx }); return isValid(result) ? { value: result.value, } : { issues: ctx.common.issues, }; } catch (err) { if ((_b = (_a = err === null || err === void 0 ? void 0 : err.message) === null || _a === void 0 ? void 0 : _a.toLowerCase()) === null || _b === void 0 ? void 0 : _b.includes("encountered")) { this["~standard"].async = true; } ctx.common = { issues: [], async: true, }; } } return this._parseAsync({ data, path: [], parent: ctx }).then((result) => isValid(result) ? { value: result.value, } : { issues: ctx.common.issues, }); } async parseAsync(data, params) { const result = await this.safeParseAsync(data, params); if (result.success) return result.data; throw result.error; } async safeParseAsync(data, params) { const ctx = { common: { issues: [], contextualErrorMap: params === null || params === void 0 ? void 0 : params.errorMap, async: true, }, path: (params === null || params === void 0 ? void 0 : params.path) || [], schemaErrorMap: this._def.errorMap, parent: null, data, parsedType: getParsedType(data), }; const maybeAsyncResult = this._parse({ data, path: ctx.path, parent: ctx }); const result = await (isAsync(maybeAsyncResult) ? maybeAsyncResult : Promise.resolve(maybeAsyncResult)); return handleResult(ctx, result); } refine(check, message) { const getIssueProperties = (val) => { if (typeof message === "string" || typeof message === "undefined") { return { message }; } else if (typeof message === "function") { return message(val); } else { return message; } }; return this._refinement((val, ctx) => { const result = check(val); const setError = () => ctx.addIssue({ code: ZodIssueCode.custom, ...getIssueProperties(val), }); if (typeof Promise !== "undefined" && result instanceof Promise) { return result.then((data) => { if (!data) { setError(); return false; } else { return true; } }); } if (!result) { setError(); return false; } else { return true; } }); } refinement(check, refinementData) { return this._refinement((val, ctx) => { if (!check(val)) { ctx.addIssue(typeof refinementData === "function" ? refinementData(val, ctx) : refinementData); return false; } else { return true; } }); } _refinement(refinement) { return new ZodEffects({ schema: this, typeName: ZodFirstPartyTypeKind.ZodEffects, effect: { type: "refinement", refinement }, }); } superRefine(refinement) { return this._refinement(refinement); } constructor(def) { /** Alias of safeParseAsync */ this.spa = this.safeParseAsync; this._def = def; this.parse = this.parse.bind(this); this.safeParse = this.safeParse.bind(this); this.parseAsync = this.parseAsync.bind(this); this.safeParseAsync = this.safeParseAsync.bind(this); this.spa = this.spa.bind(this); this.refine = this.refine.bind(this); this.refinement = this.refinement.bind(this); this.superRefine = this.superRefine.bind(this); this.optional = this.optional.bind(this); this.nullable = this.nullable.bind(this); this.nullish = this.nullish.bind(this); this.array = this.array.bind(this); this.promise = this.promise.bind(this); this.or = this.or.bind(this); this.and = this.and.bind(this); this.transform = this.transform.bind(this); this.brand = this.brand.bind(this); this.default = this.default.bind(this); this.catch = this.catch.bind(this); this.describe = this.describe.bind(this); this.pipe = this.pipe.bind(this); this.readonly = this.readonly.bind(this); this.isNullable = this.isNullable.bind(this); this.isOptional = this.isOptional.bind(this); this["~standard"] = { version: 1, vendor: "zod", validate: (data) => this["~validate"](data), }; } optional() { return ZodOptional.create(this, this._def); } nullable() { return ZodNullable.create(this, this._def); } nullish() { return this.nullable().optional(); } array() { return ZodArray.create(this); } promise() { return ZodPromise.create(this, this._def); } or(option) { return ZodUnion.create([this, option], this._def); } and(incoming) { return ZodIntersection.create(this, incoming, this._def); } transform(transform) { return new ZodEffects({ ...processCreateParams(this._def), schema: this, typeName: ZodFirstPartyTypeKind.ZodEffects, effect: { type: "transform", transform }, }); } default(def) { const defaultValueFunc = typeof def === "function" ? def : () => def; return new ZodDefault({ ...processCreateParams(this._def), innerType: this, defaultValue: defaultValueFunc, typeName: ZodFirstPartyTypeKind.ZodDefault, }); } brand() { return new ZodBranded({ typeName: ZodFirstPartyTypeKind.ZodBranded, type: this, ...processCreateParams(this._def), }); } catch(def) { const catchValueFunc = typeof def === "function" ? def : () => def; return new ZodCatch({ ...processCreateParams(this._def), innerType: this, catchValue: catchValueFunc, typeName: ZodFirstPartyTypeKind.ZodCatch, }); } describe(description) { const This = this.constructor; return new This({ ...this._def, description, }); } pipe(target) { return ZodPipeline.create(this, target); } readonly() { return ZodReadonly.create(this); } isOptional() { return this.safeParse(undefined).success; } isNullable() { return this.safeParse(null).success; } } const cuidRegex = /^c[^\s-]{8,}$/i; const cuid2Regex = /^[0-9a-z]+$/; const ulidRegex = /^[0-9A-HJKMNP-TV-Z]{26}$/i; // const uuidRegex = // /^([a-f0-9]{8}-[a-f0-9]{4}-[1-5][a-f0-9]{3}-[a-f0-9]{4}-[a-f0-9]{12}|00000000-0000-0000-0000-000000000000)$/i; const uuidRegex = /^[0-9a-fA-F]{8}\b-[0-9a-fA-F]{4}\b-[0-9a-fA-F]{4}\b-[0-9a-fA-F]{4}\b-[0-9a-fA-F]{12}$/i; const nanoidRegex = /^[a-z0-9_-]{21}$/i; const jwtRegex = /^[A-Za-z0-9-_]+\.[A-Za-z0-9-_]+\.[A-Za-z0-9-_]*$/; const durationRegex = /^[-+]?P(?!$)(?:(?:[-+]?\d+Y)|(?:[-+]?\d+[.,]\d+Y$))?(?:(?:[-+]?\d+M)|(?:[-+]?\d+[.,]\d+M$))?(?:(?:[-+]?\d+W)|(?:[-+]?\d+[.,]\d+W$))?(?:(?:[-+]?\d+D)|(?:[-+]?\d+[.,]\d+D$))?(?:T(?=[\d+-])(?:(?:[-+]?\d+H)|(?:[-+]?\d+[.,]\d+H$))?(?:(?:[-+]?\d+M)|(?:[-+]?\d+[.,]\d+M$))?(?:[-+]?\d+(?:[.,]\d+)?S)?)??$/; // from https://stackoverflow.com/a/46181/1550155 // old version: too slow, didn't support unicode // const emailRegex = /^((([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+(\.([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+)*)|((\x22)((((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(([\x01-\x08\x0b\x0c\x0e-\x1f\x7f]|\x21|[\x23-\x5b]|[\x5d-\x7e]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(\\([\x01-\x09\x0b\x0c\x0d-\x7f]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]))))*(((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(\x22)))@((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))$/i; //old email regex // const emailRegex = /^(([^<>()[\].,;:\s@"]+(\.[^<>()[\].,;:\s@"]+)*)|(".+"))@((?!-)([^<>()[\].,;:\s@"]+\.)+[^<>()[\].,;:\s@"]{1,})[^-<>()[\].,;:\s@"]$/i; // eslint-disable-next-line // const emailRegex = // /^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[(((25[0-5])|(2[0-4][0-9])|(1[0-9]{2})|([0-9]{1,2}))\.){3}((25[0-5])|(2[0-4][0-9])|(1[0-9]{2})|([0-9]{1,2}))\])|(\[IPv6:(([a-f0-9]{1,4}:){7}|::([a-f0-9]{1,4}:){0,6}|([a-f0-9]{1,4}:){1}:([a-f0-9]{1,4}:){0,5}|([a-f0-9]{1,4}:){2}:([a-f0-9]{1,4}:){0,4}|([a-f0-9]{1,4}:){3}:([a-f0-9]{1,4}:){0,3}|([a-f0-9]{1,4}:){4}:([a-f0-9]{1,4}:){0,2}|([a-f0-9]{1,4}:){5}:([a-f0-9]{1,4}:){0,1})([a-f0-9]{1,4}|(((25[0-5])|(2[0-4][0-9])|(1[0-9]{2})|([0-9]{1,2}))\.){3}((25[0-5])|(2[0-4][0-9])|(1[0-9]{2})|([0-9]{1,2})))\])|([A-Za-z0-9]([A-Za-z0-9-]*[A-Za-z0-9])*(\.[A-Za-z]{2,})+))$/; // const emailRegex = // /^[a-zA-Z0-9\.\!\#\$\%\&\'\*\+\/\=\?\^\_\`\{\|\}\~\-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/; // const emailRegex = // /^(?:[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*|"(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21\x23-\x5b\x5d-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])*")@(?:(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?|\[(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?|[a-z0-9-]*[a-z0-9]:(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21-\x5a\x53-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])+)\])$/i; const emailRegex = /^(?!\.)(?!.*\.\.)([A-Z0-9_'+\-\.]*)[A-Z0-9_+-]@([A-Z0-9][A-Z0-9\-]*\.)+[A-Z]{2,}$/i; // const emailRegex = // /^[a-z0-9.!#$%&’*+/=?^_`{|}~-]+@[a-z0-9-]+(?:\.[a-z0-9\-]+)*$/i; // from https://thekevinscott.com/emojis-in-javascript/#writing-a-regular-expression const _emojiRegex = `^(\\p{Extended_Pictographic}|\\p{Emoji_Component})+$`; let emojiRegex; // faster, simpler, safer const ipv4Regex = /^(?:(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])\.){3}(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])$/; const ipv4CidrRegex = /^(?:(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])\.){3}(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])\/(3[0-2]|[12]?[0-9])$/; // const ipv6Regex = // /^(([a-f0-9]{1,4}:){7}|::([a-f0-9]{1,4}:){0,6}|([a-f0-9]{1,4}:){1}:([a-f0-9]{1,4}:){0,5}|([a-f0-9]{1,4}:){2}:([a-f0-9]{1,4}:){0,4}|([a-f0-9]{1,4}:){3}:([a-f0-9]{1,4}:){0,3}|([a-f0-9]{1,4}:){4}:([a-f0-9]{1,4}:){0,2}|([a-f0-9]{1,4}:){5}:([a-f0-9]{1,4}:){0,1})([a-f0-9]{1,4}|(((25[0-5])|(2[0-4][0-9])|(1[0-9]{2})|([0-9]{1,2}))\.){3}((25[0-5])|(2[0-4][0-9])|(1[0-9]{2})|([0-9]{1,2})))$/; const ipv6Regex = /^(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]))$/; const ipv6CidrRegex = /^(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]))\/(12[0-8]|1[01][0-9]|[1-9]?[0-9])$/; // https://stackoverflow.com/questions/7860392/determine-if-string-is-in-base64-using-javascript const base64Regex = /^([0-9a-zA-Z+/]{4})*(([0-9a-zA-Z+/]{2}==)|([0-9a-zA-Z+/]{3}=))?$/; // https://base64.guru/standards/base64url const base64urlRegex = /^([0-9a-zA-Z-_]{4})*(([0-9a-zA-Z-_]{2}(==)?)|([0-9a-zA-Z-_]{3}(=)?))?$/; // simple // const dateRegexSource = `\\d{4}-\\d{2}-\\d{2}`; // no leap year validation // const dateRegexSource = `\\d{4}-((0[13578]|10|12)-31|(0[13-9]|1[0-2])-30|(0[1-9]|1[0-2])-(0[1-9]|1\\d|2\\d))`; // with leap year validation const dateRegexSource = `((\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-((0[13578]|1[02])-(0[1-9]|[12]\\d|3[01])|(0[469]|11)-(0[1-9]|[12]\\d|30)|(02)-(0[1-9]|1\\d|2[0-8])))`; const dateRegex = new RegExp(`^${dateRegexSource}$`); function timeRegexSource(args) { let secondsRegexSource = `[0-5]\\d`; if (args.precision) { secondsRegexSource = `${secondsRegexSource}\\.\\d{${args.precision}}`; } else if (args.precision == null) { secondsRegexSource = `${secondsRegexSource}(\\.\\d+)?`; } const secondsQuantifier = args.precision ? "+" : "?"; // require seconds if precision is nonzero return `([01]\\d|2[0-3]):[0-5]\\d(:${secondsRegexSource})${secondsQuantifier}`; } function timeRegex(args) { return new RegExp(`^${timeRegexSource(args)}$`); } // Adapted from https://stackoverflow.com/a/3143231 function datetimeRegex(args) { let regex = `${dateRegexSource}T${timeRegexSource(args)}`; const opts = []; opts.push(args.local ? `Z?` : `Z`); if (args.offset) opts.push(`([+-]\\d{2}:?\\d{2})`); regex = `${regex}(${opts.join("|")})`; return new RegExp(`^${regex}$`); } function isValidIP(ip, version) { if ((version === "v4" || !version) && ipv4Regex.test(ip)) { return true; } if ((version === "v6" || !version) && ipv6Regex.test(ip)) { return true; } return false; } function isValidJWT(jwt, alg) { if (!jwtRegex.test(jwt)) return false; try { const [header] = jwt.split("."); // Convert base64url to base64 const base64 = header .replace(/-/g, "+") .replace(/_/g, "/") .padEnd(header.length + ((4 - (header.length % 4)) % 4), "="); const decoded = JSON.parse(atob(base64)); if (typeof decoded !== "object" || decoded === null) return false; if (!decoded.typ || !decoded.alg) return false; if (alg && decoded.alg !== alg) return false; return true; } catch (_a) { return false; } } function isValidCidr(ip, version) { if ((version === "v4" || !version) && ipv4CidrRegex.test(ip)) { return true; } if ((version === "v6" || !version) && ipv6CidrRegex.test(ip)) { return true; } return false; } class ZodString extends ZodType { _parse(input) { if (this._def.coerce) { input.data = String(input.data); } const parsedType = this._getType(input); if (parsedType !== ZodParsedType.string) { const ctx = this._getOrReturnCtx(input); addIssueToContext(ctx, { code: ZodIssueCode.invalid_type, expected: ZodParsedType.string, received: ctx.parsedType, }); return INVALID; } const status = new ParseStatus(); let ctx = undefined; for (const check of this._def.checks) { if (check.kind === "min") { if (input.data.length < check.value) { ctx = this._getOrReturnCtx(input, ctx); addIssueToContext(ctx, { code: ZodIssueCode.too_small, minimum: check.value, type: "string", inclusive: true, exact: false, message: check.message, }); status.dirty(); } } else if (check.kind === "max") { if (input.data.length > check.value) { ctx = this._getOrReturnCtx(input, ctx); addIssueToContext(ctx, { code: ZodIssueCode.too_big, maximum: check.value, type: "string", inclusive: true, exact: false, message: check.message, }); status.dirty(); } } else if (check.kind === "length") { const tooBig = input.data.length > check.value; const tooSmall = input.data.length < check.value; if (tooBig || tooSmall) { ctx = this._getOrReturnCtx(input, ctx); if (tooBig) { addIssueToContext(ctx, { code: ZodIssueCode.too_big, maximum: check.value, type: "string", inclusive: true, exact: true, message: check.message, }); } else if (tooSmall) { addIssueToContext(ctx, { code: ZodIssueCode.too_small, minimum: check.value, type: "string", inclusive: true, exact: true, message: check.message, }); } status.dirty(); } } else if (check.kind === "email") { if (!emailRegex.test(input.data)) { ctx = this._getOrReturnCtx(input, ctx); addIssueToContext(ctx, { validation: "email", code: ZodIssueCode.invalid_string, message: check.message, }); status.dirty(); } } else if (check.kind === "emoji") { if (!emojiRegex) { emojiRegex = new RegExp(_emojiRegex, "u"); } if (!emojiRegex.test(input.data)) { ctx = this._getOrReturnCtx(input, ctx); addIssueToContext(ctx, { validation: "emoji", code: ZodIssueCode.invalid_string, message: check.message, }); status.dirty(); } } else if (check.kind === "uuid") { if (!uuidRegex.test(input.data)) { ctx = this._getOrReturnCtx(input, ctx); addIssueToContext(ctx, { validation: "uuid", code: ZodIssueCode.invalid_string, message: check.message, }); status.dirty(); } } else if (check.kind === "nanoid") { if (!nanoidRegex.test(input.data)) { ctx = this._getOrReturnCtx(input, ctx); addIssueToContext(ctx, { validation: "nanoid", code: ZodIssueCode.invalid_string, message: check.message, }); status.dirty(); } } else if (check.kind === "cuid") { if (!cuidRegex.test(input.data)) { ctx = this._getOrReturnCtx(input, ctx); addIssueToContext(ctx, { validation: "cuid", code: ZodIssueCode.invalid_string, message: check.message, }); status.dirty(); } } else if (check.kind === "cuid2") { if (!cuid2Regex.test(input.data)) { ctx = this._getOrReturnCtx(input, ctx); addIssueToContext(ctx, { validation: "cuid2", code: ZodIssueCode.invalid_string, message: check.message, }); status.dirty(); } } else if (check.kind === "ulid") { if (!ulidRegex.test(input.data)) { ctx = this._getOrReturnCtx(input, ctx); addIssueToContext(ctx, { validation: "ulid", code: ZodIssueCode.invalid_string, message: check.message, }); status.dirty(); } } else if (check.kind === "url") { try { new URL(input.data); } catch (_a) { ctx = this._getOrReturnCtx(input, ctx); addIssueToContext(ctx, { validation: "url", code: ZodIssueCode.invalid_string, message: check.message, }); status.dirty(); } } else if (check.kind === "regex") { check.regex.lastIndex = 0; const testResult = check.regex.test(input.data); if (!testResult) { ctx = this._getOrReturnCtx(input, ctx); addIssueToContext(ctx, { validation: "regex", code: ZodIssueCode.invalid_string, message: check.message, }); status.dirty(); } } else if (check.kind === "trim") { input.data = input.data.trim(); } else if (check.kind === "includes") { if (!input.data.includes(check.value, check.position)) { ctx = this._getOrReturnCtx(input, ctx); addIssueToContext(ctx, { code: ZodIssueCode.invalid_string, validation: { includes: check.value, position: check.position }, message: check.message, }); status.dirty(); } } else if (check.kind === "toLowerCase") { input.data = input.data.toLowerCase(); } else if (check.kind === "toUpperCase") { input.data = input.data.toUpperCase(); } else if (check.kind === "startsWith") { if (!input.data.startsWith(check.value)) { ctx = this._getOrReturnCtx(input, ctx); addIssueToContext(ctx, { code: ZodIssueCode.invalid_string, validation: { startsWith: check.value }, message: check.message, }); status.dirty(); } } else if (check.kind === "endsWith") { if (!input.data.endsWith(check.value)) { ctx = this._getOrReturnCtx(input, ctx); addIssueToContext(ctx, { code: ZodIssueCode.invalid_string, validation: { endsWith: check.value }, message: check.message, }); status.dirty(); } } else if (check.kind === "datetime") { const regex = datetimeRegex(check); if (!regex.test(input.data)) { ctx = this._getOrReturnCtx(input, ctx); addIssueToContext(ctx, { code: ZodIssueCode.invalid_string, validation: "datetime", message: check.message, }); status.dirty(); } } else if (check.kind === "date") { const regex = dateRegex; if (!regex.test(input.data)) { ctx = this._getOrReturnCtx(input, ctx); addIssueToContext(ctx, { code: ZodIssueCode.invalid_string, validation: "date", message: check.message, }); status.dirty(); } } else if (check.kind === "time") { const regex = timeRegex(check); if (!regex.test(input.data)) { ctx = this._getOrReturnCtx(input, ctx); addIssueToContext(ctx, { code: ZodIssueCode.invalid_string, validation: "time", message: check.message, }); status.dirty(); } } else if (check.kind === "duration") { if (!durationRegex.test(input.data)) { ctx = this._getOrReturnCtx(input, ctx); addIssueToContext(ctx, { validation: "duration", code: ZodIssueCode.invalid_string, message: check.message, }); status.dirty(); } } else if (check.kind === "ip") { if (!isValidIP(input.data, check.version)) { ctx = this._getOrReturnCtx(input, ctx); addIssueToContext(ctx, { validation: "ip", code: ZodIssueCode.invalid_string, message: check.message, }); status.dirty(); } } else if (check.kind === "jwt") { if (!isValidJWT(input.data, check.alg)) { ctx = this._getOrReturnCtx(input, ctx); addIssueToContext(ctx, { validation: "jwt", code: ZodIssueCode.invalid_string, message: check.message, }); status.dirty(); } } else if (check.kind === "cidr") { if (!isValidCidr(input.data, check.version)) { ctx = this._getOrReturnCtx(input, ctx); addIssueToContext(ctx, { validation: "cidr", code: ZodIssueCode.invalid_string, message: check.message, }); status.dirty(); } } else if (check.kind === "base64") { if (!base64Regex.test(input.data)) { ctx = this._getOrReturnCtx(input, ctx); addIssueToContext(ctx, { validation: "base64", code: ZodIssueCode.invalid_string, message: check.message, }); status.dirty(); } } else if (check.kind === "base64url") { if (!base64urlRegex.test(input.data)) { ctx = this._getOrReturnCtx(input, ctx); addIssueToContext(ctx, { validation: "base64url", code: ZodIssueCode.invalid_string, message: check.message, }); status.dirty(); } } else { util.assertNever(check); } } return { status: status.value, value: input.data }; } _regex(regex, validation, message) { return this.refinement((data) => regex.test(data), { validation, code: ZodIssueCode.invalid_string, ...errorUtil.errToObj(message), }); } _addCheck(check) { return new ZodString({ ...this._def, checks: [...this._def.checks, check], }); } email(message) { return this._addCheck({ kind: "email", ...errorUtil.errToObj(message) }); } url(message) { return this._addCheck({ kind: "url", ...errorUtil.errToObj(message) }); } emoji(message) { return this._addCheck({ kind: "emoji", ...errorUtil.errToObj(message) }); } uuid(message) { return this._addCheck({ kind: "uuid", ...errorUtil.errToObj(message) }); } nanoid(message) { return this._addCheck({ kind: "nanoid", ...errorUtil.errToObj(message) }); } cuid(message) { return this._addCheck({ kind: "cuid", ...errorUtil.errToObj(message) }); } cuid2(message) { return this._addCheck({ kind: "cuid2", ...errorUtil.errToObj(message) }); } ulid(message) { return this._addCheck({ kind: "ulid", ...errorUtil.errToObj(message) }); } base64(message) { return this._addCheck({ kind: "base64", ...errorUtil.errToObj(message) }); } base64url(message) { // base64url encoding is a modification of base64 that can safely be used in URLs and filenames return this._addCheck({ kind: "base64url", ...errorUtil.errToObj(message), }); } jwt(options) { return this._addCheck({ kind: "jwt", ...errorUtil.errToObj(options) }); } ip(options) { return this._addCheck({ kind: "ip", ...errorUtil.errToObj(options) }); } cidr(options) { return this._addCheck({ kind: "cidr", ...errorUtil.errToObj(options) }); } datetime(options) { var _a, _b; if (typeof options === "string") { return this._addCheck({ kind: "datetime", precision: null, offset: false, local: false, message: options, }); } return this._addCheck({ kind: "datetime", precision: typeof (options === null || options === void 0 ? void 0 : options.precision) === "undefined" ? null : options === null || options === void 0 ? void 0 : options.precision, offset: (_a = options === null || options === void 0 ? void 0 : options.offset) !== null && _a !== void 0 ? _a : false, local: (_b = options === null || options === void 0 ? void 0 : options.local) !== null && _b !== void 0 ? _b : false, ...errorUtil.errToObj(options === null || options === void 0 ? void 0 : options.message), }); } date(message) { return this._addCheck({ kind: "date", message }); } time(options) { if (typeof options === "string") { return this._addCheck({ kind: "time", precision: null, message: options, }); } return this._addCheck({ kind: "time", precision: typeof (options === null || options === void 0 ? void 0 : options.precision) === "undefined" ? null : options === null || options === void 0 ? void 0 : options.precision, ...errorUtil.errToObj(options === null || options === void 0 ? void 0 : options.message), }); } duration(message) { return this._addCheck({ kind: "duration", ...errorUtil.errToObj(message) }); } regex(regex, message) { return this._addCheck({ kind: "regex", regex: regex, ...errorUtil.errToObj(message), }); } includes(value, options) { return this._addCheck({ kind: "includes", value: value, position: options === null || options === void 0 ? void 0 : options.position, ...errorUtil.errToObj(options === null || options === void 0 ? void 0 : options.message), }); } startsWith(value, message) { return this._addCheck({ kind: "startsWith", value: value, ...errorUtil.errToObj(message), }); } endsWith(value, message) { return this._addCheck({ kind: "endsWith", value: value, ...errorUtil.errToObj(message), }); } min(minLength, message) { return this._addCheck({ kind: "min", value: minLength, ...errorUtil.errToObj(message), }); } max(maxLength, message) { return this._addCheck({ kind: "max", value: maxLength, ...errorUtil.errToObj(message), }); } length(len, message) { return this._addCheck({ kind: "length", value: len, ...errorUtil.errToObj(message), }); } /** * Equivalent to `.min(1)` */ nonempty(message) { return this.min(1, errorUtil.errToObj(message)); } trim() { return new ZodString({ ...this._def, checks: [...this._def.checks, { kind: "trim" }], }); } toLowerCase() { return new ZodString({ ...this._def, checks: [...this._def.checks, { kind: "toLowerCase" }], }); } toUpperCase() { return new ZodString({ ...this._def, checks: [...this._def.checks, { kind: "toUpperCase" }], }); } get isDatetime() { return !!this._def.checks.find((ch) => ch.kind === "datetime"); } get isDate() { return !!this._def.checks.find((ch) => ch.kind === "date"); } get isTime() { return !!this._def.checks.find((ch) => ch.kind === "time"); } get isDuration() { return !!this._def.checks.find((ch) => ch.kind === "duration"); } get isEmail() { return !!this._def.checks.find((ch) => ch.kind === "email"); } get isURL() { return !!this._def.checks.find((ch) => ch.kind === "url"); } get isEmoji() { return !!this._def.checks.find((ch) => ch.kind === "emoji"); } get isUUID() { return !!this._def.checks.find((ch) => ch.kind === "uuid"); } get isNANOID() { return !!this._def.checks.find((ch) => ch.kind === "nanoid"); } get isCUID() { return !!this._def.checks.find((ch) => ch.kind === "cuid"); } get isCUID2() { return !!this._def.checks.find((ch) => ch.kind === "cuid2"); } get isULID() { return !!this._def.checks.find((ch) => ch.kind === "ulid"); } get isIP() { return !!this._def.checks.find((ch) => ch.kind === "ip"); } get isCIDR() { return !!this._def.checks.find((ch) => ch.kind === "cidr"); } get isBase64() { return !!this._def.checks.find((ch) => ch.kind === "base64"); } get isBase64url() { // base64url encoding is a modification of base64 that can safely be used in URLs and filenames return !!this._def.checks.find((ch) => ch.kind === "base64url"); } get minLength() { let min = null; for (const ch of this._def.checks) { if (ch.kind === "min") { if (min === null || ch.value > min) min = ch.value; } } return min; } get maxLength() { let max = null; for (const ch of this._def.checks) { if (ch.kind === "max") { if (max === null || ch.value < max) max = ch.value; } } return max; } } ZodString.create = (params) => { var _a; return new ZodString({ checks: [], typeName: ZodFirstPartyTypeKind.ZodString, coerce: (_a = params === null || params === void 0 ? void 0 : params.coerce) !== null && _a !== void 0 ? _a : false, ...processCreateParams(params), }); }; // https://stackoverflow.com/questions/3966484/why-does-modulus-operator-return-fractional-number-in-javascript/31711034#31711034 function floatSafeRemainder(val, step) { const valDecCount = (val.toString().split(".")[1] || "").length; const stepDecCount = (step.toString().split(".")[1] || "").length; const decCount = valDecCount > stepDecCount ? valDecCount : stepDecCount; const valInt = parseInt(val.toFixed(decCount).replace(".", "")); const stepInt = parseInt(step.toFixed(decCount).replace(".", "")); return (valInt % stepInt) / Math.pow(10, decCount); } class ZodNumber extends ZodType { constructor() { super(...arguments); this.min = this.gte; this.max = this.lte; this.step = this.multipleOf; } _parse(input) { if (this._def.coerce) { input.data = Number(input.data); } const parsedType = this._getType(input); if (parsedType !== ZodParsedType.number) { const ctx = this._getOrReturnCtx(input); addIssueToContext(ctx, { code: ZodIssueCode.invalid_type, expected: ZodParsedType.number, received: ctx.parsedType, }); return INVALID; } let ctx = undefined; const status = new ParseStatus(); for (const check of this._def.checks) { if (check.kind === "int") { if (!util.isInteger(input.data)) { ctx = this._getOrReturnCtx(input, ctx); addIssueToContext(ctx, { code: ZodIssueCode.invalid_type, expected: "integer", received: "float", message: check.message, }); status.dirty(); } } else if (check.kind === "min") { const tooSmall = check.inclusive ? input.data < check.value : input.data <= check.value; if (tooSmall) { ctx = this._getOrReturnCtx(input, ctx); addIssueToContext(ctx, { code: ZodIssueCode.too_small, minimum: check.value, type: "number", inclusive: check.inclusive, exact: false, message: check.message, }); status.dirty(); } } else if (check.kind === "max") { const tooBig = check.inclusive ? input.data > check.value : input.data >= check.value; if (tooBig) { ctx = this._getOrReturnCtx(input, ctx); addIssueToContext(ctx, { code: ZodIssueCode.too_big, maximum: check.value, type: "number", inclusive: check.inclusive, exact: false, message: check.message, }); status.dirty(); } } else if (check.kind === "multipleOf") { if (floatSafeRemainder(input.data, check.value) !== 0) { ctx = this._getOrReturnCtx(input, ctx); addIssueToContext(ctx, { code: ZodIssueCode.not_multiple_of, multipleOf: check.value, message: check.message, }); status.dirty(); } } else if (check.kind === "finite") { if (!Number.isFinite(input.data)) { ctx = this._getOrReturnCtx(input, ctx); addIssueToContext(ctx, { code: ZodIssueCode.not_finite, message: check.message, }); status.dirty(); } } else { util.assertNever(check); } } return { status: status.value, value: input.data }; } gte(value, message) { return this.setLimit("min", value, true, errorUtil.toString(message)); } gt(value, message) { return this.setLimit("min", value, false, errorUtil.toString(message)); } lte(value, message) { return this.setLimit("max", value, true, errorUtil.toString(message)); } lt(value, message) { return this.setLimit("max", value, false, errorUtil.toString(message)); } setLimit(kind, value, inclusive, message) { return new ZodNumber({ ...this._def, checks: [ ...this._def.checks, { kind, value, inclusive, message: errorUtil.toString(message), }, ], }); } _addCheck(check) { return new ZodNumber({ ...this._def, checks: [...this._def.checks, check], }); } int(message) { return this._addCheck({ kind: "int", message: errorUtil.toString(message), }); } positive(message) { return this._addCheck({ kind: "min", value: 0, inclusive: false, message: errorUtil.toString(message), }); } negative(message) { return this._addCheck({ kind: "max", value: 0, inclusive: false, message: errorUtil.toString(message), }); } nonpositive(message) { return this._addCheck({ kind: "max", value: 0, inclusive: true, message: errorUtil.toString(message), }); } nonnegative(message) { return this._addCheck({ kind: "min", value: 0, inclusive: true, message: errorUtil.toString(message), }); } multipleOf(value, message) { return this._addCheck({ kind: "multipleOf", value: value, message: errorUtil.toString(message), }); } finite(message) { return this._addCheck({ kind: "finite", message: errorUtil.toString(message), }); } safe(message) { return this._addCheck({ kind: "min", inclusive: true, value: Number.MIN_SAFE_INTEGER, message: errorUtil.toString(message), })._addCheck({ kind: "max", inclusive: true, value: Number.MAX_SAFE_INTEGER, message: errorUtil.toString(message), }); } get minValue() { let min = null; for (const ch of this._def.checks) { if (ch.kind === "min") { if (min === null || ch.value > min) min = ch.value; } } return min; } get maxValue() { let max = null; for (const ch of this._def.checks) { if (ch.kind === "max") { if (max === null || ch.value < max) max = ch.value; } } return max; } get isInt() { return !!this._def.checks.find((ch) => ch.kind === "int" || (ch.kind === "multipleOf" && util.isInteger(ch.value))); } get isFinite() { let max = null, min = null; for (const ch of this._def.checks) { if (ch.kind === "finite" || ch.kind === "int" || ch.kind === "multipleOf") { return true; } else if (ch.kind === "min") { if (min === null || ch.value > min) min = ch.value; } else if (ch.kind === "max") { if (max === null || ch.value < max) max = ch.value; } } return Number.isFinite(min) && Number.isFinite(max); } } ZodNumber.create = (params) => { return new ZodNumber({ checks: [], typeName: ZodFirstPartyTypeKind.ZodNumber, coerce: (params === null || params === void 0 ? void 0 : params.coerce) || false, ...processCreateParams(params), }); }; class ZodBigInt extends ZodType { constructor() { super(...arguments); this.min = this.gte; this.max = this.lte; } _parse(input) { if (this._def.coerce) { try { input.data = BigInt(input.data); } catch (_a) { return this._getInvalidInput(input); } } const parsedType = this._getType(input); if (parsedType !== ZodParsedType.bigint) { return this._getInvalidInput(input); } let ctx = undefined; const status = new ParseStatus(); for (const check of this._def.checks) { if (check.kind === "min") { const tooSmall = check.inclusive ? input.data < check.value : input.data <= check.value; if (tooSmall) { ctx = this._getOrReturnCtx(input, ctx); addIssueToContext(ctx, { code: ZodIssueCode.too_small, type: "bigint", minimum: check.value, inclusive: check.inclusive, message: check.message, }); status.dirty(); } } else if (check.kind === "max") { const tooBig = check.inclusive ? input.data > check.value : input.data >= check.value; if (tooBig) { ctx = this._getOrReturnCtx(input, ctx); addIssueToContext(ctx, { code: ZodIssueCode.too_big, type: "bigint", maximum: check.value, inclusive: check.inclusive, message: check.message, }); status.dirty(); } } else if (check.kind === "multipleOf") { if (input.data % check.value !== BigInt(0)) { ctx = this._getOrReturnCtx(input, ctx); addIssueToContext(ctx, { code: ZodIssueCode.not_multiple_of, multipleOf: check.value, message: check.message, }); status.dirty(); } } else { util.assertNever(check); } } return { status: status.value, value: input.data }; } _getInvalidInput(input) { const ctx = this._getOrReturnCtx(input); addIssueToContext(ctx, { code: ZodIssueCode.invalid_type, expected: ZodParsedType.bigint, received: ctx.parsedType, }); return INVALID; } gte(value, message) { return this.setLimit("min", value, true, errorUtil.toString(message)); } gt(value, message) { return this.setLimit("min", value, false, errorUtil.toString(message)); } lte(value, message) { return this.setLimit("max", value, true, errorUtil.toString(message)); } lt(value, message) { return this.setLimit("max", value, false, errorUtil.toString(message)); } setLimit(kind, value, inclusive, message) { return new ZodBigInt({ ...this._def, checks: [ ...this._def.checks, { kind, value, inclusive, message: errorUtil.toString(message), }, ], }); } _addCheck(check) { return new ZodBigInt({ ...this._def, checks: [...this._def.checks, check], }); } positive(message) { return this._addCheck({ kind: "min", value: BigInt(0), inclusive: false, message: errorUtil.toString(message), }); } negative(message) { return this._addCheck({ kind: "max", value: BigInt(0), inclusive: false, message: errorUtil.toString(message), }); } nonpositive(message) { return this._addCheck({ kind: "max", value: BigInt(0), inclusive: true, message: errorUtil.toString(message), }); } nonnegative(message) { return this._addCheck({ kind: "min", value: BigInt(0), inclusive: true, message: errorUtil.toString(message), }); } multipleOf(value, message) { return this._addCheck({ kind: "multipleOf", value, message: errorUtil.toString(message), }); } get minValue() { let min = null; for (const ch of this._def.checks) { if (ch.kind === "min") { if (min === null || ch.value > min) min = ch.value; } } return min; } get maxValue() { let max = null; for (const ch of this._def.checks) { if (ch.kind === "max") { if (max === null || ch.value < max) max = ch.value; } } return max; } } ZodBigInt.create = (params) => { var _a; return new ZodBigInt({ checks: [], typeName: ZodFirstPartyTypeKind.ZodBigInt, coerce: (_a = params === null || params === void 0 ? void 0 : params.coerce) !== null && _a !== void 0 ? _a : false, ...processCreateParams(params), }); }; class ZodBoolean extends ZodType { _parse(input) { if (this._def.coerce) { input.data = Boolean(input.data); } const parsedType = this._getType(input); if (parsedType !== ZodParsedType.boolean) { const ctx = this._getOrReturnCtx(input); addIssueToContext(ctx, { code: ZodIssueCode.invalid_type, expected: ZodParsedType.boolean, received: ctx.parsedType, }); return INVALID; } return OK(input.data); } } ZodBoolean.create = (params) => { return new ZodBoolean({ typeName: ZodFirstPartyTypeKind.ZodBoolean, coerce: (params === null || params === void 0 ? void 0 : params.coerce) || false, ...processCreateParams(params), }); }; class ZodDate extends ZodType { _parse(input) { if (this._def.coerce) { input.data = new Date(input.data); } const parsedType = this._getType(input); if (parsedType !== ZodParsedType.date) { const ctx = this._getOrReturnCtx(input); addIssueToContext(ctx, { code: ZodIssueCode.invalid_type, expected: ZodParsedType.date, received: ctx.parsedType, }); return INVALID; } if (isNaN(input.data.getTime())) { const ctx = this._getOrReturnCtx(input); addIssueToContext(ctx, { code: ZodIssueCode.invalid_date, }); return INVALID; } const status = new ParseStatus(); let ctx = undefined; for (const check of this._def.checks) { if (check.kind === "min") { if (input.data.getTime() < check.value) { ctx = this._getOrReturnCtx(input, ctx); addIssueToContext(ctx, { code: ZodIssueCode.too_small, message: check.message, inclusive: true, exact: false, minimum: check.value, type: "date", }); status.dirty(); } } else if (check.kind === "max") { if (input.data.getTime() > check.value) { ctx = this._getOrReturnCtx(input, ctx); addIssueToContext(ctx, { code: ZodIssueCode.too_big, message: check.message, inclusive: true, exact: false, maximum: check.value, type: "date", }); status.dirty(); } } else { util.assertNever(check); } } return { status: status.value, value: new Date(input.data.getTime()), }; } _addCheck(check) { return new ZodDate({ ...this._def, checks: [...this._def.checks, check], }); } min(minDate, message) { return this._addCheck({ kind: "min", value: minDate.getTime(), message: errorUtil.toString(message), }); } max(maxDate, message) { return this._addCheck({ kind: "max", value: maxDate.getTime(), message: errorUtil.toString(message), }); } get minDate() { let min = null; for (const ch of this._def.checks) { if (ch.kind === "min") { if (min === null || ch.value > min) min = ch.value; } } return min != null ? new Date(min) : null; } get maxDate() { let max = null; for (const ch of this._def.checks) { if (ch.kind === "max") { if (max === null || ch.value < max) max = ch.value; } } return max != null ? new Date(max) : null; } } ZodDate.create = (params) => { return new ZodDate({ checks: [], coerce: (params === null || params === void 0 ? void 0 : params.coerce) || false, typeName: ZodFirstPartyTypeKind.ZodDate, ...processCreateParams(params), }); }; class ZodSymbol extends ZodType { _parse(input) { const parsedType = this._getType(input); if (parsedType !== ZodParsedType.symbol) { const ctx = this._getOrReturnCtx(input); addIssueToContext(ctx, { code: ZodIssueCode.invalid_type, expected: ZodParsedType.symbol, received: ctx.parsedType, }); return INVALID; } return OK(input.data); } } ZodSymbol.create = (params) => { return new ZodSymbol({ typeName: ZodFirstPartyTypeKind.ZodSymbol, ...processCreateParams(params), }); }; class ZodUndefined extends ZodType { _parse(input) { const parsedType = this._getType(input); if (parsedType !== ZodParsedType.undefined) { const ctx = this._getOrReturnCtx(input); addIssueToContext(ctx, { code: ZodIssueCode.invalid_type, expected: ZodParsedType.undefined, received: ctx.parsedType, }); return INVALID; } return OK(input.data); } } ZodUndefined.create = (params) => { return new ZodUndefined({ typeName: ZodFirstPartyTypeKind.ZodUndefined, ...processCreateParams(params), }); }; class ZodNull extends ZodType { _parse(input) { const parsedType = this._getType(input); if (parsedType !== ZodParsedType.null) { const ctx = this._getOrReturnCtx(input); addIssueToContext(ctx, { code: ZodIssueCode.invalid_type, expected: ZodParsedType.null, received: ctx.parsedType, }); return INVALID; } return OK(input.data); } } ZodNull.create = (params) => { return new ZodNull({ typeName: ZodFirstPartyTypeKind.ZodNull, ...processCreateParams(params), }); }; class ZodAny extends ZodType { constructor() { super(...arguments); // to prevent instances of other classes from extending ZodAny. this causes issues with catchall in ZodObject. this._any = true; } _parse(input) { return OK(input.data); } } ZodAny.create = (params) => { return new ZodAny({ typeName: ZodFirstPartyTypeKind.ZodAny, ...processCreateParams(params), }); }; class ZodUnknown extends ZodType { constructor() { super(...arguments); // required this._unknown = true; } _parse(input) { return OK(input.data); } } ZodUnknown.create = (params) => { return new ZodUnknown({ typeName: ZodFirstPartyTypeKind.ZodUnknown, ...processCreateParams(params), }); }; class ZodNever extends ZodType { _parse(input) { const ctx = this._getOrReturnCtx(input); addIssueToContext(ctx, { code: ZodIssueCode.invalid_type, expected: ZodParsedType.never, received: ctx.parsedType, }); return INVALID; } } ZodNever.create = (params) => { return new ZodNever({ typeName: ZodFirstPartyTypeKind.ZodNever, ...processCreateParams(params), }); }; class ZodVoid extends ZodType { _parse(input) { const parsedType = this._getType(input); if (parsedType !== ZodParsedType.undefined) { const ctx = this._getOrReturnCtx(input); addIssueToContext(ctx, { code: ZodIssueCode.invalid_type, expected: ZodParsedType.void, received: ctx.parsedType, }); return INVALID; } return OK(input.data); } } ZodVoid.create = (params) => { return new ZodVoid({ typeName: ZodFirstPartyTypeKind.ZodVoid, ...processCreateParams(params), }); }; class ZodArray extends ZodType { _parse(input) { const { ctx, status } = this._processInputParams(input); const def = this._def; if (ctx.parsedType !== ZodParsedType.array) { addIssueToContext(ctx, { code: ZodIssueCode.invalid_type, expected: ZodParsedType.array, received: ctx.parsedType, }); return INVALID; } if (def.exactLength !== null) { const tooBig = ctx.data.length > def.exactLength.value; const tooSmall = ctx.data.length < def.exactLength.value; if (tooBig || tooSmall) { addIssueToContext(ctx, { code: tooBig ? ZodIssueCode.too_big : ZodIssueCode.too_small, minimum: (tooSmall ? def.exactLength.value : undefined), maximum: (tooBig ? def.exactLength.value : undefined), type: "array", inclusive: true, exact: true, message: def.exactLength.message, }); status.dirty(); } } if (def.minLength !== null) { if (ctx.data.length < def.minLength.value) { addIssueToContext(ctx, { code: ZodIssueCode.too_small, minimum: def.minLength.value, type: "array", inclusive: true, exact: false, message: def.minLength.message, }); status.dirty(); } } if (def.maxLength !== null) { if (ctx.data.length > def.maxLength.value) { addIssueToContext(ctx, { code: ZodIssueCode.too_big, maximum: def.maxLength.value, type: "array", inclusive: true, exact: false, message: def.maxLength.message, }); status.dirty(); } } if (ctx.common.async) { return Promise.all([...ctx.data].map((item, i) => { return def.type._parseAsync(new ParseInputLazyPath(ctx, item, ctx.path, i)); })).then((result) => { return ParseStatus.mergeArray(status, result); }); } const result = [...ctx.data].map((item, i) => { return def.type._parseSync(new ParseInputLazyPath(ctx, item, ctx.path, i)); }); return ParseStatus.mergeArray(status, result); } get element() { return this._def.type; } min(minLength, message) { return new ZodArray({ ...this._def, minLength: { value: minLength, message: errorUtil.toString(message) }, }); } max(maxLength, message) { return new ZodArray({ ...this._def, maxLength: { value: maxLength, message: errorUtil.toString(message) }, }); } length(len, message) { return new ZodArray({ ...this._def, exactLength: { value: len, message: errorUtil.toString(message) }, }); } nonempty(message) { return this.min(1, message); } } ZodArray.create = (schema, params) => { return new ZodArray({ type: schema, minLength: null, maxLength: null, exactLength: null, typeName: ZodFirstPartyTypeKind.ZodArray, ...processCreateParams(params), }); }; function deepPartialify(schema) { if (schema instanceof ZodObject) { const newShape = {}; for (const key in schema.shape) { const fieldSchema = schema.shape[key]; newShape[key] = ZodOptional.create(deepPartialify(fieldSchema)); } return new ZodObject({ ...schema._def, shape: () => newShape, }); } else if (schema instanceof ZodArray) { return new ZodArray({ ...schema._def, type: deepPartialify(schema.element), }); } else if (schema instanceof ZodOptional) { return ZodOptional.create(deepPartialify(schema.unwrap())); } else if (schema instanceof ZodNullable) { return ZodNullable.create(deepPartialify(schema.unwrap())); } else if (schema instanceof ZodTuple) { return ZodTuple.create(schema.items.map((item) => deepPartialify(item))); } else { return schema; } } class ZodObject extends ZodType { constructor() { super(...arguments); this._cached = null; /** * @deprecated In most cases, this is no longer needed - unknown properties are now silently stripped. * If you want to pass through unknown properties, use `.passthrough()` instead. */ this.nonstrict = this.passthrough; // extend< // Augmentation extends ZodRawShape, // NewOutput extends util.flatten<{ // [k in keyof Augmentation | keyof Output]: k extends keyof Augmentation // ? Augmentation[k]["_output"] // : k extends keyof Output // ? Output[k] // : never; // }>, // NewInput extends util.flatten<{ // [k in keyof Augmentation | keyof Input]: k extends keyof Augmentation // ? Augmentation[k]["_input"] // : k extends keyof Input // ? Input[k] // : never; // }> // >( // augmentation: Augmentation // ): ZodObject< // extendShape, // UnknownKeys, // Catchall, // NewOutput, // NewInput // > { // return new ZodObject({ // ...this._def, // shape: () => ({ // ...this._def.shape(), // ...augmentation, // }), // }) as any; // } /** * @deprecated Use `.extend` instead * */ this.augment = this.extend; } _getCached() { if (this._cached !== null) return this._cached; const shape = this._def.shape(); const keys = util.objectKeys(shape); return (this._cached = { shape, keys }); } _parse(input) { const parsedType = this._getType(input); if (parsedType !== ZodParsedType.object) { const ctx = this._getOrReturnCtx(input); addIssueToContext(ctx, { code: ZodIssueCode.invalid_type, expected: ZodParsedType.object, received: ctx.parsedType, }); return INVALID; } const { status, ctx } = this._processInputParams(input); const { shape, keys: shapeKeys } = this._getCached(); const extraKeys = []; if (!(this._def.catchall instanceof ZodNever && this._def.unknownKeys === "strip")) { for (const key in ctx.data) { if (!shapeKeys.includes(key)) { extraKeys.push(key); } } } const pairs = []; for (const key of shapeKeys) { const keyValidator = shape[key]; const value = ctx.data[key]; pairs.push({ key: { status: "valid", value: key }, value: keyValidator._parse(new ParseInputLazyPath(ctx, value, ctx.path, key)), alwaysSet: key in ctx.data, }); } if (this._def.catchall instanceof ZodNever) { const unknownKeys = this._def.unknownKeys; if (unknownKeys === "passthrough") { for (const key of extraKeys) { pairs.push({ key: { status: "valid", value: key }, value: { status: "valid", value: ctx.data[key] }, }); } } else if (unknownKeys === "strict") { if (extraKeys.length > 0) { addIssueToContext(ctx, { code: ZodIssueCode.unrecognized_keys, keys: extraKeys, }); status.dirty(); } } else if (unknownKeys === "strip") ; else { throw new Error(`Internal ZodObject error: invalid unknownKeys value.`); } } else { // run catchall validation const catchall = this._def.catchall; for (const key of extraKeys) { const value = ctx.data[key]; pairs.push({ key: { status: "valid", value: key }, value: catchall._parse(new ParseInputLazyPath(ctx, value, ctx.path, key) //, ctx.child(key), value, getParsedType(value) ), alwaysSet: key in ctx.data, }); } } if (ctx.common.async) { return Promise.resolve() .then(async () => { const syncPairs = []; for (const pair of pairs) { const key = await pair.key; const value = await pair.value; syncPairs.push({ key, value, alwaysSet: pair.alwaysSet, }); } return syncPairs; }) .then((syncPairs) => { return ParseStatus.mergeObjectSync(status, syncPairs); }); } else { return ParseStatus.mergeObjectSync(status, pairs); } } get shape() { return this._def.shape(); } strict(message) { errorUtil.errToObj; return new ZodObject({ ...this._def, unknownKeys: "strict", ...(message !== undefined ? { errorMap: (issue, ctx) => { var _a, _b, _c, _d; const defaultError = (_c = (_b = (_a = this._def).errorMap) === null || _b === void 0 ? void 0 : _b.call(_a, issue, ctx).message) !== null && _c !== void 0 ? _c : ctx.defaultError; if (issue.code === "unrecognized_keys") return { message: (_d = errorUtil.errToObj(message).message) !== null && _d !== void 0 ? _d : defaultError, }; return { message: defaultError, }; }, } : {}), }); } strip() { return new ZodObject({ ...this._def, unknownKeys: "strip", }); } passthrough() { return new ZodObject({ ...this._def, unknownKeys: "passthrough", }); } // const AugmentFactory = // (def: Def) => // ( // augmentation: Augmentation // ): ZodObject< // extendShape, Augmentation>, // Def["unknownKeys"], // Def["catchall"] // > => { // return new ZodObject({ // ...def, // shape: () => ({ // ...def.shape(), // ...augmentation, // }), // }) as any; // }; extend(augmentation) { return new ZodObject({ ...this._def, shape: () => ({ ...this._def.shape(), ...augmentation, }), }); } /** * Prior to zod@1.0.12 there was a bug in the * inferred type of merged objects. Please * upgrade if you are experiencing issues. */ merge(merging) { const merged = new ZodObject({ unknownKeys: merging._def.unknownKeys, catchall: merging._def.catchall, shape: () => ({ ...this._def.shape(), ...merging._def.shape(), }), typeName: ZodFirstPartyTypeKind.ZodObject, }); return merged; } // merge< // Incoming extends AnyZodObject, // Augmentation extends Incoming["shape"], // NewOutput extends { // [k in keyof Augmentation | keyof Output]: k extends keyof Augmentation // ? Augmentation[k]["_output"] // : k extends keyof Output // ? Output[k] // : never; // }, // NewInput extends { // [k in keyof Augmentation | keyof Input]: k extends keyof Augmentation // ? Augmentation[k]["_input"] // : k extends keyof Input // ? Input[k] // : never; // } // >( // merging: Incoming // ): ZodObject< // extendShape>, // Incoming["_def"]["unknownKeys"], // Incoming["_def"]["catchall"], // NewOutput, // NewInput // > { // const merged: any = new ZodObject({ // unknownKeys: merging._def.unknownKeys, // catchall: merging._def.catchall, // shape: () => // objectUtil.mergeShapes(this._def.shape(), merging._def.shape()), // typeName: ZodFirstPartyTypeKind.ZodObject, // }) as any; // return merged; // } setKey(key, schema) { return this.augment({ [key]: schema }); } // merge( // merging: Incoming // ): //ZodObject = (merging) => { // ZodObject< // extendShape>, // Incoming["_def"]["unknownKeys"], // Incoming["_def"]["catchall"] // > { // // const mergedShape = objectUtil.mergeShapes( // // this._def.shape(), // // merging._def.shape() // // ); // const merged: any = new ZodObject({ // unknownKeys: merging._def.unknownKeys, // catchall: merging._def.catchall, // shape: () => // objectUtil.mergeShapes(this._def.shape(), merging._def.shape()), // typeName: ZodFirstPartyTypeKind.ZodObject, // }) as any; // return merged; // } catchall(index) { return new ZodObject({ ...this._def, catchall: index, }); } pick(mask) { const shape = {}; util.objectKeys(mask).forEach((key) => { if (mask[key] && this.shape[key]) { shape[key] = this.shape[key]; } }); return new ZodObject({ ...this._def, shape: () => shape, }); } omit(mask) { const shape = {}; util.objectKeys(this.shape).forEach((key) => { if (!mask[key]) { shape[key] = this.shape[key]; } }); return new ZodObject({ ...this._def, shape: () => shape, }); } /** * @deprecated */ deepPartial() { return deepPartialify(this); } partial(mask) { const newShape = {}; util.objectKeys(this.shape).forEach((key) => { const fieldSchema = this.shape[key]; if (mask && !mask[key]) { newShape[key] = fieldSchema; } else { newShape[key] = fieldSchema.optional(); } }); return new ZodObject({ ...this._def, shape: () => newShape, }); } required(mask) { const newShape = {}; util.objectKeys(this.shape).forEach((key) => { if (mask && !mask[key]) { newShape[key] = this.shape[key]; } else { const fieldSchema = this.shape[key]; let newField = fieldSchema; while (newField instanceof ZodOptional) { newField = newField._def.innerType; } newShape[key] = newField; } }); return new ZodObject({ ...this._def, shape: () => newShape, }); } keyof() { return createZodEnum(util.objectKeys(this.shape)); } } ZodObject.create = (shape, params) => { return new ZodObject({ shape: () => shape, unknownKeys: "strip", catchall: ZodNever.create(), typeName: ZodFirstPartyTypeKind.ZodObject, ...processCreateParams(params), }); }; ZodObject.strictCreate = (shape, params) => { return new ZodObject({ shape: () => shape, unknownKeys: "strict", catchall: ZodNever.create(), typeName: ZodFirstPartyTypeKind.ZodObject, ...processCreateParams(params), }); }; ZodObject.lazycreate = (shape, params) => { return new ZodObject({ shape, unknownKeys: "strip", catchall: ZodNever.create(), typeName: ZodFirstPartyTypeKind.ZodObject, ...processCreateParams(params), }); }; class ZodUnion extends ZodType { _parse(input) { const { ctx } = this._processInputParams(input); const options = this._def.options; function handleResults(results) { // return first issue-free validation if it exists for (const result of results) { if (result.result.status === "valid") { return result.result; } } for (const result of results) { if (result.result.status === "dirty") { // add issues from dirty option ctx.common.issues.push(...result.ctx.common.issues); return result.result; } } // return invalid const unionErrors = results.map((result) => new ZodError(result.ctx.common.issues)); addIssueToContext(ctx, { code: ZodIssueCode.invalid_union, unionErrors, }); return INVALID; } if (ctx.common.async) { return Promise.all(options.map(async (option) => { const childCtx = { ...ctx, common: { ...ctx.common, issues: [], }, parent: null, }; return { result: await option._parseAsync({ data: ctx.data, path: ctx.path, parent: childCtx, }), ctx: childCtx, }; })).then(handleResults); } else { let dirty = undefined; const issues = []; for (const option of options) { const childCtx = { ...ctx, common: { ...ctx.common, issues: [], }, parent: null, }; const result = option._parseSync({ data: ctx.data, path: ctx.path, parent: childCtx, }); if (result.status === "valid") { return result; } else if (result.status === "dirty" && !dirty) { dirty = { result, ctx: childCtx }; } if (childCtx.common.issues.length) { issues.push(childCtx.common.issues); } } if (dirty) { ctx.common.issues.push(...dirty.ctx.common.issues); return dirty.result; } const unionErrors = issues.map((issues) => new ZodError(issues)); addIssueToContext(ctx, { code: ZodIssueCode.invalid_union, unionErrors, }); return INVALID; } } get options() { return this._def.options; } } ZodUnion.create = (types, params) => { return new ZodUnion({ options: types, typeName: ZodFirstPartyTypeKind.ZodUnion, ...processCreateParams(params), }); }; ///////////////////////////////////////////////////// ///////////////////////////////////////////////////// ////////// ////////// ////////// ZodDiscriminatedUnion ////////// ////////// ////////// ///////////////////////////////////////////////////// ///////////////////////////////////////////////////// const getDiscriminator = (type) => { if (type instanceof ZodLazy) { return getDiscriminator(type.schema); } else if (type instanceof ZodEffects) { return getDiscriminator(type.innerType()); } else if (type instanceof ZodLiteral) { return [type.value]; } else if (type instanceof ZodEnum) { return type.options; } else if (type instanceof ZodNativeEnum) { // eslint-disable-next-line ban/ban return util.objectValues(type.enum); } else if (type instanceof ZodDefault) { return getDiscriminator(type._def.innerType); } else if (type instanceof ZodUndefined) { return [undefined]; } else if (type instanceof ZodNull) { return [null]; } else if (type instanceof ZodOptional) { return [undefined, ...getDiscriminator(type.unwrap())]; } else if (type instanceof ZodNullable) { return [null, ...getDiscriminator(type.unwrap())]; } else if (type instanceof ZodBranded) { return getDiscriminator(type.unwrap()); } else if (type instanceof ZodReadonly) { return getDiscriminator(type.unwrap()); } else if (type instanceof ZodCatch) { return getDiscriminator(type._def.innerType); } else { return []; } }; class ZodDiscriminatedUnion extends ZodType { _parse(input) { const { ctx } = this._processInputParams(input); if (ctx.parsedType !== ZodParsedType.object) { addIssueToContext(ctx, { code: ZodIssueCode.invalid_type, expected: ZodParsedType.object, received: ctx.parsedType, }); return INVALID; } const discriminator = this.discriminator; const discriminatorValue = ctx.data[discriminator]; const option = this.optionsMap.get(discriminatorValue); if (!option) { addIssueToContext(ctx, { code: ZodIssueCode.invalid_union_discriminator, options: Array.from(this.optionsMap.keys()), path: [discriminator], }); return INVALID; } if (ctx.common.async) { return option._parseAsync({ data: ctx.data, path: ctx.path, parent: ctx, }); } else { return option._parseSync({ data: ctx.data, path: ctx.path, parent: ctx, }); } } get discriminator() { return this._def.discriminator; } get options() { return this._def.options; } get optionsMap() { return this._def.optionsMap; } /** * The constructor of the discriminated union schema. Its behaviour is very similar to that of the normal z.union() constructor. * However, it only allows a union of objects, all of which need to share a discriminator property. This property must * have a different value for each object in the union. * @param discriminator the name of the discriminator property * @param types an array of object schemas * @param params */ static create(discriminator, options, params) { // Get all the valid discriminator values const optionsMap = new Map(); // try { for (const type of options) { const discriminatorValues = getDiscriminator(type.shape[discriminator]); if (!discriminatorValues.length) { throw new Error(`A discriminator value for key \`${discriminator}\` could not be extracted from all schema options`); } for (const value of discriminatorValues) { if (optionsMap.has(value)) { throw new Error(`Discriminator property ${String(discriminator)} has duplicate value ${String(value)}`); } optionsMap.set(value, type); } } return new ZodDiscriminatedUnion({ typeName: ZodFirstPartyTypeKind.ZodDiscriminatedUnion, discriminator, options, optionsMap, ...processCreateParams(params), }); } } function mergeValues(a, b) { const aType = getParsedType(a); const bType = getParsedType(b); if (a === b) { return { valid: true, data: a }; } else if (aType === ZodParsedType.object && bType === ZodParsedType.object) { const bKeys = util.objectKeys(b); const sharedKeys = util .objectKeys(a) .filter((key) => bKeys.indexOf(key) !== -1); const newObj = { ...a, ...b }; for (const key of sharedKeys) { const sharedValue = mergeValues(a[key], b[key]); if (!sharedValue.valid) { return { valid: false }; } newObj[key] = sharedValue.data; } return { valid: true, data: newObj }; } else if (aType === ZodParsedType.array && bType === ZodParsedType.array) { if (a.length !== b.length) { return { valid: false }; } const newArray = []; for (let index = 0; index < a.length; index++) { const itemA = a[index]; const itemB = b[index]; const sharedValue = mergeValues(itemA, itemB); if (!sharedValue.valid) { return { valid: false }; } newArray.push(sharedValue.data); } return { valid: true, data: newArray }; } else if (aType === ZodParsedType.date && bType === ZodParsedType.date && +a === +b) { return { valid: true, data: a }; } else { return { valid: false }; } } class ZodIntersection extends ZodType { _parse(input) { const { status, ctx } = this._processInputParams(input); const handleParsed = (parsedLeft, parsedRight) => { if (isAborted(parsedLeft) || isAborted(parsedRight)) { return INVALID; } const merged = mergeValues(parsedLeft.value, parsedRight.value); if (!merged.valid) { addIssueToContext(ctx, { code: ZodIssueCode.invalid_intersection_types, }); return INVALID; } if (isDirty(parsedLeft) || isDirty(parsedRight)) { status.dirty(); } return { status: status.value, value: merged.data }; }; if (ctx.common.async) { return Promise.all([ this._def.left._parseAsync({ data: ctx.data, path: ctx.path, parent: ctx, }), this._def.right._parseAsync({ data: ctx.data, path: ctx.path, parent: ctx, }), ]).then(([left, right]) => handleParsed(left, right)); } else { return handleParsed(this._def.left._parseSync({ data: ctx.data, path: ctx.path, parent: ctx, }), this._def.right._parseSync({ data: ctx.data, path: ctx.path, parent: ctx, })); } } } ZodIntersection.create = (left, right, params) => { return new ZodIntersection({ left: left, right: right, typeName: ZodFirstPartyTypeKind.ZodIntersection, ...processCreateParams(params), }); }; class ZodTuple extends ZodType { _parse(input) { const { status, ctx } = this._processInputParams(input); if (ctx.parsedType !== ZodParsedType.array) { addIssueToContext(ctx, { code: ZodIssueCode.invalid_type, expected: ZodParsedType.array, received: ctx.parsedType, }); return INVALID; } if (ctx.data.length < this._def.items.length) { addIssueToContext(ctx, { code: ZodIssueCode.too_small, minimum: this._def.items.length, inclusive: true, exact: false, type: "array", }); return INVALID; } const rest = this._def.rest; if (!rest && ctx.data.length > this._def.items.length) { addIssueToContext(ctx, { code: ZodIssueCode.too_big, maximum: this._def.items.length, inclusive: true, exact: false, type: "array", }); status.dirty(); } const items = [...ctx.data] .map((item, itemIndex) => { const schema = this._def.items[itemIndex] || this._def.rest; if (!schema) return null; return schema._parse(new ParseInputLazyPath(ctx, item, ctx.path, itemIndex)); }) .filter((x) => !!x); // filter nulls if (ctx.common.async) { return Promise.all(items).then((results) => { return ParseStatus.mergeArray(status, results); }); } else { return ParseStatus.mergeArray(status, items); } } get items() { return this._def.items; } rest(rest) { return new ZodTuple({ ...this._def, rest, }); } } ZodTuple.create = (schemas, params) => { if (!Array.isArray(schemas)) { throw new Error("You must pass an array of schemas to z.tuple([ ... ])"); } return new ZodTuple({ items: schemas, typeName: ZodFirstPartyTypeKind.ZodTuple, rest: null, ...processCreateParams(params), }); }; class ZodRecord extends ZodType { get keySchema() { return this._def.keyType; } get valueSchema() { return this._def.valueType; } _parse(input) { const { status, ctx } = this._processInputParams(input); if (ctx.parsedType !== ZodParsedType.object) { addIssueToContext(ctx, { code: ZodIssueCode.invalid_type, expected: ZodParsedType.object, received: ctx.parsedType, }); return INVALID; } const pairs = []; const keyType = this._def.keyType; const valueType = this._def.valueType; for (const key in ctx.data) { pairs.push({ key: keyType._parse(new ParseInputLazyPath(ctx, key, ctx.path, key)), value: valueType._parse(new ParseInputLazyPath(ctx, ctx.data[key], ctx.path, key)), alwaysSet: key in ctx.data, }); } if (ctx.common.async) { return ParseStatus.mergeObjectAsync(status, pairs); } else { return ParseStatus.mergeObjectSync(status, pairs); } } get element() { return this._def.valueType; } static create(first, second, third) { if (second instanceof ZodType) { return new ZodRecord({ keyType: first, valueType: second, typeName: ZodFirstPartyTypeKind.ZodRecord, ...processCreateParams(third), }); } return new ZodRecord({ keyType: ZodString.create(), valueType: first, typeName: ZodFirstPartyTypeKind.ZodRecord, ...processCreateParams(second), }); } } class ZodMap extends ZodType { get keySchema() { return this._def.keyType; } get valueSchema() { return this._def.valueType; } _parse(input) { const { status, ctx } = this._processInputParams(input); if (ctx.parsedType !== ZodParsedType.map) { addIssueToContext(ctx, { code: ZodIssueCode.invalid_type, expected: ZodParsedType.map, received: ctx.parsedType, }); return INVALID; } const keyType = this._def.keyType; const valueType = this._def.valueType; const pairs = [...ctx.data.entries()].map(([key, value], index) => { return { key: keyType._parse(new ParseInputLazyPath(ctx, key, ctx.path, [index, "key"])), value: valueType._parse(new ParseInputLazyPath(ctx, value, ctx.path, [index, "value"])), }; }); if (ctx.common.async) { const finalMap = new Map(); return Promise.resolve().then(async () => { for (const pair of pairs) { const key = await pair.key; const value = await pair.value; if (key.status === "aborted" || value.status === "aborted") { return INVALID; } if (key.status === "dirty" || value.status === "dirty") { status.dirty(); } finalMap.set(key.value, value.value); } return { status: status.value, value: finalMap }; }); } else { const finalMap = new Map(); for (const pair of pairs) { const key = pair.key; const value = pair.value; if (key.status === "aborted" || value.status === "aborted") { return INVALID; } if (key.status === "dirty" || value.status === "dirty") { status.dirty(); } finalMap.set(key.value, value.value); } return { status: status.value, value: finalMap }; } } } ZodMap.create = (keyType, valueType, params) => { return new ZodMap({ valueType, keyType, typeName: ZodFirstPartyTypeKind.ZodMap, ...processCreateParams(params), }); }; class ZodSet extends ZodType { _parse(input) { const { status, ctx } = this._processInputParams(input); if (ctx.parsedType !== ZodParsedType.set) { addIssueToContext(ctx, { code: ZodIssueCode.invalid_type, expected: ZodParsedType.set, received: ctx.parsedType, }); return INVALID; } const def = this._def; if (def.minSize !== null) { if (ctx.data.size < def.minSize.value) { addIssueToContext(ctx, { code: ZodIssueCode.too_small, minimum: def.minSize.value, type: "set", inclusive: true, exact: false, message: def.minSize.message, }); status.dirty(); } } if (def.maxSize !== null) { if (ctx.data.size > def.maxSize.value) { addIssueToContext(ctx, { code: ZodIssueCode.too_big, maximum: def.maxSize.value, type: "set", inclusive: true, exact: false, message: def.maxSize.message, }); status.dirty(); } } const valueType = this._def.valueType; function finalizeSet(elements) { const parsedSet = new Set(); for (const element of elements) { if (element.status === "aborted") return INVALID; if (element.status === "dirty") status.dirty(); parsedSet.add(element.value); } return { status: status.value, value: parsedSet }; } const elements = [...ctx.data.values()].map((item, i) => valueType._parse(new ParseInputLazyPath(ctx, item, ctx.path, i))); if (ctx.common.async) { return Promise.all(elements).then((elements) => finalizeSet(elements)); } else { return finalizeSet(elements); } } min(minSize, message) { return new ZodSet({ ...this._def, minSize: { value: minSize, message: errorUtil.toString(message) }, }); } max(maxSize, message) { return new ZodSet({ ...this._def, maxSize: { value: maxSize, message: errorUtil.toString(message) }, }); } size(size, message) { return this.min(size, message).max(size, message); } nonempty(message) { return this.min(1, message); } } ZodSet.create = (valueType, params) => { return new ZodSet({ valueType, minSize: null, maxSize: null, typeName: ZodFirstPartyTypeKind.ZodSet, ...processCreateParams(params), }); }; class ZodFunction extends ZodType { constructor() { super(...arguments); this.validate = this.implement; } _parse(input) { const { ctx } = this._processInputParams(input); if (ctx.parsedType !== ZodParsedType.function) { addIssueToContext(ctx, { code: ZodIssueCode.invalid_type, expected: ZodParsedType.function, received: ctx.parsedType, }); return INVALID; } function makeArgsIssue(args, error) { return makeIssue({ data: args, path: ctx.path, errorMaps: [ ctx.common.contextualErrorMap, ctx.schemaErrorMap, getErrorMap(), errorMap, ].filter((x) => !!x), issueData: { code: ZodIssueCode.invalid_arguments, argumentsError: error, }, }); } function makeReturnsIssue(returns, error) { return makeIssue({ data: returns, path: ctx.path, errorMaps: [ ctx.common.contextualErrorMap, ctx.schemaErrorMap, getErrorMap(), errorMap, ].filter((x) => !!x), issueData: { code: ZodIssueCode.invalid_return_type, returnTypeError: error, }, }); } const params = { errorMap: ctx.common.contextualErrorMap }; const fn = ctx.data; if (this._def.returns instanceof ZodPromise) { // Would love a way to avoid disabling this rule, but we need // an alias (using an arrow function was what caused 2651). // eslint-disable-next-line @typescript-eslint/no-this-alias const me = this; return OK(async function (...args) { const error = new ZodError([]); const parsedArgs = await me._def.args .parseAsync(args, params) .catch((e) => { error.addIssue(makeArgsIssue(args, e)); throw error; }); const result = await Reflect.apply(fn, this, parsedArgs); const parsedReturns = await me._def.returns._def.type .parseAsync(result, params) .catch((e) => { error.addIssue(makeReturnsIssue(result, e)); throw error; }); return parsedReturns; }); } else { // Would love a way to avoid disabling this rule, but we need // an alias (using an arrow function was what caused 2651). // eslint-disable-next-line @typescript-eslint/no-this-alias const me = this; return OK(function (...args) { const parsedArgs = me._def.args.safeParse(args, params); if (!parsedArgs.success) { throw new ZodError([makeArgsIssue(args, parsedArgs.error)]); } const result = Reflect.apply(fn, this, parsedArgs.data); const parsedReturns = me._def.returns.safeParse(result, params); if (!parsedReturns.success) { throw new ZodError([makeReturnsIssue(result, parsedReturns.error)]); } return parsedReturns.data; }); } } parameters() { return this._def.args; } returnType() { return this._def.returns; } args(...items) { return new ZodFunction({ ...this._def, args: ZodTuple.create(items).rest(ZodUnknown.create()), }); } returns(returnType) { return new ZodFunction({ ...this._def, returns: returnType, }); } implement(func) { const validatedFunc = this.parse(func); return validatedFunc; } strictImplement(func) { const validatedFunc = this.parse(func); return validatedFunc; } static create(args, returns, params) { return new ZodFunction({ args: (args ? args : ZodTuple.create([]).rest(ZodUnknown.create())), returns: returns || ZodUnknown.create(), typeName: ZodFirstPartyTypeKind.ZodFunction, ...processCreateParams(params), }); } } class ZodLazy extends ZodType { get schema() { return this._def.getter(); } _parse(input) { const { ctx } = this._processInputParams(input); const lazySchema = this._def.getter(); return lazySchema._parse({ data: ctx.data, path: ctx.path, parent: ctx }); } } ZodLazy.create = (getter, params) => { return new ZodLazy({ getter: getter, typeName: ZodFirstPartyTypeKind.ZodLazy, ...processCreateParams(params), }); }; class ZodLiteral extends ZodType { _parse(input) { if (input.data !== this._def.value) { const ctx = this._getOrReturnCtx(input); addIssueToContext(ctx, { received: ctx.data, code: ZodIssueCode.invalid_literal, expected: this._def.value, }); return INVALID; } return { status: "valid", value: input.data }; } get value() { return this._def.value; } } ZodLiteral.create = (value, params) => { return new ZodLiteral({ value: value, typeName: ZodFirstPartyTypeKind.ZodLiteral, ...processCreateParams(params), }); }; function createZodEnum(values, params) { return new ZodEnum({ values, typeName: ZodFirstPartyTypeKind.ZodEnum, ...processCreateParams(params), }); } class ZodEnum extends ZodType { constructor() { super(...arguments); _ZodEnum_cache.set(this, void 0); } _parse(input) { if (typeof input.data !== "string") { const ctx = this._getOrReturnCtx(input); const expectedValues = this._def.values; addIssueToContext(ctx, { expected: util.joinValues(expectedValues), received: ctx.parsedType, code: ZodIssueCode.invalid_type, }); return INVALID; } if (!__classPrivateFieldGet(this, _ZodEnum_cache, "f")) { __classPrivateFieldSet(this, _ZodEnum_cache, new Set(this._def.values), "f"); } if (!__classPrivateFieldGet(this, _ZodEnum_cache, "f").has(input.data)) { const ctx = this._getOrReturnCtx(input); const expectedValues = this._def.values; addIssueToContext(ctx, { received: ctx.data, code: ZodIssueCode.invalid_enum_value, options: expectedValues, }); return INVALID; } return OK(input.data); } get options() { return this._def.values; } get enum() { const enumValues = {}; for (const val of this._def.values) { enumValues[val] = val; } return enumValues; } get Values() { const enumValues = {}; for (const val of this._def.values) { enumValues[val] = val; } return enumValues; } get Enum() { const enumValues = {}; for (const val of this._def.values) { enumValues[val] = val; } return enumValues; } extract(values, newDef = this._def) { return ZodEnum.create(values, { ...this._def, ...newDef, }); } exclude(values, newDef = this._def) { return ZodEnum.create(this.options.filter((opt) => !values.includes(opt)), { ...this._def, ...newDef, }); } } _ZodEnum_cache = new WeakMap(); ZodEnum.create = createZodEnum; class ZodNativeEnum extends ZodType { constructor() { super(...arguments); _ZodNativeEnum_cache.set(this, void 0); } _parse(input) { const nativeEnumValues = util.getValidEnumValues(this._def.values); const ctx = this._getOrReturnCtx(input); if (ctx.parsedType !== ZodParsedType.string && ctx.parsedType !== ZodParsedType.number) { const expectedValues = util.objectValues(nativeEnumValues); addIssueToContext(ctx, { expected: util.joinValues(expectedValues), received: ctx.parsedType, code: ZodIssueCode.invalid_type, }); return INVALID; } if (!__classPrivateFieldGet(this, _ZodNativeEnum_cache, "f")) { __classPrivateFieldSet(this, _ZodNativeEnum_cache, new Set(util.getValidEnumValues(this._def.values)), "f"); } if (!__classPrivateFieldGet(this, _ZodNativeEnum_cache, "f").has(input.data)) { const expectedValues = util.objectValues(nativeEnumValues); addIssueToContext(ctx, { received: ctx.data, code: ZodIssueCode.invalid_enum_value, options: expectedValues, }); return INVALID; } return OK(input.data); } get enum() { return this._def.values; } } _ZodNativeEnum_cache = new WeakMap(); ZodNativeEnum.create = (values, params) => { return new ZodNativeEnum({ values: values, typeName: ZodFirstPartyTypeKind.ZodNativeEnum, ...processCreateParams(params), }); }; class ZodPromise extends ZodType { unwrap() { return this._def.type; } _parse(input) { const { ctx } = this._processInputParams(input); if (ctx.parsedType !== ZodParsedType.promise && ctx.common.async === false) { addIssueToContext(ctx, { code: ZodIssueCode.invalid_type, expected: ZodParsedType.promise, received: ctx.parsedType, }); return INVALID; } const promisified = ctx.parsedType === ZodParsedType.promise ? ctx.data : Promise.resolve(ctx.data); return OK(promisified.then((data) => { return this._def.type.parseAsync(data, { path: ctx.path, errorMap: ctx.common.contextualErrorMap, }); })); } } ZodPromise.create = (schema, params) => { return new ZodPromise({ type: schema, typeName: ZodFirstPartyTypeKind.ZodPromise, ...processCreateParams(params), }); }; class ZodEffects extends ZodType { innerType() { return this._def.schema; } sourceType() { return this._def.schema._def.typeName === ZodFirstPartyTypeKind.ZodEffects ? this._def.schema.sourceType() : this._def.schema; } _parse(input) { const { status, ctx } = this._processInputParams(input); const effect = this._def.effect || null; const checkCtx = { addIssue: (arg) => { addIssueToContext(ctx, arg); if (arg.fatal) { status.abort(); } else { status.dirty(); } }, get path() { return ctx.path; }, }; checkCtx.addIssue = checkCtx.addIssue.bind(checkCtx); if (effect.type === "preprocess") { const processed = effect.transform(ctx.data, checkCtx); if (ctx.common.async) { return Promise.resolve(processed).then(async (processed) => { if (status.value === "aborted") return INVALID; const result = await this._def.schema._parseAsync({ data: processed, path: ctx.path, parent: ctx, }); if (result.status === "aborted") return INVALID; if (result.status === "dirty") return DIRTY(result.value); if (status.value === "dirty") return DIRTY(result.value); return result; }); } else { if (status.value === "aborted") return INVALID; const result = this._def.schema._parseSync({ data: processed, path: ctx.path, parent: ctx, }); if (result.status === "aborted") return INVALID; if (result.status === "dirty") return DIRTY(result.value); if (status.value === "dirty") return DIRTY(result.value); return result; } } if (effect.type === "refinement") { const executeRefinement = (acc) => { const result = effect.refinement(acc, checkCtx); if (ctx.common.async) { return Promise.resolve(result); } if (result instanceof Promise) { throw new Error("Async refinement encountered during synchronous parse operation. Use .parseAsync instead."); } return acc; }; if (ctx.common.async === false) { const inner = this._def.schema._parseSync({ data: ctx.data, path: ctx.path, parent: ctx, }); if (inner.status === "aborted") return INVALID; if (inner.status === "dirty") status.dirty(); // return value is ignored executeRefinement(inner.value); return { status: status.value, value: inner.value }; } else { return this._def.schema ._parseAsync({ data: ctx.data, path: ctx.path, parent: ctx }) .then((inner) => { if (inner.status === "aborted") return INVALID; if (inner.status === "dirty") status.dirty(); return executeRefinement(inner.value).then(() => { return { status: status.value, value: inner.value }; }); }); } } if (effect.type === "transform") { if (ctx.common.async === false) { const base = this._def.schema._parseSync({ data: ctx.data, path: ctx.path, parent: ctx, }); if (!isValid(base)) return base; const result = effect.transform(base.value, checkCtx); if (result instanceof Promise) { throw new Error(`Asynchronous transform encountered during synchronous parse operation. Use .parseAsync instead.`); } return { status: status.value, value: result }; } else { return this._def.schema ._parseAsync({ data: ctx.data, path: ctx.path, parent: ctx }) .then((base) => { if (!isValid(base)) return base; return Promise.resolve(effect.transform(base.value, checkCtx)).then((result) => ({ status: status.value, value: result })); }); } } util.assertNever(effect); } } ZodEffects.create = (schema, effect, params) => { return new ZodEffects({ schema, typeName: ZodFirstPartyTypeKind.ZodEffects, effect, ...processCreateParams(params), }); }; ZodEffects.createWithPreprocess = (preprocess, schema, params) => { return new ZodEffects({ schema, effect: { type: "preprocess", transform: preprocess }, typeName: ZodFirstPartyTypeKind.ZodEffects, ...processCreateParams(params), }); }; class ZodOptional extends ZodType { _parse(input) { const parsedType = this._getType(input); if (parsedType === ZodParsedType.undefined) { return OK(undefined); } return this._def.innerType._parse(input); } unwrap() { return this._def.innerType; } } ZodOptional.create = (type, params) => { return new ZodOptional({ innerType: type, typeName: ZodFirstPartyTypeKind.ZodOptional, ...processCreateParams(params), }); }; class ZodNullable extends ZodType { _parse(input) { const parsedType = this._getType(input); if (parsedType === ZodParsedType.null) { return OK(null); } return this._def.innerType._parse(input); } unwrap() { return this._def.innerType; } } ZodNullable.create = (type, params) => { return new ZodNullable({ innerType: type, typeName: ZodFirstPartyTypeKind.ZodNullable, ...processCreateParams(params), }); }; class ZodDefault extends ZodType { _parse(input) { const { ctx } = this._processInputParams(input); let data = ctx.data; if (ctx.parsedType === ZodParsedType.undefined) { data = this._def.defaultValue(); } return this._def.innerType._parse({ data, path: ctx.path, parent: ctx, }); } removeDefault() { return this._def.innerType; } } ZodDefault.create = (type, params) => { return new ZodDefault({ innerType: type, typeName: ZodFirstPartyTypeKind.ZodDefault, defaultValue: typeof params.default === "function" ? params.default : () => params.default, ...processCreateParams(params), }); }; class ZodCatch extends ZodType { _parse(input) { const { ctx } = this._processInputParams(input); // newCtx is used to not collect issues from inner types in ctx const newCtx = { ...ctx, common: { ...ctx.common, issues: [], }, }; const result = this._def.innerType._parse({ data: newCtx.data, path: newCtx.path, parent: { ...newCtx, }, }); if (isAsync(result)) { return result.then((result) => { return { status: "valid", value: result.status === "valid" ? result.value : this._def.catchValue({ get error() { return new ZodError(newCtx.common.issues); }, input: newCtx.data, }), }; }); } else { return { status: "valid", value: result.status === "valid" ? result.value : this._def.catchValue({ get error() { return new ZodError(newCtx.common.issues); }, input: newCtx.data, }), }; } } removeCatch() { return this._def.innerType; } } ZodCatch.create = (type, params) => { return new ZodCatch({ innerType: type, typeName: ZodFirstPartyTypeKind.ZodCatch, catchValue: typeof params.catch === "function" ? params.catch : () => params.catch, ...processCreateParams(params), }); }; class ZodNaN extends ZodType { _parse(input) { const parsedType = this._getType(input); if (parsedType !== ZodParsedType.nan) { const ctx = this._getOrReturnCtx(input); addIssueToContext(ctx, { code: ZodIssueCode.invalid_type, expected: ZodParsedType.nan, received: ctx.parsedType, }); return INVALID; } return { status: "valid", value: input.data }; } } ZodNaN.create = (params) => { return new ZodNaN({ typeName: ZodFirstPartyTypeKind.ZodNaN, ...processCreateParams(params), }); }; const BRAND = Symbol("zod_brand"); class ZodBranded extends ZodType { _parse(input) { const { ctx } = this._processInputParams(input); const data = ctx.data; return this._def.type._parse({ data, path: ctx.path, parent: ctx, }); } unwrap() { return this._def.type; } } class ZodPipeline extends ZodType { _parse(input) { const { status, ctx } = this._processInputParams(input); if (ctx.common.async) { const handleAsync = async () => { const inResult = await this._def.in._parseAsync({ data: ctx.data, path: ctx.path, parent: ctx, }); if (inResult.status === "aborted") return INVALID; if (inResult.status === "dirty") { status.dirty(); return DIRTY(inResult.value); } else { return this._def.out._parseAsync({ data: inResult.value, path: ctx.path, parent: ctx, }); } }; return handleAsync(); } else { const inResult = this._def.in._parseSync({ data: ctx.data, path: ctx.path, parent: ctx, }); if (inResult.status === "aborted") return INVALID; if (inResult.status === "dirty") { status.dirty(); return { status: "dirty", value: inResult.value, }; } else { return this._def.out._parseSync({ data: inResult.value, path: ctx.path, parent: ctx, }); } } } static create(a, b) { return new ZodPipeline({ in: a, out: b, typeName: ZodFirstPartyTypeKind.ZodPipeline, }); } } class ZodReadonly extends ZodType { _parse(input) { const result = this._def.innerType._parse(input); const freeze = (data) => { if (isValid(data)) { data.value = Object.freeze(data.value); } return data; }; return isAsync(result) ? result.then((data) => freeze(data)) : freeze(result); } unwrap() { return this._def.innerType; } } ZodReadonly.create = (type, params) => { return new ZodReadonly({ innerType: type, typeName: ZodFirstPartyTypeKind.ZodReadonly, ...processCreateParams(params), }); }; //////////////////////////////////////// //////////////////////////////////////// ////////// ////////// ////////// z.custom ////////// ////////// ////////// //////////////////////////////////////// //////////////////////////////////////// function cleanParams(params, data) { const p = typeof params === "function" ? params(data) : typeof params === "string" ? { message: params } : params; const p2 = typeof p === "string" ? { message: p } : p; return p2; } function custom(check, _params = {}, /** * @deprecated * * Pass `fatal` into the params object instead: * * ```ts * z.string().custom((val) => val.length > 5, { fatal: false }) * ``` * */ fatal) { if (check) return ZodAny.create().superRefine((data, ctx) => { var _a, _b; const r = check(data); if (r instanceof Promise) { return r.then((r) => { var _a, _b; if (!r) { const params = cleanParams(_params, data); const _fatal = (_b = (_a = params.fatal) !== null && _a !== void 0 ? _a : fatal) !== null && _b !== void 0 ? _b : true; ctx.addIssue({ code: "custom", ...params, fatal: _fatal }); } }); } if (!r) { const params = cleanParams(_params, data); const _fatal = (_b = (_a = params.fatal) !== null && _a !== void 0 ? _a : fatal) !== null && _b !== void 0 ? _b : true; ctx.addIssue({ code: "custom", ...params, fatal: _fatal }); } return; }); return ZodAny.create(); } const late = { object: ZodObject.lazycreate, }; var ZodFirstPartyTypeKind; (function (ZodFirstPartyTypeKind) { ZodFirstPartyTypeKind["ZodString"] = "ZodString"; ZodFirstPartyTypeKind["ZodNumber"] = "ZodNumber"; ZodFirstPartyTypeKind["ZodNaN"] = "ZodNaN"; ZodFirstPartyTypeKind["ZodBigInt"] = "ZodBigInt"; ZodFirstPartyTypeKind["ZodBoolean"] = "ZodBoolean"; ZodFirstPartyTypeKind["ZodDate"] = "ZodDate"; ZodFirstPartyTypeKind["ZodSymbol"] = "ZodSymbol"; ZodFirstPartyTypeKind["ZodUndefined"] = "ZodUndefined"; ZodFirstPartyTypeKind["ZodNull"] = "ZodNull"; ZodFirstPartyTypeKind["ZodAny"] = "ZodAny"; ZodFirstPartyTypeKind["ZodUnknown"] = "ZodUnknown"; ZodFirstPartyTypeKind["ZodNever"] = "ZodNever"; ZodFirstPartyTypeKind["ZodVoid"] = "ZodVoid"; ZodFirstPartyTypeKind["ZodArray"] = "ZodArray"; ZodFirstPartyTypeKind["ZodObject"] = "ZodObject"; ZodFirstPartyTypeKind["ZodUnion"] = "ZodUnion"; ZodFirstPartyTypeKind["ZodDiscriminatedUnion"] = "ZodDiscriminatedUnion"; ZodFirstPartyTypeKind["ZodIntersection"] = "ZodIntersection"; ZodFirstPartyTypeKind["ZodTuple"] = "ZodTuple"; ZodFirstPartyTypeKind["ZodRecord"] = "ZodRecord"; ZodFirstPartyTypeKind["ZodMap"] = "ZodMap"; ZodFirstPartyTypeKind["ZodSet"] = "ZodSet"; ZodFirstPartyTypeKind["ZodFunction"] = "ZodFunction"; ZodFirstPartyTypeKind["ZodLazy"] = "ZodLazy"; ZodFirstPartyTypeKind["ZodLiteral"] = "ZodLiteral"; ZodFirstPartyTypeKind["ZodEnum"] = "ZodEnum"; ZodFirstPartyTypeKind["ZodEffects"] = "ZodEffects"; ZodFirstPartyTypeKind["ZodNativeEnum"] = "ZodNativeEnum"; ZodFirstPartyTypeKind["ZodOptional"] = "ZodOptional"; ZodFirstPartyTypeKind["ZodNullable"] = "ZodNullable"; ZodFirstPartyTypeKind["ZodDefault"] = "ZodDefault"; ZodFirstPartyTypeKind["ZodCatch"] = "ZodCatch"; ZodFirstPartyTypeKind["ZodPromise"] = "ZodPromise"; ZodFirstPartyTypeKind["ZodBranded"] = "ZodBranded"; ZodFirstPartyTypeKind["ZodPipeline"] = "ZodPipeline"; ZodFirstPartyTypeKind["ZodReadonly"] = "ZodReadonly"; })(ZodFirstPartyTypeKind || (ZodFirstPartyTypeKind = {})); const instanceOfType = ( // const instanceOfType = any>( cls, params = { message: `Input not instance of ${cls.name}`, }) => custom((data) => data instanceof cls, params); const stringType = ZodString.create; const numberType = ZodNumber.create; const nanType = ZodNaN.create; const bigIntType = ZodBigInt.create; const booleanType = ZodBoolean.create; const dateType = ZodDate.create; const symbolType = ZodSymbol.create; const undefinedType = ZodUndefined.create; const nullType = ZodNull.create; const anyType = ZodAny.create; const unknownType = ZodUnknown.create; const neverType = ZodNever.create; const voidType = ZodVoid.create; const arrayType = ZodArray.create; const objectType = ZodObject.create; const strictObjectType = ZodObject.strictCreate; const unionType = ZodUnion.create; const discriminatedUnionType = ZodDiscriminatedUnion.create; const intersectionType = ZodIntersection.create; const tupleType = ZodTuple.create; const recordType = ZodRecord.create; const mapType = ZodMap.create; const setType = ZodSet.create; const functionType = ZodFunction.create; const lazyType = ZodLazy.create; const literalType = ZodLiteral.create; const enumType = ZodEnum.create; const nativeEnumType = ZodNativeEnum.create; const promiseType = ZodPromise.create; const effectsType = ZodEffects.create; const optionalType = ZodOptional.create; const nullableType = ZodNullable.create; const preprocessType = ZodEffects.createWithPreprocess; const pipelineType = ZodPipeline.create; const ostring = () => stringType().optional(); const onumber = () => numberType().optional(); const oboolean = () => booleanType().optional(); const coerce = { string: ((arg) => ZodString.create({ ...arg, coerce: true })), number: ((arg) => ZodNumber.create({ ...arg, coerce: true })), boolean: ((arg) => ZodBoolean.create({ ...arg, coerce: true, })), bigint: ((arg) => ZodBigInt.create({ ...arg, coerce: true })), date: ((arg) => ZodDate.create({ ...arg, coerce: true })), }; const NEVER = INVALID; var z = /*#__PURE__*/Object.freeze({ __proto__: null, defaultErrorMap: errorMap, setErrorMap: setErrorMap, getErrorMap: getErrorMap, makeIssue: makeIssue, EMPTY_PATH: EMPTY_PATH, addIssueToContext: addIssueToContext, ParseStatus: ParseStatus, INVALID: INVALID, DIRTY: DIRTY, OK: OK, isAborted: isAborted, isDirty: isDirty, isValid: isValid, isAsync: isAsync, get util () { return util; }, get objectUtil () { return objectUtil; }, ZodParsedType: ZodParsedType, getParsedType: getParsedType, ZodType: ZodType, datetimeRegex: datetimeRegex, ZodString: ZodString, ZodNumber: ZodNumber, ZodBigInt: ZodBigInt, ZodBoolean: ZodBoolean, ZodDate: ZodDate, ZodSymbol: ZodSymbol, ZodUndefined: ZodUndefined, ZodNull: ZodNull, ZodAny: ZodAny, ZodUnknown: ZodUnknown, ZodNever: ZodNever, ZodVoid: ZodVoid, ZodArray: ZodArray, ZodObject: ZodObject, ZodUnion: ZodUnion, ZodDiscriminatedUnion: ZodDiscriminatedUnion, ZodIntersection: ZodIntersection, ZodTuple: ZodTuple, ZodRecord: ZodRecord, ZodMap: ZodMap, ZodSet: ZodSet, ZodFunction: ZodFunction, ZodLazy: ZodLazy, ZodLiteral: ZodLiteral, ZodEnum: ZodEnum, ZodNativeEnum: ZodNativeEnum, ZodPromise: ZodPromise, ZodEffects: ZodEffects, ZodTransformer: ZodEffects, ZodOptional: ZodOptional, ZodNullable: ZodNullable, ZodDefault: ZodDefault, ZodCatch: ZodCatch, ZodNaN: ZodNaN, BRAND: BRAND, ZodBranded: ZodBranded, ZodPipeline: ZodPipeline, ZodReadonly: ZodReadonly, custom: custom, Schema: ZodType, ZodSchema: ZodType, late: late, get ZodFirstPartyTypeKind () { return ZodFirstPartyTypeKind; }, coerce: coerce, any: anyType, array: arrayType, bigint: bigIntType, boolean: booleanType, date: dateType, discriminatedUnion: discriminatedUnionType, effect: effectsType, 'enum': enumType, 'function': functionType, 'instanceof': instanceOfType, intersection: intersectionType, lazy: lazyType, literal: literalType, map: mapType, nan: nanType, nativeEnum: nativeEnumType, never: neverType, 'null': nullType, nullable: nullableType, number: numberType, object: objectType, oboolean: oboolean, onumber: onumber, optional: optionalType, ostring: ostring, pipeline: pipelineType, preprocess: preprocessType, promise: promiseType, record: recordType, set: setType, strictObject: strictObjectType, string: stringType, symbol: symbolType, transformer: effectsType, tuple: tupleType, 'undefined': undefinedType, union: unionType, unknown: unknownType, 'void': voidType, NEVER: NEVER, ZodIssueCode: ZodIssueCode, quotelessJson: quotelessJson, ZodError: ZodError }); }, },function(__webpack_require__) { var __webpack_exec__ = function(moduleId) { return __webpack_require__(__webpack_require__.s = moduleId) } var __webpack_exports__ = (__webpack_exec__(6730)); } ]);