diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 3068dd190..9c5f70465 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -46,7 +46,6 @@ jobs: # agtree npx lerna run --scope @adguard/agtree check-types - npx lerna run --scope @adguard/agtree check-compatibility-tables npx lerna run --scope @adguard/agtree lint npx lerna run --scope @adguard/agtree test npx lerna run --scope @adguard/agtree build diff --git a/bamboo-specs/agtree-test.yaml b/bamboo-specs/agtree-test.yaml index 3e321f7d5..608e45512 100644 --- a/bamboo-specs/agtree-test.yaml +++ b/bamboo-specs/agtree-test.yaml @@ -61,14 +61,14 @@ Test: # Check TypeScript types with TSC pnpm --filter @adguard/agtree check-types - # Validate compatibility tables - pnpm --filter @adguard/agtree check-compatibility-tables - # Check code with ESLint pnpm --filter @adguard/agtree lint # Run tests with Jest pnpm --filter @adguard/agtree test + + # Build should work + pnpm --filter @adguard/agtree build final-tasks: - script: interpreter: SHELL diff --git a/package.json b/package.json index 70e49e115..232d128ad 100644 --- a/package.json +++ b/package.json @@ -21,5 +21,6 @@ }, "devDependencies": { "lerna": "^8.1.2" - } + }, + "packageManager": "pnpm@8.15.0+sha512.ea45517d5285d123eac02c3793505fa1fd6da90a2fc60d1e8d9e0c1e9292886ecfaff513f062b9d1cc8021bb8615033b1ac5bea3b2ee3fc165a6d7034bbe6b03" } diff --git a/packages/agtree/CHANGELOG.md b/packages/agtree/CHANGELOG.md index fe49f337a..2c28d328c 100644 --- a/packages/agtree/CHANGELOG.md +++ b/packages/agtree/CHANGELOG.md @@ -7,6 +7,22 @@ The format is based on [Keep a Changelog][keepachangelog], and this project adhe [keepachangelog]: https://keepachangelog.com/en/1.0.0/ [semver]: https://semver.org/spec/v2.0.0.html +## Unreleased + +### Added + +- Compatibility table API. +- Compatibility table wiki, which is generated from the compatibility table API. + +### Changed + +- Reworked the compatibility table structure. +- Library now use CJS. + +### Removed + +- Scriptlets library, since it is not needed anymore, because AGTree now has its own compatibility tables. + ## 1.1.8 - 2024-04-24 ### Added diff --git a/packages/agtree/CONTRIBUTING.md b/packages/agtree/CONTRIBUTING.md index 7a7500546..4641612db 100644 --- a/packages/agtree/CONTRIBUTING.md +++ b/packages/agtree/CONTRIBUTING.md @@ -43,7 +43,9 @@ During development, you can use the following commands (listed in `package.json` - `pnpm build` - builds the library with [rollup][rollup] to the `dist` folder - `pnpm build-txt` - creates a `dist/build.txt` file which contains the version of the library. - `pnpm build-types` - build type definitions with [TypeScript][typescript] to the `dist/types` folder. -- `pnpm check-compatibility-tables` - checks if the [compatibility tables][compatibility-tables] are valid. +- `pnpm build-compatibility-tables` - build compatibility tables to `dist/compatibility-tables.json` file. + This is a transformed data structure that is used by the library. +- `build-compatibility-tables-wiki` - build compatibility tables to Markdown files in the `wiki` folder. - `pnpm check-types` - check type definitions with [TypeScript][typescript]. - `pnpm clean` - remove the `dist` folder. - `pnpm clean-types` - remove the `dist/types` folder. @@ -55,7 +57,6 @@ During development, you can use the following commands (listed in `package.json` - `pnpm precommit` - run all checks before committing. - `pnpm test` - run tests with [Jest][jest]. -[compatibility-tables]: https://github.com/AdguardTeam/tsurlfilter/tree/master/packages/agtree/src/compatibility-tables [contribute]: https://adguard.com/contribute.html [eslint]: https://eslint.org/ [git]: https://git-scm.com/ diff --git a/packages/agtree/jest.config.ts b/packages/agtree/jest.config.ts index c8456ac6c..e6737520e 100644 --- a/packages/agtree/jest.config.ts +++ b/packages/agtree/jest.config.ts @@ -5,8 +5,6 @@ const config: Config = { testTimeout: 30000, testMatch: ['**/test/**/*.test.ts'], transform: { - // Enable importing YAML files while testing - '.yml': 'yaml-jest-transform', // Speed up tests by using SWC instead of Babel '.ts': '@swc/jest', }, diff --git a/packages/agtree/package.json b/packages/agtree/package.json index 2eb51a079..343edfbb4 100644 --- a/packages/agtree/package.json +++ b/packages/agtree/package.json @@ -20,7 +20,6 @@ "url": "https://github.com/AdguardTeam/tsurlfilter/issues" }, "homepage": "https://github.com/AdguardTeam/tsurlfilter/tree/master/packages/agtree#readme", - "type": "module", "main": "dist/agtree.cjs", "module": "dist/agtree.esm.js", "browser": "dist/agtree.umd.min.js", @@ -42,16 +41,17 @@ "node": ">=14" }, "scripts": { - "build": "pnpm clean && pnpm build-types && pnpm build-txt && pnpm rollup --config rollup.config.ts --configPlugin typescript && pnpm clean-types", - "build-txt": "node --no-warnings=ExperimentalWarning --loader ts-node/esm scripts/build-txt.ts", + "build": "pnpm clean && pnpm build-types && pnpm build-txt && pnpm build-compatibility-tables && pnpm build-compatibility-tables-wiki && pnpm rollup --config rollup.config.ts --configPlugin typescript && pnpm clean-types", + "build-txt": "tsx scripts/build-txt.ts", "build-types": "tsc --declaration --emitDeclarationOnly --outdir dist/types", - "check-compatibility-tables": "node --no-warnings=ExperimentalWarning --loader ts-node/esm scripts/check-compatibility-tables.ts", + "build-compatibility-tables": "tsx scripts/build-compatibility-tables.ts", + "build-compatibility-tables-wiki": "tsx scripts/build-compatibility-tables-wiki.ts", "check-types": "tsc --noEmit", "clean": "rimraf dist", "clean-types": "rimraf dist/types", "coverage": "jest --runInBand --coverage", "increment": "pnpm version patch --no-git-tag-version", - "lint": "pnpm lint:ts && pnpm lint:md", + "lint": "pnpm check-types && pnpm lint:ts && pnpm lint:md", "lint:md": "markdownlint .", "lint:ts": "eslint . --cache --ext .ts", "precommit": "pnpm check-types && pnpm lint && pnpm test", @@ -67,18 +67,18 @@ "@rollup/plugin-node-resolve": "^15.1.0", "@rollup/plugin-terser": "^0.4.3", "@rollup/plugin-typescript": "^11.1.2", - "@rollup/plugin-yaml": "^4.1.1", "@swc/core": "^1.3.100", "@swc/helpers": "^0.5.3", "@swc/jest": "^0.2.29", "@types/clone-deep": "^4.0.1", "@types/fs-extra": "^11.0.4", - "@types/jest": "^29.5.3", + "@types/jest": "^29.5.12", "@types/js-yaml": "^4.0.5", "@types/node": "^20.2.3", "@types/semver": "^7.5.0", "@typescript-eslint/eslint-plugin": "^5.60.1", "@typescript-eslint/parser": "^5.60.1", + "camelcase-keys": "^7.0.2", "eslint": "^8.43.0", "eslint-config-airbnb-typescript": "^17.0.0", "eslint-plugin-import": "^2.27.5", @@ -89,27 +89,28 @@ "jest": "^29.5.0", "js-yaml": "^4.1.0", "jsdoc": "^4.0.2", + "markdown-table": "^3.0.3", "markdownlint": "^0.29.0", "markdownlint-cli": "^0.35.0", + "prettier": "^3.3.2", "regenerator-runtime": "^0.14.0", "rimraf": "^5.0.1", "rollup": "^3.25.3", "rollup-plugin-dts": "^5.3.0", "rollup-plugin-node-externals": "^6.1.1", "rollup-plugin-polyfill-node": "^0.12.0", - "superstruct": "^1.0.3", "ts-node": "^10.9.2", - "typescript": "^5.0.4", - "yaml-jest-transform": "^2.0.2", - "zod": "^3.22.2" + "tsx": "^4.7.3", + "type-fest": "^4.18.0", + "typescript": "^5.0.4" }, "dependencies": { "@adguard/ecss-tree": "^1.0.8", - "@adguard/scriptlets": "^1.9.61", "clone-deep": "^4.0.1", "json5": "^2.2.3", "semver": "^7.5.3", "tldts": "^5.7.112", - "xregexp": "^5.1.1" + "xregexp": "^5.1.1", + "zod": "^3.23.4" } } diff --git a/packages/agtree/rollup.config.ts b/packages/agtree/rollup.config.ts index 78b40295f..3888ca9fd 100644 --- a/packages/agtree/rollup.config.ts +++ b/packages/agtree/rollup.config.ts @@ -14,9 +14,8 @@ import alias from '@rollup/plugin-alias'; import { getBabelOutputPlugin } from '@rollup/plugin-babel'; import json from '@rollup/plugin-json'; import terser from '@rollup/plugin-terser'; -import yaml from '@rollup/plugin-yaml'; -import path from 'path'; -import { readFileSync } from 'fs'; +import path from 'node:path'; +import { readFileSync } from 'node:fs'; const ROOT_DIR = './'; const BASE_FILE_NAME = 'agtree'; @@ -62,8 +61,16 @@ const typeScriptPlugin = typescript({ // Common plugins for all types of builds const commonPlugins = [ + alias({ + entries: [ + // replace dynamic compatibility table data builder with the pre-built data file + { + find: './compatibility-table-data', + replacement: path.resolve(ROOT_DIR, 'dist', 'compatibility-tables.json'), + }, + ], + }), json({ preferConst: true }), - yaml(), commonjs({ sourceMap: false }), resolve({ preferBuiltins: false }), typeScriptPlugin, @@ -97,7 +104,7 @@ const browserPlugins = [ entries: [ { find: '@adguard/ecss-tree', - replacement: path.join( + replacement: path.resolve( 'node_modules/@adguard/ecss-tree/dist/ecsstree.umd.min.js', ), }, diff --git a/packages/agtree/scripts/build-compatibility-tables-wiki.ts b/packages/agtree/scripts/build-compatibility-tables-wiki.ts new file mode 100644 index 000000000..6faaacd4f --- /dev/null +++ b/packages/agtree/scripts/build-compatibility-tables-wiki.ts @@ -0,0 +1,278 @@ +// eslint-disable-next-line import/no-extraneous-dependencies +/** + * @file Script to generate compatibility tables for the wiki. + */ + +import * as prettier from 'prettier'; +import { markdownTable } from 'markdown-table'; +import { writeFile } from 'fs/promises'; +import { ensureDir } from 'fs-extra'; +import path from 'path'; + +import { redirectsCompatibilityTable } from '../src/compatibility-tables/redirects'; +import { type BaseCompatibilityDataSchema } from '../src/compatibility-tables/schemas'; +import { modifiersCompatibilityTable } from '../src/compatibility-tables/modifiers'; +import { scriptletsCompatibilityTable } from '../src/compatibility-tables/scriptlets'; +import { type ProductRecords, type RowByProduct, type CompatibilityTableBase } from '../src/compatibility-tables/base'; +import { EMPTY, NEWLINE } from '../src/utils/constants'; +import { AdblockSyntax } from '../src/utils/adblockers'; +import { GenericPlatform, SpecificPlatform } from '../src'; + +const WIKI_PATH = path.join(__dirname, '../src/compatibility-tables/wiki'); + +const LABELS = { + AdGuard: ['CoreLibs', 'Chromium', 'Firefox', 'Safari CB', 'Android CB'], + 'uBlock Origin': ['Chromium', 'Firefox'], + 'Adblock Plus / AdBlock': ['Chromium', 'Firefox'], +}; + +type CompatibilityEntityData = Pick; + +/** + * Helper function to get the name with aliases, e.g. `name (alias1, alias2)`. + * + * @param data Compatibility data to get the name with aliases from. + * @param html Whether to generate HTML or Markdown. + * + * @returns Name with aliases. + */ +const getNameWithAliases = ( + data: CompatibilityEntityData, + html = false, +): string => { + let { name } = data; + + if (data.docs) { + name = html + ? `${name}` + : `[${name}](${data.docs})`; + } + + if (data.aliases) { + name += ` (${data.aliases.join(', ')})`; + } + + return name; +}; + +/** + * Helper function to get the first compatible entity from the row. + * + * @param row Row to get the first compatible entity from. + * @param syntax Adblock syntax to get the entity from. + * @param compatibility Compatibility flags to check. + * + * @returns First compatible entity from the row. + */ +const getFirstCompatibleEntityFromRow = ( + row: RowByProduct, + syntax: AdblockSyntax.Adg | AdblockSyntax.Ubo | AdblockSyntax.Abp, + compatibility: SpecificPlatform | GenericPlatform, +): CompatibilityEntityData => { + const productRow: ProductRecords = row[syntax]; + for (const [key, value] of Object.entries(productRow)) { + // eslint-disable-next-line no-bitwise + if (Number(key) & compatibility) { + return ({ + name: value.name, + aliases: value.aliases, + docs: value.docs, + }); + } + } + + return { name: EMPTY, aliases: null, docs: null }; +}; + +/** + * Sort function for the compatibility table. + * It takes first (AdGuard) column as a base and moves empty cells to the end. + * + * @param a First row to compare. + * @param b Second row to compare. + * + * @returns Comparison result. + */ +const sortFn = (a: CompatibilityEntityData[], b: CompatibilityEntityData[]) => { + if (!a[0].name && !b[0].name) { + return 0; + } + + if (!a[0].name) { + return 1; + } + + if (!b[0].name) { + return -1; + } + + return a[0].name.localeCompare(b[0].name); +}; + +/** + * Helper function to get the rows by product. + * + * @param data Compatibility data to get the rows by product from. + * @param extended Whether to include extended compatibility information. + * + * @returns Rows by product. + * + * @template T Type of the compatibility data. + */ +const getRowsByProduct = >( + data: T, + extended = false, +): string[][] => { + const result: CompatibilityEntityData[][] = extended + ? data.getRowsByProduct().map((row) => [ + getFirstCompatibleEntityFromRow(row, AdblockSyntax.Adg, GenericPlatform.AdgOsAny), + getFirstCompatibleEntityFromRow(row, AdblockSyntax.Adg, GenericPlatform.AdgExtChromium), + getFirstCompatibleEntityFromRow(row, AdblockSyntax.Adg, SpecificPlatform.AdgExtFirefox), + getFirstCompatibleEntityFromRow(row, AdblockSyntax.Adg, GenericPlatform.AdgSafariAny), + getFirstCompatibleEntityFromRow(row, AdblockSyntax.Adg, SpecificPlatform.AdgCbAndroid), + + getFirstCompatibleEntityFromRow(row, AdblockSyntax.Ubo, GenericPlatform.UboExtChromium), + getFirstCompatibleEntityFromRow(row, AdblockSyntax.Ubo, SpecificPlatform.UboExtFirefox), + + getFirstCompatibleEntityFromRow(row, AdblockSyntax.Abp, GenericPlatform.AbpExtChromium), + getFirstCompatibleEntityFromRow(row, AdblockSyntax.Abp, SpecificPlatform.AbpExtFirefox), + ]) + : data.getRowsByProduct().map((row) => [ + getFirstCompatibleEntityFromRow(row, AdblockSyntax.Adg, GenericPlatform.AdgAny), + getFirstCompatibleEntityFromRow(row, AdblockSyntax.Ubo, GenericPlatform.UboAny), + getFirstCompatibleEntityFromRow(row, AdblockSyntax.Abp, GenericPlatform.AbpAny), + ]); + + return result.sort(sortFn).map((row) => row.map((cell) => getNameWithAliases(cell, extended))); +}; + +/** + * Helper function to get the markdown file content. + * + * @param title Title of the markdown file. + * @param table Markdown table content. + * + * @returns Markdown file content. + */ +const getMarkdownFileContent = (title: string, table: string): string => { + return [ + // disable max line length and embedded HTML + '', + `# ${title}`, + EMPTY, + 'This table is generated from the compatibility data.', + EMPTY, + table, + EMPTY, + ].join(NEWLINE); +}; + +/** + * Helper function to get the markdown table content. + * + * @param bodyData Table body. + * @param extended Whether to include extended compatibility information. + * + * @returns Markdown table content. + */ +const getTableContent = async (bodyData: string[][], extended = false): Promise => { + if (extended) { + /* eslint-disable @typescript-eslint/indent */ + const header = ` + + + ${Object.entries(LABELS) + .map(([mainLabel, subLabels]) => `${mainLabel}`) + .join(EMPTY) + } + + + ${Object.entries(LABELS) + // eslint-disable-next-line @typescript-eslint/no-unused-vars + .map(([_, subLabels]) => subLabels.map((subLabel) => `${subLabel}`).join(EMPTY)) + .join(EMPTY) + } + + + `; + + const tableBody = ` + + ${bodyData.map((row) => `${row.map((cell) => `${cell}`).join(EMPTY)}`).join(EMPTY)} + + `; + /* eslint-enable @typescript-eslint/indent */ + + return prettier.format(`${header}${tableBody}
`, { + parser: 'html', + }); + } + + return markdownTable([ + Object.keys(LABELS), + ...bodyData, + ]); +}; + +/** + * Helper function to write a markdown file. + * + * @param title Title of the markdown file. + * @param compatibilityTable Compatibility table to write. + * @param filePath File path to save the markdown file. + * @param extended Whether to include extended compatibility information. + */ +const writeMarkdownFile = async >( + title: string, + compatibilityTable: T, + filePath: string, + extended = false, +) => { + console.log(`Creating ${title}...`); + + const tableBody = getRowsByProduct(compatibilityTable, extended); + const tableContent = await getTableContent(tableBody, extended); + const markdownFileContent = getMarkdownFileContent(title, tableContent); + + await writeFile(filePath, markdownFileContent, 'utf8'); + console.log(`${title} has been saved to ${filePath}`); +}; + +/** + * Main function. + */ +const main = async (): Promise => { + console.log('Building compatibility tables for the wiki...'); + + console.log('Ensuring the wiki directory exists...'); + await ensureDir(WIKI_PATH); + + console.log('Generating compatibility tables...'); + + await writeMarkdownFile( + 'Redirects Compatibility Table', + redirectsCompatibilityTable, + path.join(WIKI_PATH, 'redirects-compatibility-table.md'), + ); + + await writeMarkdownFile( + 'Modifiers Compatibility Table', + modifiersCompatibilityTable, + path.join(WIKI_PATH, 'modifiers-compatibility-table.md'), + ); + + await writeMarkdownFile( + 'Modifiers Compatibility Table', + modifiersCompatibilityTable, + path.join(WIKI_PATH, 'modifiers-compatibility-table-extended.md'), + true, + ); + + await writeMarkdownFile( + 'Scriptlets Compatibility Table', + scriptletsCompatibilityTable, + path.join(WIKI_PATH, 'scriptlets-compatibility-table.md'), + ); +}; + +main(); diff --git a/packages/agtree/scripts/build-compatibility-tables.ts b/packages/agtree/scripts/build-compatibility-tables.ts new file mode 100644 index 000000000..15cd89702 --- /dev/null +++ b/packages/agtree/scripts/build-compatibility-tables.ts @@ -0,0 +1,29 @@ +/** + * @file Script to generate compatibility tables to `dist/compatibility-tables.json`. + * During development, we load the compatibility tables from YAML files directly, + * but in the production build, we load them from this JSON file. + */ + +import { writeFile } from 'fs/promises'; +import { ensureDir } from 'fs-extra'; +import path from 'path'; + +import * as data from '../src/compatibility-tables/compatibility-table-data'; + +const DIST_FOLDER_NAME = 'dist'; +const OUTPUT_FILE_NAME = 'compatibility-tables.json'; + +/** + * Main function. + */ +const main = async (): Promise => { + const outDir = path.join(__dirname, `../${DIST_FOLDER_NAME}`); + const outFile = path.join(outDir, OUTPUT_FILE_NAME); + + await ensureDir(outDir); + await writeFile(outFile, JSON.stringify(data, null, 2)); + + console.log(`Compatibility tables have been saved to ${outFile}`); +}; + +main(); diff --git a/packages/agtree/scripts/build-txt.ts b/packages/agtree/scripts/build-txt.ts index da261347a..303ef133b 100644 --- a/packages/agtree/scripts/build-txt.ts +++ b/packages/agtree/scripts/build-txt.ts @@ -4,10 +4,6 @@ import fs from 'fs-extra'; import path from 'path'; -import * as url from 'url'; - -// eslint-disable-next-line @typescript-eslint/naming-convention, no-underscore-dangle -const __dirname = url.fileURLToPath(new URL('.', import.meta.url)); const PROJECT_ROOT_RELATIVE_PATH = '../'; const DIST_FOLDER_NAME = 'dist'; diff --git a/packages/agtree/scripts/check-compatibility-tables.ts b/packages/agtree/scripts/check-compatibility-tables.ts deleted file mode 100644 index 4edbab567..000000000 --- a/packages/agtree/scripts/check-compatibility-tables.ts +++ /dev/null @@ -1,287 +0,0 @@ -/** - * @file Very simple script to validate the compatibility tables. - */ - -import { readFileSync } from 'fs'; -import { globSync } from 'glob'; -import { join } from 'path'; -import yaml from 'js-yaml'; -import ss from 'superstruct'; -import XRegExp from 'xregexp'; - -/** - * List of all supported platforms and shortcuts. - */ -const platforms = ss.enums([ - // Platforms - 'adg_os_windows', - 'adg_os_mac', - 'adg_os_android', - 'adg_ext_chrome', - 'adg_ext_opera', - 'adg_ext_edge', - 'adg_ext_firefox', - 'adg_cb_android', - 'adg_cb_ios', - 'adg_cb_safari', - 'ubo_ext_chrome', - 'ubo_ext_firefox', - 'ubo_ext_opera', - 'ubo_ext_edge', - 'abp_ext_chrome', - 'abp_ext_firefox', - 'abp_ext_opera', - 'abp_ext_edge', - - // Shortcuts for platforms - 'any', - 'adg_any', - 'adg_os_any', - 'adg_ext_any', - 'adg_ext_chromium', - 'adg_cb_any', - 'adg_any_not_cb', - 'ubo_any', - 'ubo_ext_any', - 'ubo_ext_chromium', - 'abp_any', - 'abp_ext_any', - 'abp_ext_chromium', -]); - -const predefinedValidators = [ - 'domain', - 'pipe_separated_domains', - 'regexp', - 'url', -]; - -/** - * Validates 'value_format' field, which can be either a regex or a predefined - * validator name. - * We use XRegExp for regex validation, because it supports free-spacing mode. - * - * @returns `true` if the value is valid, or an error message if it's not. - */ -const valueFormat = () => ss.define('value_format', (value) => { - // Mark any non-string values as invalid - if (typeof value !== 'string') { - return `Expected a string, got ${typeof value}`; - } - - // Trim the value for simplicity - const trimmedValue = value.trim(); - - // String cannot be empty - if (trimmedValue === '') { - return 'Expected a non-empty string'; - } - - // Try to validate as predefined validator name first - if (predefinedValidators.includes(trimmedValue)) { - // true return means that the value is valid - return true; - } - - // Otherwise, try to validate as a regex - try { - // This will throw if the regex is invalid - XRegExp(value); - - // so if we're here, the regex is valid - return true; - } catch (error: unknown) { - if (error instanceof Error) { - return error.message; - } - - // Unknown error, may never happen - // false return generates a generic error message - return false; - } -}); - -/** - * Schema for compatibility tables. - * - * The keys are glob patterns for the files to be checked. - * The values are Superstruct schemas for the files. - */ -const SCHEMA_MAP = { - /** - * Check [## File structure](../src/compatibility-tables/modifiers/README.md) - */ - 'src/compatibility-tables/modifiers/**.yml': ss.record(platforms, ss.refine( - ss.object({ - name: ss.nonempty(ss.string()), - aliases: ss.defaulted(ss.array(ss.nonempty(ss.string())), []), - description: ss.defaulted(ss.nullable(ss.string()), null), - docs: ss.defaulted(ss.nullable(ss.nonempty(ss.string())), null), - version_added: ss.defaulted(ss.nullable(ss.nonempty(ss.string())), null), - version_removed: ss.defaulted(ss.nullable(ss.nonempty(ss.string())), null), - deprecated: ss.defaulted(ss.boolean(), false), - deprecation_message: ss.defaulted(ss.nullable(ss.nonempty(ss.string())), null), - removed: ss.defaulted(ss.boolean(), false), - removal_message: ss.defaulted(ss.nullable(ss.nonempty(ss.string())), null), - conflicts: ss.defaulted(ss.array(ss.nonempty(ss.string())), []), - inverse_conflicts: ss.defaulted(ss.boolean(), false), - assignable: ss.defaulted(ss.boolean(), false), - negatable: ss.defaulted(ss.boolean(), true), - block_only: ss.defaulted(ss.boolean(), false), - exception_only: ss.defaulted(ss.boolean(), false), - value_optional: ss.defaulted(ss.boolean(), false), - value_format: ss.defaulted(ss.nullable(valueFormat()), null), - }), - 'modifier', - // Additional checks - (config) => { - // `block_only` and `exception_only` are mutually exclusive, so they can't be both true - if (config.block_only && config.exception_only) { - return 'block_only and exception_only are mutually exclusive'; - } - - if (config.assignable && !config.value_format) { - return 'value_format is required for assignable modifiers'; - } - - // `deprecated` and `deprecation_message` should be both present or both absent - if (config.deprecated && !config.deprecation_message) { - return 'deprecation_message is required for deprecated modifiers'; - } - if (!config.deprecated && config.deprecation_message) { - return 'deprecation_message is only allowed for deprecated modifiers'; - } - - if (config.aliases.length !== new Set(config.aliases).size) { - return 'Aliases must be unique'; - } - - return true; - }, - )), - - /** - * Check [## File structure](../src/compatibility-tables/redirects/README.md) - */ - 'src/compatibility-tables/redirects/**.yml': ss.record( - platforms, - ss.refine( - ss.object({ - name: ss.nonempty(ss.string()), - aliases: ss.defaulted(ss.array(ss.nonempty(ss.string())), []), - is_blocking: ss.defaulted(ss.boolean(), false), - description: ss.defaulted(ss.nullable(ss.string()), null), - docs: ss.defaulted(ss.nullable(ss.nonempty(ss.string())), null), - version_added: ss.defaulted(ss.nullable(ss.nonempty(ss.string())), null), - version_removed: ss.defaulted(ss.nullable(ss.nonempty(ss.string())), null), - deprecated: ss.defaulted(ss.boolean(), false), - deprecation_message: ss.defaulted(ss.nullable(ss.nonempty(ss.string())), null), - }), - 'redirects', - (config) => { - if (config.aliases.length !== new Set(config.aliases).size) { - return 'Aliases must be unique'; - } - - return true; - }, - ), - ), - - /** - * Check [## File structure](../src/compatibility-tables/scriptlets/README.md) - */ - 'src/compatibility-tables/scriptlets/**.yml': ss.record( - platforms, - ss.refine( - ss.object({ - name: ss.nonempty(ss.string()), - aliases: ss.defaulted(ss.array(ss.nonempty(ss.string())), []), - description: ss.defaulted(ss.nullable(ss.string()), null), - docs: ss.defaulted(ss.nullable(ss.nonempty(ss.string())), null), - version_added: ss.defaulted(ss.nullable(ss.nonempty(ss.string())), null), - version_removed: ss.defaulted(ss.nullable(ss.nonempty(ss.string())), null), - debug: ss.defaulted(ss.boolean(), false), - deprecated: ss.defaulted(ss.boolean(), false), - deprecation_message: ss.defaulted(ss.nullable(ss.nonempty(ss.string())), null), - parameters: ss.defaulted(ss.array(ss.object({ - name: ss.nonempty(ss.string()), - required: ss.boolean(), - description: ss.defaulted(ss.nullable(ss.string()), null), - pattern: ss.defaulted(ss.nullable(ss.string()), null), - default: ss.defaulted(ss.nullable(ss.string()), null), - debug: ss.defaulted(ss.boolean(), false), - })), []), - }), - 'scriptlets', - (config) => { - if (config.aliases.length !== new Set(config.aliases).size) { - return 'Aliases must be unique'; - } - - return true; - }, - ), - ), -}; - -/** - * List of all problems found in the compatibility tables. - * We don't throw an error immediately because we want to check all files. - */ -const problems: { [key: string]: string[] } = {}; - -for (const [globPattern, schema] of Object.entries(SCHEMA_MAP)) { - // Get all files matching the glob pattern - const files = globSync(globPattern); - - for (const file of files) { - // Get file contents - const content = readFileSync(file, 'utf8'); - - try { - // Parse YAML to object (throws if the YAML syntax is invalid) - const data = yaml.load(content); - - // Validate the object against the schema (throws if the object is invalid) - // Needs to use 'create' instead of 'assert' because we want to set the - // default values for optional properties. - - // In order to avoid type errors, we need to cast the schema to 'Struct'. - // It is safe to do so because we don't use create()'s return value. - // TODO: Better way to do this? Is it necessary? - if (typeof data === 'object' && data !== null && 'define' in data) { - delete data.define; - } - ss.create(data, schema as ss.Struct); - } catch (error: unknown) { - if (error instanceof Error) { - if (file in problems) { - problems[file].push(error.message); - } else { - problems[file] = [error.message]; - } - } else { - // Unknown error, abort the script - throw error; - } - } - } -} - -// Print the results -if (Object.keys(problems).length === 0) { - console.log('All compatibility tables are valid.'); -} else { - console.error('The following compatibility tables are invalid:'); - - for (const [file, errors] of Object.entries(problems)) { - console.error(` ${join(file)}:`); - for (const error of errors) { - console.error(` - ${error}`); - } - } - - // Exit with error code 1 (so that the CI fails) - process.exit(1); -} diff --git a/packages/agtree/src/compatibility-tables/README.md b/packages/agtree/src/compatibility-tables/README.md index 133c03130..7e394bf01 100644 --- a/packages/agtree/src/compatibility-tables/README.md +++ b/packages/agtree/src/compatibility-tables/README.md @@ -2,13 +2,37 @@ This directory contains compatibility tables for various adblock rule features. +Table of contents: + +- [Compatibility tables](#compatibility-tables) + - [Supported categories](#supported-categories) + - [Supported adblockers and platforms](#supported-adblockers-and-platforms) + - [Specific platforms](#specific-platforms) + - [Generic platforms](#generic-platforms) + - [Combining platforms](#combining-platforms) + - [Programmatic API](#programmatic-api) + - [General API](#general-api) + - [Available compatibility table instances](#available-compatibility-table-instances) + - [Platform flags](#platform-flags) + - [Platform expressions parser](#platform-expressions-parser) + - [Examples](#examples) + - [Check if a modifier is supported by any adblocker](#check-if-a-modifier-is-supported-by-any-adblocker) + - [Check if a modifier is supported by a specific / generic platform](#check-if-a-modifier-is-supported-by-a-specific--generic-platform) + - [Get modifier compatibility data for a specific platform](#get-modifier-compatibility-data-for-a-specific-platform) + - [Get modifier compatibility data for a generic platform](#get-modifier-compatibility-data-for-a-generic-platform) + - [Get all supported modifiers for a specific / generic platform](#get-all-supported-modifiers-for-a-specific--generic-platform) + - [Get first compatible modifier for a specific / generic platform](#get-first-compatible-modifier-for-a-specific--generic-platform) + - [Get compatibility table row](#get-compatibility-table-row) + - [Get all modifiers grouped by product](#get-all-modifiers-grouped-by-product) + ## Supported categories Currently, the following categories are supported. Each category has its own compatibility table: -- Modifiers -- Scriptlets -- (Extended) CSS selectors +- [Rule modifiers][modifiers-table] ([Extended version][modifiers-table-extended]) +- [Redirect resources][redirects-table] +- [Scriptlet resources][scriptlets-table] +- (Extended) CSS pseudo-classes :construction: Please note that certain things, such as syntax or rule categories, cannot be handled by the compatibility table. This is simply because they rarely change, and would also require a high level of abstraction, so it is much easier @@ -16,13 +40,20 @@ to manage them at a low level, at the parser / converter level. The compatibilit are well abstracted and common to several adblockers, just with different implementations. For example, network rule modifiers or CSS selectors are used by all adblockers, but with different functionality. +[modifiers-table]: ./wiki/modifiers-compatibility-table.md +[modifiers-table-extended]: ./wiki/modifiers-compatibility-table-extended.md +[redirects-table]: ./wiki/redirects-compatibility-table.md +[scriptlets-table]: ./wiki/scriptlets-compatibility-table.md + ## Supported adblockers and platforms Currently we support the following adblockers: -- AdGuard (`adg`) -- uBlock Origin (`ubo`) -- AdBlock / Adblock Plus (`abp`) + +- AdGuard logo AdGuard (`adg`) +- uBlock logo uBlock Origin (`ubo`) +- Adblock Plus logo AdBlock / Adblock Plus (`abp`) + However, there may also be compatibility differences within a brand due to the specificities and limitations of each platform. For example: @@ -33,51 +64,346 @@ platform. For example: Chrome's API does not provide this level of network-level filtering, while Firefox's does. - etc. -Therefore, we need to specify the platform for each adblocker to cover all the edge cases. The following platforms are -supported: +Therefore, we need to specify the platform for each adblocker to cover all the edge cases. + +### Specific platforms + +The following specific platforms are supported: -| Platform (ID) | Brand | Category | -| --- | --- | --- | - `adg_os_windows` | [AdGuard for Windows](https://adguard.com/adguard-windows/overview.html) | System-wide ad blocker | -`adg_os_mac` | [AdGuard for Mac](https://adguard.com/adguard-mac/overview.html) | System-wide ad blocker | -`adg_os_android` | [AdGuard for Android](https://adguard.com/adguard-android/overview.html) | System-wide ad blocker | -`adg_ext_chrome` | [AdGuard extension for Chrome](https://adguard.com/adguard-browser-extension/chrome/overview.html) | Browser extension | -`adg_ext_opera` | [AdGuard extension for Opera](https://adguard.com/adguard-browser-extension/opera/overview.html) | Browser extension | -`adg_ext_edge` | [AdGuard extension for Edge](https://adguard.com/adguard-browser-extension/edge/overview.html) | Browser extension | -`adg_ext_firefox` | [AdGuard extension for Firefox](https://adguard.com/adguard-browser-extension/firefox/overview.html) | Browser extension | -`adg_cb_android` | [AdGuard Content Blocker for Android](https://adguard.com/adguard-content-blocker/overview.html) | Content blocker | -`adg_cb_ios` | [AdGuard Content Blocker for iOS](https://adguard.com/adguard-ios/overview.html) | Content blocker | -`adg_cb_safari` | [AdGuard Content Blocker for Safari](https://adguard.com/adguard-safari/overview.html) | Content blocker | -`ubo_ext_chrome` | [uBlock Origin for Google Chrome](https://chrome.google.com/webstore/detail/ublock-origin/cjpalhdlnbpafiamejdnhcphjbkeiagm) | Browser extension | -`ubo_ext_firefox` | [uBlock Origin for Mozilla Firefox](https://addons.mozilla.org/addon/ublock-origin/) | Browser extension | -`ubo_ext_opera` | [uBlock Origin for Opera](https://addons.opera.com/extensions/details/ublock/) | Browser extension | -`ubo_ext_edge` | [uBlock Origin for Microsoft Edge](https://microsoftedge.microsoft.com/addons/detail/ublock-origin/odfafepnkmbhccpbejgmiehpchacaeak) | Browser extension | -`abp_ext_chrome` | [Adblock Plus for Google Chrome](https://chrome.google.com/webstore/detail/cfhdojbkjhnklbpkdaibdccddilifddb) | Browser extension | -`abp_ext_firefox` | [Adblock Plus for Mozilla Firefox](https://eyeo.to/adblockplus/firefox_install/) | Browser extension | -`abp_ext_opera` | [Adblock Plus for Opera](https://eyeo.to/adblockplus/opera_install/) | Browser extension | -`abp_ext_edge` | [Adblock Plus for Microsoft Edge](https://eyeo.to/adblockplus/edge_install/) | Browser extension | + +| Platform (ID) | Brand | Category | +| ----------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------- | +| `adg_os_windows` | AdGuard logo [AdGuard for Windows](https://adguard.com/adguard-windows/overview.html) | System-wide ad blocker | +| `adg_os_mac` | AdGuard logo [AdGuard for Mac](https://adguard.com/adguard-mac/overview.html) | System-wide ad blocker | +| `adg_os_android` | AdGuard logo [AdGuard for Android](https://adguard.com/adguard-android/overview.html) | System-wide ad blocker | +| `adg_ext_chrome` | AdGuard logo [AdGuard extension for Chrome](https://adguard.com/adguard-browser-extension/chrome/overview.html) | Browser extension | +| `adg_ext_opera` | AdGuard logo [AdGuard extension for Opera](https://adguard.com/adguard-browser-extension/opera/overview.html) | Browser extension | +| `adg_ext_edge` | AdGuard logo [AdGuard extension for Edge](https://adguard.com/adguard-browser-extension/edge/overview.html) | Browser extension | +| `adg_ext_firefox` | AdGuard logo [AdGuard extension for Firefox](https://adguard.com/adguard-browser-extension/firefox/overview.html) | Browser extension | +| `adg_cb_android` | AdGuard logo [AdGuard Content Blocker for Android](https://adguard.com/adguard-content-blocker/overview.html) | Content blocker | +| `adg_cb_ios` | AdGuard logo [AdGuard Content Blocker for iOS](https://adguard.com/adguard-ios/overview.html) | Content blocker | +| `adg_cb_safari` | AdGuard logo [AdGuard Content Blocker for Safari](https://adguard.com/adguard-safari/overview.html) | Content blocker | +| `ubo_ext_chrome` | uBlock logo [uBlock Origin for Google Chrome](https://chrome.google.com/webstore/detail/ublock-origin/cjpalhdlnbpafiamejdnhcphjbkeiagm) | Browser extension | +| `ubo_ext_firefox` | uBlock logo [uBlock Origin for Mozilla Firefox](https://addons.mozilla.org/addon/ublock-origin/) | Browser extension | +| `ubo_ext_opera` | uBlock logo [uBlock Origin for Opera](https://addons.opera.com/extensions/details/ublock/) | Browser extension | +| `ubo_ext_edge` | uBlock logo [uBlock Origin for Microsoft Edge](https://microsoftedge.microsoft.com/addons/detail/ublock-origin/odfafepnkmbhccpbejgmiehpchacaeak) | Browser extension | +| `abp_ext_chrome` | Adblock Plus logo [Adblock Plus for Google Chrome](https://chrome.google.com/webstore/detail/cfhdojbkjhnklbpkdaibdccddilifddb) | Browser extension | +| `abp_ext_firefox` | Adblock Plus logo [Adblock Plus for Mozilla Firefox](https://eyeo.to/adblockplus/firefox_install/) | Browser extension | +| `abp_ext_opera` | Adblock Plus logo [Adblock Plus for Opera](https://eyeo.to/adblockplus/opera_install/) | Browser extension | +| `abp_ext_edge` | Adblock Plus logo [Adblock Plus for Microsoft Edge](https://eyeo.to/adblockplus/edge_install/) | Browser extension | + -For simplicity, the following shortcuts are also supported: +### Generic platforms + +For simplicity, we introduced the concept of "generic platforms" that represent a group of specific platforms. +This is useful when we want to specify compatibility for a group of platforms, but not for all of them. -| Shortcut (ID) | Description | Equivalent to (shortcut or platform) | -| --- | --- | --- | -| `any` | Any adblocker, any platform | `adg_any`, `ubo_any`, `abp_any` | -| `adg_any` | Any AdGuard adblocker | `adg_os_any`, `adg_ext_any`, `adg_cb_any` | -| `adg_os_any` | Any AdGuard OS-wide app (using [CoreLibs](https://github.com/AdguardTeam/CoreLibs)) | `adg_os_windows`, `adg_os_mac`, `adg_os_android` | -| `adg_ext_any` | Any AdGuard browser extension | `adg_ext_chromium`, `adg_ext_firefox` | -| `adg_ext_chromium` | AdGuard browser extension for Chromium-based browsers\* | `adg_ext_chrome`, `adg_ext_opera`, `adg_ext_edge` | -| `adg_cb_any` | Any AdGuard content blocker | `adg_cb_android`, `adg_cb_ios`, `adg_cb_safari` | -| `adg_any_not_cb` | Any AdGuard adblocker except content blockers | `adg_os_any`, `adg_ext_any` | -| `ubo_any` | Any uBlock Origin browser extension | `ubo_ext_any` | -| `ubo_ext_any` | Any uBlock Origin browser extension | `ubo_ext_chromium`, `ubo_ext_firefox` | -| `ubo_ext_chromium` | uBlock Origin browser extension for Chromium-based browsers\* | `ubo_ext_chrome`, `ubo_ext_opera`, `ubo_ext_edge` | -| `abp_any` | Any Adblock Plus browser extension | `abp_ext_any` | -| `abp_ext_any` | Any Adblock Plus browser extension | `abp_ext_chromium`, `abp_ext_firefox` | -| `abp_ext_chromium` | Adblock Plus browser extension for Chromium-based browsers\* | `abp_ext_chrome`, `abp_ext_opera`, `abp_ext_edge` | + +| Generic platform (ID) | Description | Equivalent to (shortcut or platform) | +| --------------------- | ----------------------------------------------------------------------------------- | --------------------------------------------------------------- | +| `any` | Any adblocker, any platform | `adg_any`, `ubo_any`, `abp_any` | +| `adg_any` | Any AdGuard adblocker | `adg_os_any`, `adg_ext_any`, `adg_safari_any`, `adg_cb_android` | +| `adg_os_any` | Any AdGuard OS-wide app (using [CoreLibs](https://github.com/AdguardTeam/CoreLibs)) | `adg_os_windows`, `adg_os_mac`, `adg_os_android` | +| `adg_ext_any` | Any AdGuard browser extension | `adg_ext_chromium`, `adg_ext_firefox` | +| `adg_ext_chromium` | AdGuard browser extension for Chromium-based browsers\* | `adg_ext_chrome`, `adg_ext_opera`, `adg_ext_edge` | +| `adg_safari_any` | Any AdGuard Safari-like content blocker | `adg_cb_ios`, `adg_cb_safari` | +| `ubo_any` | Any uBlock Origin browser extension | `ubo_ext_any` | +| `ubo_ext_any` | Any uBlock Origin browser extension | `ubo_ext_chromium`, `ubo_ext_firefox` | +| `ubo_ext_chromium` | uBlock Origin browser extension for Chromium-based browsers\* | `ubo_ext_chrome`, `ubo_ext_opera`, `ubo_ext_edge` | +| `abp_any` | Any Adblock Plus browser extension | `abp_ext_any` | +| `abp_ext_any` | Any Adblock Plus browser extension | `abp_ext_chromium`, `abp_ext_firefox` | +| `abp_ext_chromium` | Adblock Plus browser extension for Chromium-based browsers\* | `abp_ext_chrome`, `abp_ext_opera`, `abp_ext_edge` | + \* Chromium-based browsers include Google Chrome, Microsoft Edge, Opera, Brave, Vivaldi, etc. See more details -[here](https://en.wikipedia.org/wiki/Chromium_(web_browser)). +[here](). + +### Combining platforms + +You can combine platforms by using the `|` operator. For example, `adg_os_any|adg_ext_firefox` means that the feature +is supported by any AdGuard OS-wide app and the AdGuard extension for Firefox. + +If needed, you can also negate a platform by using the `~` operator. For example, `adg_any|~adg_safari_any` means +that the feature is supported by any AdGuard adblocker, except for AdGuard Safari-like content blockers. + +## Programmatic API + +Compatibility table also provides a programmatic API to access compatibility data. + +### General API + +#### Available compatibility table instances + +We export the following compatibility table instances: + +```ts +import { + redirectsCompatibilityTable, + scriptletsCompatibilityTable, + modifiersCompatibilityTable, +} from '@adguard/agtree'; +``` + +All of them provides the following methods for their respective compatibility data: + + + +| Method name | Description | +| --- | --- | +| `existsAny(name: string): boolean` | Checks whether a compatibility data `name` exists for any platform. | +| `exists(name: string, platform: SpecificPlatform \| GenericPlatform): boolean` | Checks whether a compatibility data `name` exists for a specified platform. | +| `getSingle(name: string, platform: SpecificPlatform): T \| null` | Returns a compatibility data by name and specific platform. | +| `getMultiple(name: string, platform: SpecificPlatform \| GenericPlatform): SinglePlatformRecords \| null` | Returns all compatibility data records for name and specified platform. | +| `getAllMultiple(platform: SpecificPlatform \| GenericPlatform): SinglePlatformRecords[]` | Returns all compatibility data records for the specified platform. | +| `getFirst(name: string, platform: SpecificPlatform \| GenericPlatform): T \| null` | Returns the first compatibility data record for name and specified platform. | +| `getRow(name: string): T[]` | Returns all compatibility data records for the specified name. | +| `getRowsByProduct(): RowsByProduct` | Returns all compatibility data records grouped by product. | + +All methods based on the name of the entity and the platform. + + + +#### Platform flags + +The `SpecificPlatform` and `GenericPlatform` enums are used to specify the platform in the API methods. +These enums represents bit flags, so you can combine them on demand. + +```ts +import { SpecificPlatform, GenericPlatform } from '@adguard/agtree'; +``` + +#### Platform expressions parser + +We also provide a parser for platform expressions. You can use it to parse a raw platform string into a platform flag. + +```ts +import { parseRawPlatforms } from '@adguard/agtree'; + +parseRawPlatforms('adg_os_windows|ubo_ext_chrome'); +``` + +### Examples + +In this section, we provide examples of how to use the compatibility table API. +Examples are based on the `modifiersCompatibilityTable` instance, but you can use the same API for other tables. + +#### Check if a modifier is supported by any adblocker + +If you want to check if the `$third-party` modifier is supported by any AdGuard adblocker, +you can use the following code: + +```ts +import { modifiersCompatibilityTable } from '@adguard/agtree'; + +modifiersCompatibilityTable.existsAny('third-party'); +``` + +#### Check if a modifier is supported by a specific / generic platform + +If you want to check if the `$third-party` modifier is supported by any AdGuard OS-wide app +or the AdGuard extension for Firefox, you can use the following code: + +```ts +import { modifiersCompatibilityTable, SpecificPlatform, parseRawPlatforms } from '@adguard/agtree'; + +modifiersCompatibilityTable.exists('third-party', GenericPlatform.AdgOsAny | SpecificPlatform.AdgExtFirefox); +// or you can use the `parseRawPlatforms` helper function if you prefer raw platform expressions: +modifiersCompatibilityTable.exists('third-party', parseRawPlatforms('adg_os_any|adg_ext_firefox')); +``` + +#### Get modifier compatibility data for a specific platform + +If you want to get all compatibility data for the `$third-party` modifier for AdGuard Extension for Chrome, +you can use the following code: + +```ts +import { modifiersCompatibilityTable, SpecificPlatform } from '@adguard/agtree'; + +modifiersCompatibilityTable.getSingle('third-party', SpecificPlatform.AdgExtChrome); +``` + +this will returns all compatibility data for the `$third-party` modifier for AdGuard Extension for Chrome: + +```js +{ + name: 'third-party', + aliases: [ '3p' ], + description: 'A restriction of third-party and own requests.\n' + + 'A third-party request is a request from a different domain.\n' + + 'For example, a request to `example.org` from `domain.com` is a third-party request.', + docs: 'https://adguard.app/kb/general/ad-filtering/create-own-filters/#third-party-modifier', + versionAdded: null, + versionRemoved: null, + deprecated: false, + deprecationMessage: null, + removed: false, + removalMessage: null, + conflicts: null, + inverseConflicts: false, + assignable: false, + negatable: true, + blockOnly: false, + exceptionOnly: false, + valueOptional: false, + valueFormat: null +} +``` + +You can get any field from the compatibility data object you need. + +Of course, if you specify some non-existent modifier, the method will return `null`. + +#### Get modifier compatibility data for a generic platform + +If you want to get all compatibility data for the `$third-party` modifier for any AdGuard browser extension, +you can use the following code: + +```ts +import { modifiersCompatibilityTable, SpecificPlatform } from '@adguard/agtree'; + +modifiersCompatibilityTable.getMultiple('third-party', GenericPlatform.AdgExtAny); +``` + +this will returns an object where keys are specific platforms and values are compatibility data for the `$third-party` +modifier: + +```js +{ + // 8 = SpecificPlatform.AdgExtChrome + '8': { + name: 'third-party', + aliases: [ '3p' ], + description: 'A restriction of third-party and own requests.\n' + + 'A third-party request is a request from a different domain.\n' + + 'For example, a request to `example.org` from `domain.com` is a third-party request.', + docs: 'https://adguard.app/kb/general/ad-filtering/create-own-filters/#third-party-modifier', + // ... + }, + // 16 = SpecificPlatform.AdgExtOpera + '16': { + name: 'third-party', + // ... + }, + // 32 = SpecificPlatform.AdgExtEdge + '32': { + name: 'third-party', + // ... + }, + // 64 = SpecificPlatform.AdgExtFirefox + '64': { + name: 'third-party', + // ... + } +} +``` + +#### Get all supported modifiers for a specific / generic platform + +If you want to get all supported modifiers for AdGuard OS-wide app for Windows, you can use the following code: + +```ts +import { modifiersCompatibilityTable, SpecificPlatform } from '@adguard/agtree'; + +modifiersCompatibilityTable.getAllMultiple(SpecificPlatform.AdgOsWindows); +``` + +This will return an array of compatible modifiers for AdGuard OS-wide app for Windows. + +This method also works for generic platforms, for example, to get all supported modifiers for +any AdGuard OS-wide app, you can use the following code: + +```ts +modifiersCompatibilityTable.getAllMultiple(GenericPlatform.AdgOsAny); +``` + +#### Get first compatible modifier for a specific / generic platform + +As you've seen in the previous example, there are multiple compatible modifiers for a generic platform, +but sometimes you may need only the first compatible modifier. + +If you want to get the first compatible modifier for AdGuard OS-wide app for Windows, you can use the following code: + +```ts +import { modifiersCompatibilityTable, SpecificPlatform } from '@adguard/agtree'; + +modifiersCompatibilityTable.getFirst('third-party', SpecificPlatform.AdgOsWindows); +``` + +#### Get compatibility table row + +Sometimes you may need to get all compatibility data for a specific modifier, redirect, or scriptlet. +Lets say you want to get all compatibility data for the `$third-party` modifier: + +```ts +import { modifiersCompatibilityTable } from '@adguard/agtree'; + +modifiersCompatibilityTable.getRow('third-party'); +``` + +this will returns all compatibility data for the `$third-party` modifier: + +```js +[ + { + name: 'third-party', + aliases: [ '3p' ], + docs: 'https://adguard.app/kb/general/ad-filtering/create-own-filters/#third-party-modifier', + // ... + }, + { + name: '3p', + aliases: [ 'third-party' ], + docs: 'https://github.com/gorhill/uBlock/wiki/Static-filter-syntax#3p', + // ... + }, + { + name: 'third-party', + aliases: null, + docs: 'https://help.adblockplus.org/hc/en-us/articles/360062733293#party-requests', + // ... + } +] +``` + +As you can see, `aliases` and `docs` fields are different for each platform. + +#### Get all modifiers grouped by product + +If you want to get all compatibility data grouped by product, you can use the following code: + +```ts +import { modifiersCompatibilityTable } from '@adguard/agtree'; + +modifiersCompatibilityTable.getRowsByProduct(); +``` + +This will returns an array where each element is an object that represents compatibility data for a given modifier. + +```js +[ + { + AdGuard: { + // key are platform flags + '1': [Object], + '2': [Object], + // ... + }, + UblockOrigin: { + // key are platform flags + '1024': [Object], + '2048': [Object], + '4096': [Object], + '8192': [Object] + }, + // seems its not compatible with AdblockPlus + AdblockPlus: {} + }, + // ... +] +``` + +Practically, we use this function to generate compatibility tables in the WIKI. diff --git a/packages/agtree/src/compatibility-tables/TODO.md b/packages/agtree/src/compatibility-tables/TODO.md index 14cf432a1..d0b987962 100644 --- a/packages/agtree/src/compatibility-tables/TODO.md +++ b/packages/agtree/src/compatibility-tables/TODO.md @@ -1,18 +1,27 @@ # Compatibility tables TODO list -- [ ] Fill compatibility tables with data. - - [ ] Import scriptlets/redirects from AdGuard Scriptlets library? GitHub Action for importing? - - [ ] GitHub Action workflow that checks YML files for errors. -- [ ] Finalize table structure, if needed. It depends on edge cases and how we'll use the tables in the API. -- [ ] Table optimization, if needed. We need a maintainable, convenient data structure for the tables, so maybe we'll +- [x] Fill compatibility tables with data. + - [x] Import scriptlets/redirects from AdGuard Scriptlets library? GitHub Action for importing? + - [x] GitHub Action workflow that checks YML files for errors. +- [x] Finalize table structure, if needed. It depends on edge cases and how we'll use the tables in the API. +- [x] Table optimization, if needed. We need a maintainable, convenient data structure for the tables, so maybe we'll need to optimize it before using it in the API. -- [ ] Create API endpoints for the tables. -- [ ] Wiki generation (`.md` files from the tables / gh-pages). +- [x] Create API endpoints for the tables. +- [x] Wiki generation (`.md` files from the tables / gh-pages). - [ ] Review redirects' aliases in compatibility table: - [ ] check if `ubo-` and `abp-` prefixes should be deprecated, - - [ ] make compatibility table does not miss any [ubo aliases](https://raw.githubusercontent.com/gorhill/uBlock/master/src/js/redirect-resources.js). + - [x] make compatibility table does not miss any [ubo aliases](https://raw.githubusercontent.com/gorhill/uBlock/master/src/js/redirect-resources.js). +- [ ] Re-use data in YAML files via anchors. This will help to avoid duplication and make the data more maintainable. +- [ ] Make a site for compatibility tables in React and deploy it to GitHub Pages. + Make entities searchable and viewable by URL. +- [ ] Handle negated aliases properly, like `first-party` and `~third-party`. +- [ ] Consider adding a field called `limited` and `limitationMessage` to the compatibility tables. + This field will be used to indicate that the entity is limited in some way and provide a message with details. +- [ ] Add documentation link and description to all redirect resources. +- [ ] Add Extended CSS features to the compatibility tables. +- [ ] Add more tests for the compatibility tables API. ## Linter rules diff --git a/packages/agtree/src/compatibility-tables/base.ts b/packages/agtree/src/compatibility-tables/base.ts new file mode 100644 index 000000000..5855c9bfd --- /dev/null +++ b/packages/agtree/src/compatibility-tables/base.ts @@ -0,0 +1,350 @@ +/* eslint-disable no-bitwise */ +/** + * @file Provides common compatibility table methods. + */ + +import { type BaseCompatibilityDataSchema } from './schemas'; +import { GenericPlatform, type SpecificPlatform } from './platforms'; +import { isUndefined } from '../utils/common'; +import { type CompatibilityTable, type CompatibilityTableRow } from './types'; +import { isGenericPlatform, getSpecificPlatformName } from './utils/platform-helpers'; +import { AdblockSyntax } from '../utils/adblockers'; + +/** + * Lists all supported entity records by a product. + * + * Keys are compatibility flags, values are compatibility data records. + * + * @template T Compatibility data schema. + */ +export type ProductRecords = { + [key: string]: T +}; + +/** + * Defines a compatibility table row by product. + * + * Keys are Adblock syntaxes, values are product records. + * + * @template T Compatibility data schema. + */ +export type RowByProduct = { + [AdblockSyntax.Adg]: ProductRecords; + [AdblockSyntax.Ubo]: ProductRecords; + [AdblockSyntax.Abp]: ProductRecords; +}; + +/** + * Defines multiple compatibility table rows by product. + * + * @template T Compatibility data schema. + */ +export type RowsByProduct = RowByProduct[]; + +/** + * Single platform records type. + * + * Keys are platform enums values, values are compatibility data records. + * + * @template T Compatibility data schema. + */ +type SinglePlatformRecords = { + [key: string]: T +}; + +/** + * Name transformer function type. This function is used to normalize compatibility data names before processing them, + * e.g. converting to lowercase, remove unnecessary prefixes, etc. + * + * @param name Compatibility data name. + * + * @returns Normalized name. + */ +type NameTransformer = (name: string) => string; + +/** + * Base compatibility table class which provides common methods to work with compatibility data. + * + * @template T Compatibility data schema. + */ +export abstract class CompatibilityTableBase { + /** + * Compatibility table data. + */ + private data: CompatibilityTable; + + /** + * Optional name transformer function. If provided, + * it will be called in all methods before processing compatibility data names. + */ + private readonly nameTransformer: NameTransformer | null; + + /** + * Creates a new instance of the common compatibility table. + * + * @param data Compatibility table data. + * @param nameTransformer Optional name transformer function. + */ + constructor(data: CompatibilityTable, nameTransformer: NameTransformer | null = 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. + */ + private getRowStorage(name: string): CompatibilityTableRow | null { + const idx = this.data.map[name]; + + if (isUndefined(idx)) { + return null; + } + + return this.data.shared[idx]; + } + + /** + * Checks whether a compatibility data `name` exists for any platform. + * + * @note Technically, do the same as `exists()` method with generic platform _any_ + * but it is faster because it does not apply complex logic. + * + * @param name Compatibility data name. + * + * @returns True if the compatibility data exists, false otherwise. + */ + public existsAny(name: string): boolean { + const normalizedName = this.nameTransformer ? this.nameTransformer(name) : name; + return !isUndefined(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. + */ + public exists(name: string, platform: SpecificPlatform | GenericPlatform): boolean { + const normalizedName = this.nameTransformer ? this.nameTransformer(name) : name; + const data = this.getRowStorage(normalizedName); + + if (!data) { + return false; + } + + const isMatch = (idx: number): boolean => { + const el = data.shared[idx]; + return !isUndefined(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. + */ + public getSingle(name: string, platform: SpecificPlatform): T | null { + const normalizedName = this.nameTransformer ? this.nameTransformer(name) : name; + const data = this.getRowStorage(normalizedName); + + if (!data) { + return null; + } + + const idx = data.map[platform]; + return isUndefined(idx) ? null : data.shared[idx]; + } + + /** + * 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. + */ + public getMultiple(name: string, platform: SpecificPlatform | GenericPlatform): SinglePlatformRecords | null { + const normalizedName = this.nameTransformer ? this.nameTransformer(name) : name; + const data = this.getRowStorage(normalizedName); + + if (!data) { + return null; + } + + if (isGenericPlatform(platform)) { + const result: SinglePlatformRecords = {}; + const keys = Object.keys(data.map); + + for (let i = 0; i < keys.length; i += 1) { + const key = Number(keys[i]); + if (platform & key) { + const idx = data.map[key]; + if (!isUndefined(idx)) { + result[key] = data.shared[idx]; + } + } + } + + return result; + } + + const idx = data.map[platform]; + if (isUndefined(idx)) { + return null; + } + + return { key: data.shared[idx] }; + } + + /** + * Returns all compatibility data records for the specified platform. + * + * @param platform Specific or generic platform. + * + * @returns Array of multiple records grouped by platforms. + */ + public getAllMultiple(platform: SpecificPlatform | GenericPlatform): SinglePlatformRecords[] { + const result: SinglePlatformRecords[] = []; + + for (let i = 0; i < this.data.shared.length; i += 1) { + const data = this.data.shared[i]; + + const names = new Set(data.shared.map(({ name }) => name)); + + names.forEach((name) => { + const multipleRecords = this.getMultiple(name, platform); + if (multipleRecords) { + result.push(multipleRecords); + } + }); + } + + return result; + } + + /** + * Returns the first compatibility data record for name and specified platform. + * + * @param name Compatibility data name. + * @param platform Specific or generic platform. + * + * @returns First found compatibility data record or `null` if not found. + */ + public getFirst(name: string, platform: SpecificPlatform | GenericPlatform): T | null { + const normalizedName = this.nameTransformer ? this.nameTransformer(name) : name; + const data = this.getRowStorage(normalizedName); + + if (!data) { + return null; + } + + if (isGenericPlatform(platform)) { + const keys = Object.keys(data.map); + + for (let i = 0; i < keys.length; i += 1) { + const key = Number(keys[i]); + if (platform & key) { + const idx = data.map[key]; + if (!isUndefined(idx)) { + // return the first found record + return data.shared[idx]; + } + } + } + + return null; + } + + const idx = data.map[platform]; + if (isUndefined(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. + */ + public getRow(name: string): T[] { + 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. + */ + public getRowsByProduct(): RowsByProduct { + const result: RowsByProduct = []; + + 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: RowByProduct = { + [AdblockSyntax.Adg]: {}, + [AdblockSyntax.Ubo]: {}, + [AdblockSyntax.Abp]: {}, + }; + + for (let j = 0; j < keys.length; j += 1) { + const key = Number(keys[j]); + if (key & GenericPlatform.AdgAny) { + row[AdblockSyntax.Adg][key] = data.shared[data.map[key]]; + } else if (key & GenericPlatform.UboAny) { + row[AdblockSyntax.Ubo][key] = data.shared[data.map[key]]; + } else if (key & GenericPlatform.AbpAny) { + row[AdblockSyntax.Abp][key] = data.shared[data.map[key]]; + } + } + + result.push(row); + } + + return result; + } +} diff --git a/packages/agtree/src/compatibility-tables/compatibility-table-data.ts b/packages/agtree/src/compatibility-tables/compatibility-table-data.ts new file mode 100644 index 000000000..a424369bf --- /dev/null +++ b/packages/agtree/src/compatibility-tables/compatibility-table-data.ts @@ -0,0 +1,186 @@ +/* eslint-disable no-bitwise */ +/** + * @file Provides compatibility table data loading. + */ + +import path from 'path'; +// eslint-disable-next-line import/no-extraneous-dependencies +import yaml from 'js-yaml'; +import { readFileSync, readdirSync } from 'fs'; + +import { type CompatibilityTable, type CompatibilityTableRow } from './types'; +import { + type BaseCompatibilityDataSchema, + baseFileSchema, + modifierDataSchema, + redirectDataSchema, + scriptletDataSchema, + type ModifierDataSchema, + type RedirectDataSchema, + type ScriptletDataSchema, +} from './schemas'; +import { deepFreeze } from '../utils/deep-freeze'; + +/** + * Gets all `.yml` files from a directory. + * + * @param dir Directory to get the `.yml` files from. + * + * @returns List of `.yml` files or an empty list if no files found. + */ +const getYmlFilesFromDir = (dir: string): string[] => { + const dirEntries = readdirSync(dir, { withFileTypes: true }); + + return dirEntries + .filter((dirent) => dirent.isFile() && dirent.name.endsWith('.yml')) + .map((dirent) => dirent.name); +}; + +/** + * Gets active bit slots from a number, i.e. positions where bits are 1. + * + * @param n Number to get active bit slots from. + * + * @returns List of active bit slots. + * + * @example + * ```ts + * getActiveBitSlots(0b101) // => [1, 4] + * ``` + */ +const getActiveBitSlots = (n: number): number[] => { + const result = []; + + for (let i = 0; i < 32; i += 1) { + const p = n & (1 << i); + if (p) { + result.push(p); + } + } + + return result; +}; + +/** + * Gets compatibility table data from a directory. + * + * @param dir Directory to get the compatibility table data from. + * @param fileSchema File schema to parse the compatibility table data. + * + * @returns Compatibility table data. + * + * @template T Type of the compatibility data schema. + * + * @throws Error if the file is not found or cannot be read. + * + * @note We only run this when testing, before the build, compatibility tables should be pre-built + * to `dist/compatibility-tables.json` to avoid unnecessary processing. + * + * @internal + */ +const getCompatibilityTableData = ( + dir: string, + fileSchema: ReturnType>, +): CompatibilityTable => { + const rawFiles = getYmlFilesFromDir(dir); + + const parsedFileContents = rawFiles.map((file) => { + const rawFileContent = readFileSync(`${dir}/${file}`, 'utf8'); + const fileData = yaml.load(rawFileContent); + return fileSchema.parse(fileData); + }); + + const data: CompatibilityTable = { + shared: [], + map: {}, + }; + + parsedFileContents.forEach((file) => { + const aliases = new Set(); + + const fileData: CompatibilityTableRow = { + shared: [], + map: {}, + }; + + Object.entries(file).forEach(([platforms, value]) => { + aliases.add(value.name); + + const fileAliases = value.aliases; + + if (fileAliases) { + fileAliases.forEach((alias: string) => aliases.add(alias)); + } + + const activeBits = getActiveBitSlots(Number(platforms)); + + fileData.shared.push(value as T); + + activeBits.forEach((activeBit) => { + fileData.map[activeBit] = fileData.shared.length - 1; + }); + }); + + aliases.forEach((alias) => { + data.map[alias] = data.shared.length; + }); + + data.shared.push(fileData); + }); + + return deepFreeze(data); +}; + +/** + * Gets compatibility table data for modifiers. + * + * @param dir Directory to get the compatibility table data from. + * + * @returns Compatibility table data for modifiers. + */ +const getModifiersCompatibilityTableData = (dir: string) => { + return getCompatibilityTableData(dir, baseFileSchema(modifierDataSchema)); +}; + +/** + * Gets compatibility table data for redirects. + * + * @param dir Directory to get the compatibility table data from. + * + * @returns Compatibility table data for redirects. + */ +const getRedirectsCompatibilityTableData = (dir: string) => { + return getCompatibilityTableData(dir, baseFileSchema(redirectDataSchema)); +}; + +/** + * Gets compatibility table data for scriptlets. + * + * @param dir Directory to get the compatibility table data from. + * + * @returns Compatibility table data for scriptlets. + */ +const getScriptletsCompatibilityTableData = (dir: string) => { + return getCompatibilityTableData(dir, baseFileSchema(scriptletDataSchema)); +}; + +/** + * Compatibility table data for scriptlets. + */ +export const scriptletsCompatibilityTableData = getScriptletsCompatibilityTableData( + path.join(__dirname, './scriptlets'), +); + +/** + * Compatibility table data for redirects. + */ +export const redirectsCompatibilityTableData = getRedirectsCompatibilityTableData( + path.join(__dirname, './redirects'), +); + +/** + * Compatibility table data for modifiers. + */ +export const modifiersCompatibilityTableData = getModifiersCompatibilityTableData( + path.join(__dirname, './modifiers'), +); diff --git a/packages/agtree/src/compatibility-tables/index.ts b/packages/agtree/src/compatibility-tables/index.ts index 0e533ba30..61d2f1c8c 100644 --- a/packages/agtree/src/compatibility-tables/index.ts +++ b/packages/agtree/src/compatibility-tables/index.ts @@ -2,11 +2,19 @@ * @file Compatibility tables variables and types reexport. */ -export { getModifiersData } from './modifiers-data'; - +export { modifiersCompatibilityTable } from './modifiers'; +export { redirectsCompatibilityTable } from './redirects'; +export { scriptletsCompatibilityTable } from './scriptlets'; +export * from './types'; +export * from './platforms'; +export type { + ProductRecords, + RowByProduct, + RowsByProduct, +} from './base'; +export { parseRawPlatforms } from './schemas'; export { - type ModifierData, - type ModifierDataMap, - type SpecificPlatformModifierData, - SpecificKey, -} from './types'; + isGenericPlatform, + getPlatformId, + getSpecificPlatformName, +} from './utils/platform-helpers'; diff --git a/packages/agtree/src/compatibility-tables/modifiers-data.ts b/packages/agtree/src/compatibility-tables/modifiers-data.ts deleted file mode 100644 index da77a2f8a..000000000 --- a/packages/agtree/src/compatibility-tables/modifiers-data.ts +++ /dev/null @@ -1,70 +0,0 @@ -import { isUndefined } from '../utils/common'; -import { rawModifiersData } from './raw-modifiers'; -import { - type ModifierData, - type ModifierDataMap, - type SpecificPlatformModifierData, - SpecificKey, -} from './types'; - -/** - * Prepares specific platform modifier data from raw modifiers data — - * sets [default values] to properties that are not defined in raw data. - * - * [default values]: ./modifiers/README.md "Check File structure table for default values." - * - * @param blockerId Key in ModifierData, i.e. 'adg_os_any', 'ubo_ext_any', etc. - * @param rawModifierData Specific platform modifier data from raw modifiers data. - * - * @returns Prepared specific platform modifier data where properties cannot be undefined. - */ -const prepareBlockerData = (blockerId: string, rawModifierData: ModifierData): SpecificPlatformModifierData => { - const rawData = rawModifierData[blockerId]; - const blockerData: SpecificPlatformModifierData = { - [SpecificKey.Name]: rawData[SpecificKey.Name], - [SpecificKey.Aliases]: rawData[SpecificKey.Aliases] || null, - [SpecificKey.Description]: rawData[SpecificKey.Description] || null, - [SpecificKey.Docs]: rawData[SpecificKey.Docs] || null, - [SpecificKey.Deprecated]: rawData[SpecificKey.Deprecated] || false, - [SpecificKey.DeprecationMessage]: rawData[SpecificKey.DeprecationMessage] || null, - [SpecificKey.Removed]: rawData[SpecificKey.Removed] || false, - [SpecificKey.RemovalMessage]: rawData[SpecificKey.RemovalMessage] || null, - [SpecificKey.Conflicts]: rawData[SpecificKey.Conflicts] || null, - [SpecificKey.InverseConflicts]: rawData[SpecificKey.InverseConflicts] || false, - [SpecificKey.Assignable]: rawData[SpecificKey.Assignable] || false, - // 'negatable' should be checked whether it is undefined or not - // because if it is 'false', default value 'true' will override it - [SpecificKey.Negatable]: isUndefined(rawData[SpecificKey.Negatable]) - ? true - : rawData[SpecificKey.Negatable], - [SpecificKey.BlockOnly]: rawData[SpecificKey.BlockOnly] || false, - [SpecificKey.ExceptionOnly]: rawData[SpecificKey.ExceptionOnly] || false, - [SpecificKey.ValueOptional]: rawData[SpecificKey.ValueOptional] || false, - [SpecificKey.ValueFormat]: rawData[SpecificKey.ValueFormat] || null, - }; - return blockerData; -}; - -/** - * Prepares raw modifiers data into a data map with default values for properties - * that are not defined in raw data. - * - * @returns Map of parsed and prepared modifiers data. - */ -export const getModifiersData = (): ModifierDataMap => { - const dataMap = new Map(); - - Object.keys(rawModifiersData).forEach((modifierId: string) => { - const rawModifierData = rawModifiersData[modifierId]; - - const modifierData: ModifierData = {}; - - Object.keys(rawModifierData).forEach((blockerId) => { - modifierData[blockerId] = prepareBlockerData(blockerId, rawModifierData); - }); - - dataMap.set(modifierId, modifierData); - }); - - return dataMap; -}; diff --git a/packages/agtree/src/compatibility-tables/modifiers.ts b/packages/agtree/src/compatibility-tables/modifiers.ts new file mode 100644 index 000000000..885f7c3a1 --- /dev/null +++ b/packages/agtree/src/compatibility-tables/modifiers.ts @@ -0,0 +1,54 @@ +/** + * @file Compatibility tables for modifiers. + */ + +import { CompatibilityTableBase } from './base'; +import { type ModifierDataSchema } from './schemas'; +import { modifiersCompatibilityTableData } from './compatibility-table-data'; +import { EMPTY, UNDERSCORE } from '../utils/constants'; +import { type CompatibilityTable } from './types'; +import { deepFreeze } from '../utils/deep-freeze'; + +/** + * 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: string): string => { + if (name.startsWith(UNDERSCORE)) { + if (name.split(EMPTY).every((char) => char === UNDERSCORE)) { + // in compatibility tables, we just store '_', so we need to reduce the number of underscores to 1 + // before checking the existence of the noop modifier + return UNDERSCORE; + } + } + + return name; +}; + +/** + * Compatibility table for modifiers. + */ +class ModifiersCompatibilityTable extends CompatibilityTableBase { + /** + * Creates a new instance of the compatibility table for modifiers. + * + * @param data Compatibility table data. + */ + constructor(data: CompatibilityTable) { + super(data, noopModifierNameNormalizer); + } +} + +/** + * Deep freeze the compatibility table data to avoid accidental modifications. + */ +deepFreeze(modifiersCompatibilityTableData); + +/** + * Compatibility table instance for modifiers. + */ +export const modifiersCompatibilityTable = new ModifiersCompatibilityTable(modifiersCompatibilityTableData); diff --git a/packages/agtree/src/compatibility-tables/modifiers/README.md b/packages/agtree/src/compatibility-tables/modifiers/README.md index 6c2431c38..1584deb3a 100644 --- a/packages/agtree/src/compatibility-tables/modifiers/README.md +++ b/packages/agtree/src/compatibility-tables/modifiers/README.md @@ -10,26 +10,28 @@ Each file contains an object, where the key is the fields: -| Field | Description | Type | Default value [**] | -| --- | --- | --- | --- | -| `name` [*] | Name of the actual modifier. | `string` | | -| `aliases` | List of aliases for the modifier (if any). | `string[]\|null` | `null` (no aliases) | -| `description` | Short description of the actual modifier. If not specified or it's value is `null`, then the description is not available. | `string\|null` | `null` | -| `docs` | Link to the documentation. If not specified or it's value is `null`, then the documentation is not available. | `string\|null` | `null` | -| `version_added` | The version of the adblocker when the modifier was added. | `string\|null` | `null` | -| `version_removed` | The version of the adblocker when the modifier was removed. | `string\|null` | `null` | -| `deprecated` | Describes whether the modifier is deprecated; for *soon-to-be removed* features. | `boolean` | `false` | -| `deprecation_message` | Message that describes why the modifier is deprecated. If not specified or it's value is `null`, then the message is not available. It's value is omitted if the scriptlet is not marked as deprecated. | `string\|null` | `null` | -| `removed` | Describes whether the modifier is removed; for *already removed* features. | `boolean` | `false` | -| `removal_message` | Message that describes why the modifier is removed. If not specified or it's value is `null`, then the message is not available. It's value is omitted if the scriptlet is not marked as deprecated. | `string\|null` | `null` | -| `conflicts` | List of modifiers that are incompatible with the actual one. | `string[]\|null` | `null` (no conflicts) | -| `inverse_conflicts` | The actual modifier is incompatible with all other modifiers, except the ones listed in `conflicts`. | `boolean` | `false` | -| `assignable` | Describes whether the actual modifier supports value assignment. For example, `$domain` is assignable, so it can be used like this: `$domain=domain.com\|~subdomain.domain.com`, where `=` is the assignment operator and `domain.com\|~subdomain.domain.com` is the value. | `boolean` | `false` | -| `negatable` | Describes whether the actual modifier can be negated. For example, `$third-party` is negatable, so it can be used like this: `$~third-party`. | `boolean` | `true` | -| `block_only` | The actual modifier can only be used in blocking rules, it cannot be used in exceptions. If it's value is `true`, then the modifier can be used only in blocking rules. `exception_only` and `block_only` cannot be used together (they are mutually exclusive). | `boolean` | `false` | -| `exception_only` | The actual modifier can only be used in exceptions, it cannot be used in blocking rules. If it's value is `true`, then the modifier can be used only in exceptions. `exception_only` and `block_only` cannot be used together (they are mutually exclusive). | `boolean` | `false` | -| `value_optional` | Describes whether the *assignable* modifier value is required. For example, `$cookie` is assignable but it can be used without a value in exception rules: `@@\|\|example.com^$cookie`. If `false`, the `value_format` is required, e.g. the value of `$app` should always be specified. | `boolean` | `false` | -| `value_format` | Describes the format of the value. See [Value format](#value-format) for more details. | `string\|null` | `null` | + +| Field | Description | Type | Default value [**] | +| --------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------- | --------------------- | +| `name` [*] | Name of the actual modifier. | `string` | | +| `aliases` | List of aliases for the modifier (if any). | `string[]\|null` | `null` (no aliases) | +| `description` | Short description of the actual modifier. If not specified or it's value is `null`, then the description is not available. | `string\|null` | `null` | +| `docs` | Link to the documentation. If not specified or it's value is `null`, then the documentation is not available. | `string\|null` | `null` | +| `version_added` | The version of the adblocker when the modifier was added. | `string\|null` | `null` | +| `version_removed` | The version of the adblocker when the modifier was removed. | `string\|null` | `null` | +| `deprecated` | Describes whether the modifier is deprecated; for *soon-to-be removed* features. | `boolean` | `false` | +| `deprecation_message` | Message that describes why the modifier is deprecated. If not specified or it's value is `null`, then the message is not available. It's value is omitted if the modifier is not marked as deprecated. | `string\|null` | `null` | +| `removed` | Describes whether the modifier is removed; for *already removed* features. | `boolean` | `false` | +| `removal_message` | Message that describes why the modifier is removed. If not specified or it's value is `null`, then the message is not available. It's value is omitted if the modifier is not marked as deprecated. | `string\|null` | `null` | +| `conflicts` | List of modifiers that are incompatible with the actual one. | `string[]\|null` | `null` (no conflicts) | +| `inverse_conflicts` | The actual modifier is incompatible with all other modifiers, except the ones listed in `conflicts`. | `boolean` | `false` | +| `assignable` | Describes whether the actual modifier supports value assignment. For example, `$domain` is assignable, so it can be used like this: `$domain=domain.com\|~subdomain.domain.com`, where `=` is the assignment operator and `domain.com\|~subdomain.domain.com` is the value. | `boolean` | `false` | +| `negatable` | Describes whether the actual modifier can be negated. For example, `$third-party` is negatable, so it can be used like this: `$~third-party`. | `boolean` | `true` | +| `block_only` | The actual modifier can only be used in blocking rules, it cannot be used in exceptions. If it's value is `true`, then the modifier can be used only in blocking rules. `exception_only` and `block_only` cannot be used together (they are mutually exclusive). | `boolean` | `false` | +| `exception_only` | The actual modifier can only be used in exceptions, it cannot be used in blocking rules. If it's value is `true`, then the modifier can be used only in exceptions. `exception_only` and `block_only` cannot be used together (they are mutually exclusive). | `boolean` | `false` | +| `value_optional` | Describes whether the *assignable* modifier value is required. For example, `$cookie` is assignable but it can be used without a value in exception rules: `@@\|\|example.com^$cookie`. If `false`, the `value_format` is required, e.g. the value of `$app` should always be specified. | `boolean` | `false` | +| `value_format` | Describes the format of the value. See [Value format](#value-format) for more details. | `string\|null` | `null` | + ### Value format diff --git a/packages/agtree/src/compatibility-tables/modifiers/all.yml b/packages/agtree/src/compatibility-tables/modifiers/all.yml index 12ea0bc6f..d81345cea 100644 --- a/packages/agtree/src/compatibility-tables/modifiers/all.yml +++ b/packages/agtree/src/compatibility-tables/modifiers/all.yml @@ -1,31 +1,10 @@ -adg_os_any: +adg_any|~adg_cb_android: name: all 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 negatable: false block_only: true -adg_ext_any: - name: all - 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 - negatable: false - block_only: true - -adg_cb_ios: - name: all - description: The `$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 - negatable: false - block_only: true - -adg_cb_safari: - name: all - description: The `$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 - negatable: false - block_only: true - ubo_ext_any: name: all description: |- diff --git a/packages/agtree/src/compatibility-tables/modifiers/badfilter.yml b/packages/agtree/src/compatibility-tables/modifiers/badfilter.yml index 4a83e9387..eb8c57199 100644 --- a/packages/agtree/src/compatibility-tables/modifiers/badfilter.yml +++ b/packages/agtree/src/compatibility-tables/modifiers/badfilter.yml @@ -1,28 +1,4 @@ -adg_os_any: - name: badfilter - description: |- - The rules with the `$badfilter` modifier disable other basic rules to which they refer. It means that - the 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 - negatable: false - -adg_ext_any: - name: badfilter - description: |- - The rules with the `$badfilter` modifier disable other basic rules to which they refer. It means that - the 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 - negatable: false - -adg_cb_ios: - name: badfilter - description: |- - The rules with the `$badfilter` modifier disable other basic rules to which they refer. It means that - the 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 - negatable: false - -adg_cb_safari: +adg_any|~adg_cb_android: name: badfilter description: |- The rules with the `$badfilter` modifier disable other basic rules to which they refer. It means that diff --git a/packages/agtree/src/compatibility-tables/modifiers/cookie.yml b/packages/agtree/src/compatibility-tables/modifiers/cookie.yml index 970823bc0..d8145e799 100644 --- a/packages/agtree/src/compatibility-tables/modifiers/cookie.yml +++ b/packages/agtree/src/compatibility-tables/modifiers/cookie.yml @@ -1,15 +1,4 @@ -adg_os_any: - name: cookie - description: |- - The `$cookie` modifier completely changes rule behavior. - Instead 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 - assignable: true - negatable: false - value_optional: true - value_format: ^([^;=\s]*?)((?:;(maxAge=\d+;?)?|(sameSite=(lax|none|strict);?)?){1,3})(? 'my-resource' + */ +const abpRedirectNameNormalizer = (name: string): string => { + if (name.startsWith(ABP_RESOURCE_PREFIX)) { + return name.slice(ABP_RESOURCE_PREFIX_LENGTH); + } + + return name; +}; + +/** + * Compatibility table for redirects. + */ +class RedirectsCompatibilityTable extends CompatibilityTableBase { + /** + * Creates a new instance of the compatibility table for redirects. + * + * @param data Compatibility table data. + */ + constructor(data: CompatibilityTable) { + super(data, abpRedirectNameNormalizer); + } +} + +/** + * Deep freeze the compatibility table data to avoid accidental modifications. + */ +deepFreeze(redirectsCompatibilityTableData); + +/** + * Compatibility table instance for redirects. + */ +export const redirectsCompatibilityTable = new RedirectsCompatibilityTable(redirectsCompatibilityTableData); diff --git a/packages/agtree/src/compatibility-tables/redirects/1x1-transparent.gif.yml b/packages/agtree/src/compatibility-tables/redirects/1x1-transparent.gif.yml index 84867ed0b..18faaba90 100644 --- a/packages/agtree/src/compatibility-tables/redirects/1x1-transparent.gif.yml +++ b/packages/agtree/src/compatibility-tables/redirects/1x1-transparent.gif.yml @@ -1,5 +1,5 @@ # Note: content blocking products do not support redirects -adg_any_not_cb: +adg_os_any|adg_ext_any: name: 1x1-transparent.gif aliases: - 1x1.gif diff --git a/packages/agtree/src/compatibility-tables/redirects/2x2-transparent.png.yml b/packages/agtree/src/compatibility-tables/redirects/2x2-transparent.png.yml index db2d8fc74..ac6b5f06e 100644 --- a/packages/agtree/src/compatibility-tables/redirects/2x2-transparent.png.yml +++ b/packages/agtree/src/compatibility-tables/redirects/2x2-transparent.png.yml @@ -1,5 +1,5 @@ # Note: content blocking products do not support redirects -adg_any_not_cb: +adg_os_any|adg_ext_any: name: 2x2-transparent.png aliases: - 2x2.png diff --git a/packages/agtree/src/compatibility-tables/redirects/32x32-transparent.png.yml b/packages/agtree/src/compatibility-tables/redirects/32x32-transparent.png.yml index 7741dfed2..5e9154ee8 100644 --- a/packages/agtree/src/compatibility-tables/redirects/32x32-transparent.png.yml +++ b/packages/agtree/src/compatibility-tables/redirects/32x32-transparent.png.yml @@ -1,5 +1,5 @@ # Note: content blocking products do not support redirects -adg_any_not_cb: +adg_os_any|adg_ext_any: name: 32x32-transparent.png aliases: - 32x32.png diff --git a/packages/agtree/src/compatibility-tables/redirects/3x2-transparent.png.yml b/packages/agtree/src/compatibility-tables/redirects/3x2-transparent.png.yml index dccb801b6..9d88668ce 100644 --- a/packages/agtree/src/compatibility-tables/redirects/3x2-transparent.png.yml +++ b/packages/agtree/src/compatibility-tables/redirects/3x2-transparent.png.yml @@ -1,5 +1,5 @@ # Note: content blocking products do not support redirects -adg_any_not_cb: +adg_os_any|adg_ext_any: name: 3x2-transparent.png aliases: - 3x2.png diff --git a/packages/agtree/src/compatibility-tables/redirects/README.md b/packages/agtree/src/compatibility-tables/redirects/README.md index 1fdc2a0b6..fb9bc74a0 100644 --- a/packages/agtree/src/compatibility-tables/redirects/README.md +++ b/packages/agtree/src/compatibility-tables/redirects/README.md @@ -10,17 +10,21 @@ Each file contains an object, where the key is the with the following fields: -| Field | Description | Type | Default value | -| --- | --- | --- | --- | -| `name`\* | Name of the actual redirect. | `string` | | -| `aliases` | List of aliases for the redirect (if any). | `string[]` | `[]` (no aliases) | -| `is_blocking` | Whether the redirect is blocking. | `boolean` | `false` | -| `description` | Short description of the actual redirect. If not specified or it's value is `null`, then the description is not available. | `string\|null` | `null` | -| `docs` | Link to the documentation. If not specified or it's value is `null`, then the documentation is not available. | `string\|null` | `null` | -| `version_added` | The version of the adblocker in which the redirect was added. For AdGuard resources, the version of the library is specified. | `string\|null` | `null` | -| `version_removed` | The version of the adblocker when the redirect was removed. | `string\|null` | `null` | -| `deprecated` | Describes whether the redirect is deprecated. | `boolean` | `false` | -| `deprecation_message` | Message that describes why the redirect is deprecated. If not specified or it's value is `null`, then the message is not available. It's value is omitted if the redirect is not marked as deprecated. | `string\|null` | `null` | + +| Field | Description | Type | Default value | +| --------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ---------------- | ------------------- | +| `name`\* | Name of the actual redirect. | `string` | | +| `aliases` | List of aliases for the redirect (if any). | `string[]\|null` | `null` (no aliases) | +| `description` | Short description of the actual redirect. If not specified or it's value is `null`, then the description is not available. | `string\|null` | `null` | +| `docs` | Link to the documentation. If not specified or it's value is `null`, then the documentation is not available. | `string\|null` | `null` | +| `version_added` | The version of the adblocker in which the redirect was added. For AdGuard resources, the version of the library is specified. | `string\|null` | `null` | +| `version_removed` | The version of the adblocker when the redirect was removed. | `string\|null` | `null` | +| `deprecated` | Describes whether the redirect is deprecated. | `boolean` | `false` | +| `deprecation_message` | Message that describes why the redirect is deprecated. If not specified or it's value is `null`, then the message is not available. It's value is omitted if the redirect is not marked as deprecated. | `string\|null` | `null` | +| `removed` | Describes whether the redirect is removed; for *already removed* features. | `boolean` | `false` | +| `removal_message` | Message that describes why the redirect is removed. If not specified or it's value is `null`, then the message is not available. It's value is omitted if the redirect is not marked as deprecated. | `string\|null` | `null` | +| `is_blocking` | Whether the redirect is blocking. | `boolean` | `false` | + \*: The field is required. diff --git a/packages/agtree/src/compatibility-tables/redirects/amazon-apstag.yml b/packages/agtree/src/compatibility-tables/redirects/amazon-apstag.yml index 734d27f33..43cc2e629 100644 --- a/packages/agtree/src/compatibility-tables/redirects/amazon-apstag.yml +++ b/packages/agtree/src/compatibility-tables/redirects/amazon-apstag.yml @@ -1,5 +1,5 @@ # Note: content blocking products do not support redirects -adg_any_not_cb: +adg_os_any|adg_ext_any: name: amazon-apstag aliases: - ubo-amazon_apstag.js diff --git a/packages/agtree/src/compatibility-tables/redirects/ati-smarttag.yml b/packages/agtree/src/compatibility-tables/redirects/ati-smarttag.yml index 48a19d340..a880c2c8e 100644 --- a/packages/agtree/src/compatibility-tables/redirects/ati-smarttag.yml +++ b/packages/agtree/src/compatibility-tables/redirects/ati-smarttag.yml @@ -1,4 +1,4 @@ # TODO: add description and documentation reference # Note: content blocking products do not support redirects -adg_any_not_cb: +adg_os_any|adg_ext_any: name: ati-smarttag diff --git a/packages/agtree/src/compatibility-tables/redirects/click2load.html.yml b/packages/agtree/src/compatibility-tables/redirects/click2load.html.yml index 6075bf75d..ab7ff3194 100644 --- a/packages/agtree/src/compatibility-tables/redirects/click2load.html.yml +++ b/packages/agtree/src/compatibility-tables/redirects/click2load.html.yml @@ -1,6 +1,6 @@ # TODO: add documentation reference # Note: content blocking products do not support redirects -adg_any_not_cb: +adg_os_any|adg_ext_any: name: click2load.html aliases: - click2load.html diff --git a/packages/agtree/src/compatibility-tables/redirects/didomi-loader.yml b/packages/agtree/src/compatibility-tables/redirects/didomi-loader.yml index b7ecc2550..793f2d6c0 100644 --- a/packages/agtree/src/compatibility-tables/redirects/didomi-loader.yml +++ b/packages/agtree/src/compatibility-tables/redirects/didomi-loader.yml @@ -1,5 +1,5 @@ # TODO: add documentation reference # Note: content blocking products do not support redirects -adg_any_not_cb: +adg_os_any|adg_ext_any: name: didomi-loader description: Mocks Didomi's CMP loader script. diff --git a/packages/agtree/src/compatibility-tables/redirects/empty.yml b/packages/agtree/src/compatibility-tables/redirects/empty.yml index 0f6778fbc..0df445f8b 100644 --- a/packages/agtree/src/compatibility-tables/redirects/empty.yml +++ b/packages/agtree/src/compatibility-tables/redirects/empty.yml @@ -1,5 +1,5 @@ # TODO: add documentation reference -adg_any_not_cb: +adg_os_any|adg_ext_any: name: empty description: Redirects to an empty file. diff --git a/packages/agtree/src/compatibility-tables/redirects/fingerprintjs2.yml b/packages/agtree/src/compatibility-tables/redirects/fingerprintjs2.yml index c8c6e9d84..24df3833d 100644 --- a/packages/agtree/src/compatibility-tables/redirects/fingerprintjs2.yml +++ b/packages/agtree/src/compatibility-tables/redirects/fingerprintjs2.yml @@ -1,6 +1,6 @@ # TODO: add documentation reference # Note: content blocking products do not support redirects -adg_any_not_cb: +adg_os_any|adg_ext_any: name: fingerprintjs2 aliases: - fingerprint2.js diff --git a/packages/agtree/src/compatibility-tables/redirects/fingerprintjs3.yml b/packages/agtree/src/compatibility-tables/redirects/fingerprintjs3.yml index 50f9ba76d..46d4d193b 100644 --- a/packages/agtree/src/compatibility-tables/redirects/fingerprintjs3.yml +++ b/packages/agtree/src/compatibility-tables/redirects/fingerprintjs3.yml @@ -1,6 +1,6 @@ # TODO: add documentation reference # Note: content blocking products do not support redirects -adg_any_not_cb: +adg_os_any|adg_ext_any: name: fingerprintjs3 aliases: - fingerprint3.js diff --git a/packages/agtree/src/compatibility-tables/redirects/gemius.yml b/packages/agtree/src/compatibility-tables/redirects/gemius.yml index f96b0e9b3..931880526 100644 --- a/packages/agtree/src/compatibility-tables/redirects/gemius.yml +++ b/packages/agtree/src/compatibility-tables/redirects/gemius.yml @@ -1,5 +1,5 @@ # TODO: add documentation reference # Note: content blocking products do not support redirects -adg_any_not_cb: +adg_os_any|adg_ext_any: name: gemius description: Mocks Gemius Analytics. diff --git a/packages/agtree/src/compatibility-tables/redirects/google-analytics-ga.yml b/packages/agtree/src/compatibility-tables/redirects/google-analytics-ga.yml index e6419ab46..0d123cc14 100644 --- a/packages/agtree/src/compatibility-tables/redirects/google-analytics-ga.yml +++ b/packages/agtree/src/compatibility-tables/redirects/google-analytics-ga.yml @@ -1,6 +1,6 @@ # TODO: add documentation reference # Note: content blocking products do not support redirects -adg_any_not_cb: +adg_os_any|adg_ext_any: name: google-analytics-ga aliases: - ubo-google-analytics_ga.js diff --git a/packages/agtree/src/compatibility-tables/redirects/google-analytics.yml b/packages/agtree/src/compatibility-tables/redirects/google-analytics.yml index 3c39183dd..8247a5d42 100644 --- a/packages/agtree/src/compatibility-tables/redirects/google-analytics.yml +++ b/packages/agtree/src/compatibility-tables/redirects/google-analytics.yml @@ -1,6 +1,6 @@ # TODO: add documentation reference # Note: content blocking products do not support redirects -adg_any_not_cb: +adg_os_any|adg_ext_any: name: google-analytics aliases: - ubo-google-analytics_analytics.js diff --git a/packages/agtree/src/compatibility-tables/redirects/google-ima3.yml b/packages/agtree/src/compatibility-tables/redirects/google-ima3.yml index 3df1f8bea..890246e1e 100644 --- a/packages/agtree/src/compatibility-tables/redirects/google-ima3.yml +++ b/packages/agtree/src/compatibility-tables/redirects/google-ima3.yml @@ -1,6 +1,6 @@ # TODO: add documentation reference # Note: content blocking products do not support redirects -adg_any_not_cb: +adg_os_any|adg_ext_any: name: google-ima3 aliases: - ubo-google-ima.js diff --git a/packages/agtree/src/compatibility-tables/redirects/googlesyndication-adsbygoogle.yml b/packages/agtree/src/compatibility-tables/redirects/googlesyndication-adsbygoogle.yml index 1e1947802..abca8e085 100644 --- a/packages/agtree/src/compatibility-tables/redirects/googlesyndication-adsbygoogle.yml +++ b/packages/agtree/src/compatibility-tables/redirects/googlesyndication-adsbygoogle.yml @@ -1,6 +1,6 @@ # TODO: add documentation reference # Note: content blocking products do not support redirects -adg_any_not_cb: +adg_os_any|adg_ext_any: name: googlesyndication-adsbygoogle aliases: - ubo-googlesyndication_adsbygoogle.js diff --git a/packages/agtree/src/compatibility-tables/redirects/googletagservices-gpt.yml b/packages/agtree/src/compatibility-tables/redirects/googletagservices-gpt.yml index 426e396e9..fc76491c7 100644 --- a/packages/agtree/src/compatibility-tables/redirects/googletagservices-gpt.yml +++ b/packages/agtree/src/compatibility-tables/redirects/googletagservices-gpt.yml @@ -1,6 +1,6 @@ # TODO: add documentation reference # Note: content blocking products do not support redirects -adg_any_not_cb: +adg_os_any|adg_ext_any: name: googletagservices-gpt aliases: - ubo-googletagservices_gpt.js diff --git a/packages/agtree/src/compatibility-tables/redirects/matomo.yml b/packages/agtree/src/compatibility-tables/redirects/matomo.yml index 59f2cd93b..b4e57a3dd 100644 --- a/packages/agtree/src/compatibility-tables/redirects/matomo.yml +++ b/packages/agtree/src/compatibility-tables/redirects/matomo.yml @@ -1,5 +1,5 @@ # TODO: add documentation reference # Note: content blocking products do not support redirects -adg_any_not_cb: +adg_os_any|adg_ext_any: name: matomo description: Mocks the piwik.js file of Matomo (formerly Piwik). diff --git a/packages/agtree/src/compatibility-tables/redirects/metrika-yandex-tag.yml b/packages/agtree/src/compatibility-tables/redirects/metrika-yandex-tag.yml index 2f6e09e65..e6cbe3971 100644 --- a/packages/agtree/src/compatibility-tables/redirects/metrika-yandex-tag.yml +++ b/packages/agtree/src/compatibility-tables/redirects/metrika-yandex-tag.yml @@ -1,5 +1,5 @@ # TODO: add documentation reference # Note: content blocking products do not support redirects -adg_any_not_cb: +adg_os_any|adg_ext_any: name: metrika-yandex-tag description: Mocks Yandex Metrika API. diff --git a/packages/agtree/src/compatibility-tables/redirects/metrika-yandex-watch.yml b/packages/agtree/src/compatibility-tables/redirects/metrika-yandex-watch.yml index 1ff1a5802..054fee0a9 100644 --- a/packages/agtree/src/compatibility-tables/redirects/metrika-yandex-watch.yml +++ b/packages/agtree/src/compatibility-tables/redirects/metrika-yandex-watch.yml @@ -1,5 +1,5 @@ # TODO: add documentation reference # Note: content blocking products do not support redirects -adg_any_not_cb: +adg_os_any|adg_ext_any: name: metrika-yandex-watch description: Mocks the old Yandex Metrika API. diff --git a/packages/agtree/src/compatibility-tables/redirects/naver-wcslog.yml b/packages/agtree/src/compatibility-tables/redirects/naver-wcslog.yml index d4cc42fd3..85b3fe7f0 100644 --- a/packages/agtree/src/compatibility-tables/redirects/naver-wcslog.yml +++ b/packages/agtree/src/compatibility-tables/redirects/naver-wcslog.yml @@ -1,5 +1,5 @@ # TODO: add documentation reference # Note: content blocking products do not support redirects -adg_any_not_cb: +adg_os_any|adg_ext_any: name: naver-wcslog description: Mocks wcslog.js of Naver Analytics. diff --git a/packages/agtree/src/compatibility-tables/redirects/no-protected-audience.yml b/packages/agtree/src/compatibility-tables/redirects/no-protected-audience.yml index 35399c1a2..fc712dadf 100644 --- a/packages/agtree/src/compatibility-tables/redirects/no-protected-audience.yml +++ b/packages/agtree/src/compatibility-tables/redirects/no-protected-audience.yml @@ -1,5 +1,5 @@ # TODO: add documentation reference # Note: content blocking products do not support redirects -adg_any_not_cb: +adg_os_any|adg_ext_any: name: no-protected-audience description: Prevents using the Protected Audience API. diff --git a/packages/agtree/src/compatibility-tables/redirects/no-topics.yml b/packages/agtree/src/compatibility-tables/redirects/no-topics.yml index 1b202f0f0..5c5ef8a93 100644 --- a/packages/agtree/src/compatibility-tables/redirects/no-topics.yml +++ b/packages/agtree/src/compatibility-tables/redirects/no-topics.yml @@ -1,5 +1,5 @@ # TODO: add documentation reference # Note: content blocking products do not support redirects -adg_any_not_cb: +adg_os_any|adg_ext_any: name: no-topics description: Prevents using the Topics API. diff --git a/packages/agtree/src/compatibility-tables/redirects/noeval.yml b/packages/agtree/src/compatibility-tables/redirects/noeval.yml index ee28eb41d..358c16696 100644 --- a/packages/agtree/src/compatibility-tables/redirects/noeval.yml +++ b/packages/agtree/src/compatibility-tables/redirects/noeval.yml @@ -1,6 +1,6 @@ # TODO: add documentation reference # Note: content blocking products do not support redirects -adg_any_not_cb: +adg_os_any|adg_ext_any: name: noeval aliases: - noeval.js diff --git a/packages/agtree/src/compatibility-tables/redirects/noopcss.yml b/packages/agtree/src/compatibility-tables/redirects/noopcss.yml index c430e8d38..50929c306 100644 --- a/packages/agtree/src/compatibility-tables/redirects/noopcss.yml +++ b/packages/agtree/src/compatibility-tables/redirects/noopcss.yml @@ -1,6 +1,6 @@ # TODO: add documentation reference # Note: content blocking products do not support redirects -adg_any_not_cb: +adg_os_any|adg_ext_any: name: noopcss aliases: - noop.css diff --git a/packages/agtree/src/compatibility-tables/redirects/noopframe.yml b/packages/agtree/src/compatibility-tables/redirects/noopframe.yml index 2677c147f..098dff09f 100644 --- a/packages/agtree/src/compatibility-tables/redirects/noopframe.yml +++ b/packages/agtree/src/compatibility-tables/redirects/noopframe.yml @@ -1,6 +1,6 @@ # TODO: add documentation reference # Note: content blocking products do not support redirects -adg_any_not_cb: +adg_os_any|adg_ext_any: name: noopframe aliases: - noop.html diff --git a/packages/agtree/src/compatibility-tables/redirects/noopjs.yml b/packages/agtree/src/compatibility-tables/redirects/noopjs.yml index c366d2b41..6c7337a1b 100644 --- a/packages/agtree/src/compatibility-tables/redirects/noopjs.yml +++ b/packages/agtree/src/compatibility-tables/redirects/noopjs.yml @@ -1,6 +1,6 @@ # TODO: add documentation reference # Note: content blocking products do not support redirects -adg_any_not_cb: +adg_os_any|adg_ext_any: name: noopjs aliases: - noop.js diff --git a/packages/agtree/src/compatibility-tables/redirects/noopjson.yml b/packages/agtree/src/compatibility-tables/redirects/noopjson.yml index 2d86a17e6..c8724a269 100644 --- a/packages/agtree/src/compatibility-tables/redirects/noopjson.yml +++ b/packages/agtree/src/compatibility-tables/redirects/noopjson.yml @@ -1,6 +1,6 @@ # TODO: add documentation reference # Note: content blocking products do not support redirects -adg_any_not_cb: +adg_os_any|adg_ext_any: name: noopjson aliases: - noop.json diff --git a/packages/agtree/src/compatibility-tables/redirects/noopmp3-0.1s.yml b/packages/agtree/src/compatibility-tables/redirects/noopmp3-0.1s.yml index 77496e57f..c512eefcf 100644 --- a/packages/agtree/src/compatibility-tables/redirects/noopmp3-0.1s.yml +++ b/packages/agtree/src/compatibility-tables/redirects/noopmp3-0.1s.yml @@ -1,6 +1,6 @@ # TODO: add documentation reference # Note: content blocking products do not support redirects -adg_any_not_cb: +adg_os_any|adg_ext_any: name: noopmp3-0.1s aliases: - noop-0.1s.mp3 diff --git a/packages/agtree/src/compatibility-tables/redirects/noopmp4-1s.yml b/packages/agtree/src/compatibility-tables/redirects/noopmp4-1s.yml index 8d55a88e3..6c53f47e5 100644 --- a/packages/agtree/src/compatibility-tables/redirects/noopmp4-1s.yml +++ b/packages/agtree/src/compatibility-tables/redirects/noopmp4-1s.yml @@ -1,6 +1,6 @@ # TODO: add documentation reference # Note: content blocking products do not support redirects -adg_any_not_cb: +adg_os_any|adg_ext_any: name: noopmp4-1s aliases: - noop-1s.mp4 diff --git a/packages/agtree/src/compatibility-tables/redirects/nooptext.yml b/packages/agtree/src/compatibility-tables/redirects/nooptext.yml index 8dbcf706a..6b1b390b0 100644 --- a/packages/agtree/src/compatibility-tables/redirects/nooptext.yml +++ b/packages/agtree/src/compatibility-tables/redirects/nooptext.yml @@ -1,6 +1,6 @@ # TODO: add documentation reference # Note: content blocking products do not support redirects -adg_any_not_cb: +adg_os_any|adg_ext_any: name: nooptext aliases: - noop.txt diff --git a/packages/agtree/src/compatibility-tables/redirects/noopvast-2.0.yml b/packages/agtree/src/compatibility-tables/redirects/noopvast-2.0.yml index 64bae65ec..e6dacb007 100644 --- a/packages/agtree/src/compatibility-tables/redirects/noopvast-2.0.yml +++ b/packages/agtree/src/compatibility-tables/redirects/noopvast-2.0.yml @@ -1,5 +1,5 @@ # TODO: add documentation reference # Note: content blocking products do not support redirects -adg_any_not_cb: +adg_os_any|adg_ext_any: name: noopvast-2.0 description: Redirects to an empty VAST 2.0 XML file. diff --git a/packages/agtree/src/compatibility-tables/redirects/noopvast-3.0.yml b/packages/agtree/src/compatibility-tables/redirects/noopvast-3.0.yml index 07a7b2eff..aa7f43bcc 100644 --- a/packages/agtree/src/compatibility-tables/redirects/noopvast-3.0.yml +++ b/packages/agtree/src/compatibility-tables/redirects/noopvast-3.0.yml @@ -1,5 +1,5 @@ # TODO: add documentation reference # Note: content blocking products do not support redirects -adg_any_not_cb: +adg_os_any|adg_ext_any: name: noopvast-3.0 description: Redirects to an empty VAST 3.0 XML file. diff --git a/packages/agtree/src/compatibility-tables/redirects/noopvast-4.0.yml b/packages/agtree/src/compatibility-tables/redirects/noopvast-4.0.yml index 63e35bfe8..bca2b9c7f 100644 --- a/packages/agtree/src/compatibility-tables/redirects/noopvast-4.0.yml +++ b/packages/agtree/src/compatibility-tables/redirects/noopvast-4.0.yml @@ -1,5 +1,5 @@ # TODO: add documentation reference # Note: content blocking products do not support redirects -adg_any_not_cb: +adg_os_any|adg_ext_any: name: noopvast-4.0 description: Redirects to an empty VAST 4.0 XML file. diff --git a/packages/agtree/src/compatibility-tables/redirects/noopvmap-1.0.yml b/packages/agtree/src/compatibility-tables/redirects/noopvmap-1.0.yml index 3aea69191..74b90fe95 100644 --- a/packages/agtree/src/compatibility-tables/redirects/noopvmap-1.0.yml +++ b/packages/agtree/src/compatibility-tables/redirects/noopvmap-1.0.yml @@ -1,6 +1,6 @@ # TODO: add documentation reference # Note: content blocking products do not support redirects -adg_any_not_cb: +adg_os_any|adg_ext_any: name: noopvmap-1.0 aliases: - noop-vmap1.0.xml diff --git a/packages/agtree/src/compatibility-tables/redirects/nowebrtc.yml b/packages/agtree/src/compatibility-tables/redirects/nowebrtc.yml index 07e1e4279..da38e3f36 100644 --- a/packages/agtree/src/compatibility-tables/redirects/nowebrtc.yml +++ b/packages/agtree/src/compatibility-tables/redirects/nowebrtc.yml @@ -1,6 +1,6 @@ # TODO: add documentation reference # Note: content blocking products do not support redirects -adg_any_not_cb: +adg_os_any|adg_ext_any: name: nowebrtc aliases: - nowebrtc.js diff --git a/packages/agtree/src/compatibility-tables/redirects/pardot-1.0.yml b/packages/agtree/src/compatibility-tables/redirects/pardot-1.0.yml index 0e1dac12f..acf7c50fc 100644 --- a/packages/agtree/src/compatibility-tables/redirects/pardot-1.0.yml +++ b/packages/agtree/src/compatibility-tables/redirects/pardot-1.0.yml @@ -1,5 +1,5 @@ # TODO: add documentation reference # Note: content blocking products do not support redirects -adg_any_not_cb: +adg_os_any|adg_ext_any: name: pardot-1.0 description: Mocks the pd.js file of Salesforce. diff --git a/packages/agtree/src/compatibility-tables/redirects/prebid-ads.yml b/packages/agtree/src/compatibility-tables/redirects/prebid-ads.yml index 17f250093..7fe64f657 100644 --- a/packages/agtree/src/compatibility-tables/redirects/prebid-ads.yml +++ b/packages/agtree/src/compatibility-tables/redirects/prebid-ads.yml @@ -1,6 +1,6 @@ # TODO: add documentation reference # Note: content blocking products do not support redirects -adg_any_not_cb: +adg_os_any|adg_ext_any: name: prebid-ads aliases: - prebid-ads.js diff --git a/packages/agtree/src/compatibility-tables/redirects/prebid.yml b/packages/agtree/src/compatibility-tables/redirects/prebid.yml index 2aed919ff..2a0325b3e 100644 --- a/packages/agtree/src/compatibility-tables/redirects/prebid.yml +++ b/packages/agtree/src/compatibility-tables/redirects/prebid.yml @@ -1,5 +1,5 @@ # TODO: add documentation reference # Note: content blocking products do not support redirects -adg_any_not_cb: +adg_os_any|adg_ext_any: name: prebid description: Mocks the prebid.js header bidding suit. diff --git a/packages/agtree/src/compatibility-tables/redirects/prevent-bab.yml b/packages/agtree/src/compatibility-tables/redirects/prevent-bab.yml index cce7ce6a9..6b7ecc65c 100644 --- a/packages/agtree/src/compatibility-tables/redirects/prevent-bab.yml +++ b/packages/agtree/src/compatibility-tables/redirects/prevent-bab.yml @@ -1,6 +1,6 @@ # TODO: add documentation reference # Note: content blocking products do not support redirects -adg_any_not_cb: +adg_os_any|adg_ext_any: name: prevent-bab aliases: - nobab.js diff --git a/packages/agtree/src/compatibility-tables/redirects/prevent-bab2.yml b/packages/agtree/src/compatibility-tables/redirects/prevent-bab2.yml index aa18ac212..ba6196a98 100644 --- a/packages/agtree/src/compatibility-tables/redirects/prevent-bab2.yml +++ b/packages/agtree/src/compatibility-tables/redirects/prevent-bab2.yml @@ -1,6 +1,6 @@ # TODO: add documentation reference # Note: content blocking products do not support redirects -adg_any_not_cb: +adg_os_any|adg_ext_any: name: prevent-bab2 aliases: - nobab2.js diff --git a/packages/agtree/src/compatibility-tables/redirects/prevent-fab-3.2.0.yml b/packages/agtree/src/compatibility-tables/redirects/prevent-fab-3.2.0.yml index ed64c5dc4..07abb6e75 100644 --- a/packages/agtree/src/compatibility-tables/redirects/prevent-fab-3.2.0.yml +++ b/packages/agtree/src/compatibility-tables/redirects/prevent-fab-3.2.0.yml @@ -1,6 +1,6 @@ # TODO: add documentation reference # Note: content blocking products do not support redirects -adg_any_not_cb: +adg_os_any|adg_ext_any: name: prevent-fab-3.2.0 aliases: - nofab.js diff --git a/packages/agtree/src/compatibility-tables/redirects/prevent-popads-net.yml b/packages/agtree/src/compatibility-tables/redirects/prevent-popads-net.yml index b2c8ccf03..529d6e41a 100644 --- a/packages/agtree/src/compatibility-tables/redirects/prevent-popads-net.yml +++ b/packages/agtree/src/compatibility-tables/redirects/prevent-popads-net.yml @@ -1,6 +1,6 @@ # TODO: add documentation reference # Note: content blocking products do not support redirects -adg_any_not_cb: +adg_os_any|adg_ext_any: name: prevent-popads-net aliases: - popads.js diff --git a/packages/agtree/src/compatibility-tables/redirects/scorecardresearch-beacon.yml b/packages/agtree/src/compatibility-tables/redirects/scorecardresearch-beacon.yml index 9ab8bedb4..a190f3b2b 100644 --- a/packages/agtree/src/compatibility-tables/redirects/scorecardresearch-beacon.yml +++ b/packages/agtree/src/compatibility-tables/redirects/scorecardresearch-beacon.yml @@ -1,6 +1,6 @@ # TODO: add documentation reference # Note: content blocking products do not support redirects -adg_any_not_cb: +adg_os_any|adg_ext_any: name: scorecardresearch-beacon aliases: - scorecardresearch_beacon.js diff --git a/packages/agtree/src/compatibility-tables/redirects/set-popads-dummy.yml b/packages/agtree/src/compatibility-tables/redirects/set-popads-dummy.yml index 91e3351d7..0597089b8 100644 --- a/packages/agtree/src/compatibility-tables/redirects/set-popads-dummy.yml +++ b/packages/agtree/src/compatibility-tables/redirects/set-popads-dummy.yml @@ -1,6 +1,6 @@ # TODO: add documentation reference # Note: content blocking products do not support redirects -adg_any_not_cb: +adg_os_any|adg_ext_any: name: set-popads-dummy aliases: - popads-dummy.js diff --git a/packages/agtree/src/compatibility-tables/schemas/base.ts b/packages/agtree/src/compatibility-tables/schemas/base.ts new file mode 100644 index 000000000..9f464dbc7 --- /dev/null +++ b/packages/agtree/src/compatibility-tables/schemas/base.ts @@ -0,0 +1,153 @@ +/** + * @file Base compatibility data schema, which is commonly used in compatibility tables. + */ + +import zod from 'zod'; + +import { platformSchema } from './platform'; +import { zodToCamelCase } from '../utils/zod-camelcase'; + +/** + * Zod schema for boolean values. Accepts both boolean and string values. + */ +export const booleanSchema = zod.union([ + zod.string().transform((val) => val.trim().toLowerCase() === 'true'), + zod.boolean(), +]); + +/** + * Zod schema for non-empty string values. + */ +export const nonEmptyStringSchema = zod + .string() + .transform((val) => val.trim()) + .pipe(zod.string().min(1)); + +/** + * Zod schema for base compatibility data. + * Here we use snake_case properties because the compatibility data is stored in YAML files. + */ +export const baseCompatibilityDataSchema = zod.object({ + /** + * Name of the actual entity. + */ + name: nonEmptyStringSchema, + + /** + * List of aliases for the entity (if any). + */ + aliases: zod.array(nonEmptyStringSchema).nullable().default(null), + + /** + * Short description of the actual entity. + * If not specified or it's value is `null`, then the description is not available. + */ + description: nonEmptyStringSchema.nullable().default(null), + + /** + * Link to the documentation. If not specified or it's value is `null`, then the documentation is not available. + */ + docs: nonEmptyStringSchema.nullable().default(null), + + /** + * The version of the adblocker in which the entity was added. + * For AdGuard resources, the version of the library is specified. + */ + version_added: nonEmptyStringSchema.nullable().default(null), + + /** + * The version of the adblocker when the entity was removed. + */ + version_removed: nonEmptyStringSchema.nullable().default(null), + + /** + * Describes whether the entity is deprecated. + */ + deprecated: booleanSchema.default(false), + + /** + * Message that describes why the entity is deprecated. + * If not specified or it's value is `null`, then the message is not available. + * It's value is omitted if the entity is not marked as deprecated. + */ + deprecation_message: nonEmptyStringSchema.nullable().default(null), + + /** + * Describes whether the entity is removed; for *already removed* features. + */ + removed: booleanSchema.default(false), + + /** + * Message that describes why the entity is removed. + * If not specified or it's value is `null`, then the message is not available. + * It's value is omitted if the entity is not marked as deprecated. + */ + removal_message: nonEmptyStringSchema.nullable().default(null), +}); + +/** + * Zod schema for base compatibility data with camelCase properties. + */ +export const baseCompatibilityDataSchemaCamelCase = zodToCamelCase(baseCompatibilityDataSchema); + +/** + * Type of the base compatibility data schema. + */ +export type BaseCompatibilityDataSchema = zod.infer; + +/** + * Refinement logic for base compatibility data. + * + * @param data Base compatibility data. + * @param ctx Refinement context. + */ +export const baseRefineLogic = (data: zod.infer, ctx: zod.RefinementCtx) => { + if (data.deprecated && !data.deprecation_message) { + ctx.addIssue({ + code: zod.ZodIssueCode.custom, + message: 'deprecation_message is required for deprecated modifiers', + }); + } + + if (!data.deprecated && data.deprecation_message) { + ctx.addIssue({ + code: zod.ZodIssueCode.custom, + message: 'deprecation_message is only allowed for deprecated modifiers', + }); + } + + if (data.aliases && data.aliases.length !== new Set(data.aliases).size) { + ctx.addIssue({ + code: zod.ZodIssueCode.custom, + message: 'Aliases must be unique', + }); + } +}; + +/** + * Creates a base file schema. + * + * @param dataSchema Data schema. + * + * @returns Base file schema. + */ +export const baseFileSchema = (dataSchema: zod.ZodType) => { + return zod.record(zod.any(), zod.any()).transform((val) => { + const result = val; + + // Note: js-yaml will leave `define` key in the object, but we don't need it, + // and since we're using a strict schema, we need to remove it. + if ('define' in result) { + delete result.define; + } + + return result; + }).pipe( + zod.record(platformSchema, dataSchema), + ); +}; + +/** + * Type of the base file schema. + */ +export type BaseFileSchema = zod.infer>>; diff --git a/packages/agtree/src/compatibility-tables/schemas/index.ts b/packages/agtree/src/compatibility-tables/schemas/index.ts new file mode 100644 index 000000000..483d731e5 --- /dev/null +++ b/packages/agtree/src/compatibility-tables/schemas/index.ts @@ -0,0 +1,9 @@ +/** + * @file Entry point for compatibility tables schemas. + */ + +export * from './base'; +export * from './modifier'; +export * from './redirect'; +export * from './scriptlet'; +export * from './platform'; diff --git a/packages/agtree/src/compatibility-tables/schemas/modifier.ts b/packages/agtree/src/compatibility-tables/schemas/modifier.ts new file mode 100644 index 000000000..22d23a12b --- /dev/null +++ b/packages/agtree/src/compatibility-tables/schemas/modifier.ts @@ -0,0 +1,123 @@ +/** + * @file Schema for modifier data. + */ + +import zod from 'zod'; +import XRegExp from 'xregexp'; + +import { zodToCamelCase } from '../utils/zod-camelcase'; +import { + baseCompatibilityDataSchema, + baseRefineLogic, + booleanSchema, + nonEmptyStringSchema, +} from './base'; +import { getErrorMessage } from '../../utils/error'; + +/** + * Known validators that don't need to be validated as regex. + */ +const KNOWN_VALIDATORS = new Set([ + 'domain', + 'pipe_separated_domains', + 'regexp', + 'url', +]); + +/** + * Zod schema for modifier data. + */ +export const modifierDataSchema = zodToCamelCase(baseCompatibilityDataSchema.extend({ + /** + * List of modifiers that are incompatible with the actual one. + */ + conflicts: zod.array(nonEmptyStringSchema).nullable().default(null), + + /** + * The actual modifier is incompatible with all other modifiers, except the ones listed in `conflicts`. + */ + inverse_conflicts: booleanSchema.default(false), + + /** + * Describes whether the actual modifier supports value assignment. For example, `$domain` is assignable, + * so it can be used like this: `$domain=domain.com\|~subdomain.domain.com`, where `=` is the assignment operator + * and `domain.com\|~subdomain.domain.com` is the value. + */ + assignable: booleanSchema.default(false), + + /** + * Describes whether the actual modifier can be negated. For example, `$third-party` is negatable, + * so it can be used like this: `$~third-party`. + */ + negatable: booleanSchema.default(true), + + /** + * The actual modifier can only be used in blocking rules, it cannot be used in exceptions. + * If it's value is `true`, then the modifier can be used only in blocking rules. + * `exception_only` and `block_only` cannot be used together (they are mutually exclusive). + */ + block_only: booleanSchema.default(false), + + /** + * The actual modifier can only be used in exceptions, it cannot be used in blocking rules. + * If it's value is `true`, then the modifier can be used only in exceptions. + * `exception_only` and `block_only` cannot be used together (they are mutually exclusive). + */ + exception_only: booleanSchema.default(false), + + /** + * Describes whether the *assignable* modifier value is required. + * For example, `$cookie` is assignable but it can be used without a value in exception rules: + * `@@\|\|example.com^$cookie`. + * If `false`, the `value_format` is required, e.g. the value of `$app` should always be specified + */ + value_optional: booleanSchema.default(false), + + /** + * Describes the format of the value for the *assignable* modifier. + * Its value can be a regex pattern or a known validator name (e.g. `domain`, `pipe_separated_domains`, etc.). + */ + value_format: nonEmptyStringSchema.nullable().default(null), +}).superRefine((data, ctx) => { + // TODO: find something better, for now we can't add refine logic to the base schema: + // https://github.com/colinhacks/zod/issues/454#issuecomment-848370721 + baseRefineLogic(data, ctx); + + if (data.block_only && data.exception_only) { + ctx.addIssue({ + code: zod.ZodIssueCode.custom, + message: 'block_only and exception_only are mutually exclusive', + }); + } + + if (data.assignable && !data.value_format) { + ctx.addIssue({ + code: zod.ZodIssueCode.custom, + message: 'value_format is required for assignable modifiers', + }); + } + + if (data.value_format) { + const valueFormat = data.value_format.trim(); + + // if it is a known validator, we don't need to validate it further + if (KNOWN_VALIDATORS.has(valueFormat)) { + return; + } + + // otherwise, we need to validate it as a regex + try { + XRegExp(valueFormat); + } catch (error: unknown) { + ctx.addIssue({ + code: zod.ZodIssueCode.custom, + message: getErrorMessage(error), + }); + } + } +})); + +/** + * Type of the modifier data schema. + */ +export type ModifierDataSchema = zod.infer; diff --git a/packages/agtree/src/compatibility-tables/schemas/platform.ts b/packages/agtree/src/compatibility-tables/schemas/platform.ts new file mode 100644 index 000000000..92e03e109 --- /dev/null +++ b/packages/agtree/src/compatibility-tables/schemas/platform.ts @@ -0,0 +1,73 @@ +/* eslint-disable no-bitwise */ +/** + * @file Platform schema. + */ + +import zod from 'zod'; + +import { GENERIC_PLATFORM_MAP, SPECIFIC_PLATFORM_MAP } from '../utils/platform-helpers'; +import { isUndefined } from '../../utils/common'; + +/** + * Platform separator, e.g. 'adg_os_any|adg_safari_any' means any AdGuard OS platform and + * any AdGuard Safari content blocker platform. + */ +const PLATFORM_SEPARATOR = '|'; + +/** + * Platform negation character, e.g. 'adg_any|~adg_safari_any' means any AdGuard product except + * Safari content blockers. + */ +const PLATFORM_NEGATION = '~'; + +/** + * Parses a raw platform string into a platform bitmask. + * + * @param rawPlatforms Raw platform string, e.g. 'adg_safari_any|adg_os_any'. + * + * @returns Platform bitmask. + */ +export const parseRawPlatforms = (rawPlatforms: string): number => { + // e.g. 'adg_safari_any|adg_os_any' + const rawPlatformList = rawPlatforms + .split(PLATFORM_SEPARATOR) + .map((rawPlatform) => rawPlatform.trim()); + + let result = 0; + + for (let rawPlatform of rawPlatformList) { + // negation, e.g. 'adg_any|~adg_safari_any' means any AdGuard product except Safari content blockers + let negated = false; + + if (rawPlatform.startsWith(PLATFORM_NEGATION)) { + negated = true; + rawPlatform = rawPlatform.slice(1).trim(); + } + + const platform = SPECIFIC_PLATFORM_MAP.get(rawPlatform) ?? GENERIC_PLATFORM_MAP.get(rawPlatform); + + if (isUndefined(platform)) { + throw new Error(`Unknown platform: ${rawPlatform}`); + } + + if (negated) { + result &= ~platform; + } else { + result |= platform; + } + } + + if (result === 0) { + throw new Error('No platforms specified'); + } + + return result; +}; + +/** + * Platform schema. + */ +export const platformSchema = zod + .string() + .min(1) + .transform((value) => parseRawPlatforms(value)); diff --git a/packages/agtree/src/compatibility-tables/schemas/redirect.ts b/packages/agtree/src/compatibility-tables/schemas/redirect.ts new file mode 100644 index 000000000..de191d019 --- /dev/null +++ b/packages/agtree/src/compatibility-tables/schemas/redirect.ts @@ -0,0 +1,23 @@ +/** + * @file Schema for redirect data. + */ + +import type zod from 'zod'; + +import { zodToCamelCase } from '../utils/zod-camelcase'; +import { baseCompatibilityDataSchema, baseRefineLogic, booleanSchema } from './base'; + +/** + * Zod schema for redirect data. + */ +export const redirectDataSchema = zodToCamelCase(baseCompatibilityDataSchema.extend({ + /** + * Whether the redirect is blocking. + */ + is_blocking: booleanSchema.default(false), +}).superRefine(baseRefineLogic)); + +/** + * Type of the redirect data schema. + */ +export type RedirectDataSchema = zod.infer; diff --git a/packages/agtree/src/compatibility-tables/schemas/scriptlet.ts b/packages/agtree/src/compatibility-tables/schemas/scriptlet.ts new file mode 100644 index 000000000..0ccfc89d8 --- /dev/null +++ b/packages/agtree/src/compatibility-tables/schemas/scriptlet.ts @@ -0,0 +1,98 @@ +/** + * @file Schema for scriptlet data. + */ + +import zod from 'zod'; + +import { zodToCamelCase } from '../utils/zod-camelcase'; +import { + baseCompatibilityDataSchema, + baseRefineLogic, + booleanSchema, + nonEmptyStringSchema, +} from './base'; + +/** + * Zod schema for scriptlet parameter data. + */ +const scriptletParameterSchema = zod.object({ + /** + * Name of the actual parameter. + */ + name: nonEmptyStringSchema, + + /** + * Describes whether the parameter is required. Empty parameters are not allowed. + */ + required: booleanSchema, + + /** + * Short description of the parameter. + * If not specified or it's value is `null`,then the description is not available. + */ + description: nonEmptyStringSchema.nullable().default(null), + + /** + * Regular expression that matches the value of the parameter. + * If it's value is `null`, then the parameter value is not checked. + */ + pattern: nonEmptyStringSchema.nullable().default(null), + + /** + * Default value of the parameter (if any). + */ + default: nonEmptyStringSchema.nullable().default(null), + + /** + * Describes whether the parameter is used only for debugging purposes. + */ + debug: booleanSchema.default(false), +}); + +/** + * Zod schema for scriptlet parameters. + */ +const scriptletParametersSchema = zod.array(scriptletParameterSchema); + +/** + * Zod schema for scriptlet data. + */ +export const scriptletDataSchema = zodToCamelCase( + baseCompatibilityDataSchema.extend({ + /** + * List of parameters that the scriptlet accepts. + * **Every** parameter should be listed here, because we check that the scriptlet is used correctly + * (e.g. that the number of parameters is correct). + */ + parameters: scriptletParametersSchema.optional(), + }).superRefine((data, ctx) => { + // TODO: find something better, for now we can't add refine logic to the base schema: + // https://github.com/colinhacks/zod/issues/454#issuecomment-848370721 + baseRefineLogic(data, ctx); + + // we don't allow required parameters after optional ones + if (!data.parameters) { + return; + } + + let optionalFound = false; + + for (const parameter of data.parameters) { + if (optionalFound && parameter.required) { + ctx.addIssue({ + code: zod.ZodIssueCode.custom, + message: 'Required parameters must be before optional ones', + }); + } + + if (!parameter.required) { + optionalFound = true; + } + } + }), +); + +/** + * Type of the scriptlet data schema. + */ +export type ScriptletDataSchema = zod.infer; diff --git a/packages/agtree/src/compatibility-tables/scriptlets.ts b/packages/agtree/src/compatibility-tables/scriptlets.ts new file mode 100644 index 000000000..3e248bb63 --- /dev/null +++ b/packages/agtree/src/compatibility-tables/scriptlets.ts @@ -0,0 +1,23 @@ +/** + * @file Compatibility tables for scriptlets. + */ + +import { CompatibilityTableBase } from './base'; +import { type ScriptletDataSchema } from './schemas'; +import { scriptletsCompatibilityTableData } from './compatibility-table-data'; +import { deepFreeze } from '../utils/deep-freeze'; + +/** + * Compatibility table for scriptlets. + */ +class ScriptletsCompatibilityTable extends CompatibilityTableBase { } + +/** + * Deep freeze the compatibility table data to avoid accidental modifications. + */ +deepFreeze(scriptletsCompatibilityTableData); + +/** + * Compatibility table instance for scriptlets. + */ +export const scriptletsCompatibilityTable = new ScriptletsCompatibilityTable(scriptletsCompatibilityTableData); diff --git a/packages/agtree/src/compatibility-tables/scriptlets/README.md b/packages/agtree/src/compatibility-tables/scriptlets/README.md index fd3c78466..0e91d8393 100644 --- a/packages/agtree/src/compatibility-tables/scriptlets/README.md +++ b/packages/agtree/src/compatibility-tables/scriptlets/README.md @@ -11,24 +11,26 @@ and the value is the object with the following fields: -| Field | Description | Type | Default value | -| -------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------- | -------------------- | -| `name`\* | Name of the actual scriptlet. | `string` | | -| `aliases` | List of aliases for the scriptlet (if any). | `string[]` | `[]` (no aliases) | -| `description` | Short description of the actual scriptlet. If not specified or it's value is `null`, then the description is not available. | `string\|null` | `null` | -| `docs` | Link to the documentation. If not specified or it's value is `null`, then the documentation is not available. | `string\|null` | `null` | -| `version_added` | The version of the adblocker in which the scriptlet was added. For AdGuard resources, the version of the library is specified. | `string\|null` | `null` | -| `version_removed` | The version of the adblocker when the scriptlet was removed. | `string\|null` | `null` | -| `debug` | Describes whether the scriptlet is used only for debugging purposes. | `boolean` | `false` | -| `deprecated` | Describes whether the scriptlet is deprecated. | `boolean` | `false` | -| `deprecation_message` | Message that describes why the scriptlet is deprecated. If not specified or it's value is `null`, then the message is not available. It's value is omitted if the scriptlet is not marked as deprecated. | `string\|null` | `null` | -| `parameters` | List of parameters that the scriptlet accepts. **Every** parameter should be listed here, because we check that the scriptlet is used correctly (e.g. that the number of parameters is correct). | `Parameter[]` | `[]` (no parameters) | -| `parameters[].name`\* | Name of the actual parameter. | `string` | | -| `parameters[].required`\* | Describes whether the parameter is required. Empty parameters are not allowed. | `boolean` | | -| `parameters[].description` | Short description of the parameter. If not specified or it's value is `null`, then the description is not available. | `string\|null` | `null` | -| `parameters[].pattern` | Regular expression that matches the value of the parameter. If it's value is `null`, then the parameter value is not checked. | `string\|null` | `null` | -| `parameters[].default` | Default value of the parameter (if any) | `string\|null` | `null` | -| `parameters[].debug` | Describes whether the parameter is used only for debugging purposes. | `boolean` | `false` | +| Field | Description | Type | Default value | +| -------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------- | -------------------- | +| `name`\* | Name of the actual scriptlet. | `string` | | +| `aliases` | List of aliases for the scriptlet (if any). | `string[]\|null` | `null` (no aliases) | +| `description` | Short description of the actual scriptlet. If not specified or it's value is `null`, then the description is not available. | `string\|null` | `null` | +| `docs` | Link to the documentation. If not specified or it's value is `null`, then the documentation is not available. | `string\|null` | `null` | +| `version_added` | The version of the adblocker in which the scriptlet was added. For AdGuard resources, the version of the library is specified. | `string\|null` | `null` | +| `version_removed` | The version of the adblocker when the scriptlet was removed. | `string\|null` | `null` | +| `debug` | Describes whether the scriptlet is used only for debugging purposes. | `boolean` | `false` | +| `deprecated` | Describes whether the scriptlet is deprecated. | `boolean` | `false` | +| `deprecation_message` | Message that describes why the scriptlet is deprecated. If not specified or it's value is `null`, then the message is not available. It's value is omitted if the scriptlet is not marked as deprecated. | `string\|null` | `null` | +| `removed` | Describes whether the scriptlet is removed; for *already removed* features. | `boolean` | `false` | +| `removal_message` | Message that describes why the scriptlet is removed. If not specified or it's value is `null`, then the message is not available. It's value is omitted if the scriptlet is not marked as deprecated. | `string\|null` | `null` | +| `parameters` | List of parameters that the scriptlet accepts. **Every** parameter should be listed here, because we check that the scriptlet is used correctly (e.g. that the number of parameters is correct). | `Parameter[]` | `[]` (no parameters) | +| `parameters[].name`\* | Name of the actual parameter. | `string` | | +| `parameters[].required`\* | Describes whether the parameter is required. Empty parameters are not allowed. | `boolean` | | +| `parameters[].description` | Short description of the parameter. If not specified or it's value is `null`, then the description is not available. | `string\|null` | `null` | +| `parameters[].pattern` | Regular expression that matches the value of the parameter. If it's value is `null`, then the parameter value is not checked. | `string\|null` | `null` | +| `parameters[].default` | Default value of the parameter (if any) | `string\|null` | `null` | +| `parameters[].debug` | Describes whether the parameter is used only for debugging purposes. | `boolean` | `false` | diff --git a/packages/agtree/src/compatibility-tables/scriptlets/abort-current-inline-script.yml b/packages/agtree/src/compatibility-tables/scriptlets/abort-current-inline-script.yml index 8e4ebe54f..7930c4754 100644 --- a/packages/agtree/src/compatibility-tables/scriptlets/abort-current-inline-script.yml +++ b/packages/agtree/src/compatibility-tables/scriptlets/abort-current-inline-script.yml @@ -1,6 +1,6 @@ # TODO: add scriptlet and param descriptions, documentation references, and versions # Note: content blocking products do not support scriptlets -adg_any_not_cb: +adg_os_any|adg_ext_any: name: abort-current-inline-script version_added: 1.0.4 aliases: diff --git a/packages/agtree/src/compatibility-tables/scriptlets/abort-on-property-read.yml b/packages/agtree/src/compatibility-tables/scriptlets/abort-on-property-read.yml index d4f4ae7bf..a9479b4be 100644 --- a/packages/agtree/src/compatibility-tables/scriptlets/abort-on-property-read.yml +++ b/packages/agtree/src/compatibility-tables/scriptlets/abort-on-property-read.yml @@ -1,6 +1,6 @@ # TODO: add scriptlet and param descriptions, documentation references, and versions # Note: content blocking products do not support scriptlets -adg_any_not_cb: +adg_os_any|adg_ext_any: name: abort-on-property-read version_added: 1.0.4 aliases: diff --git a/packages/agtree/src/compatibility-tables/scriptlets/abort-on-property-write.yml b/packages/agtree/src/compatibility-tables/scriptlets/abort-on-property-write.yml index df7ff0873..845e5c57e 100644 --- a/packages/agtree/src/compatibility-tables/scriptlets/abort-on-property-write.yml +++ b/packages/agtree/src/compatibility-tables/scriptlets/abort-on-property-write.yml @@ -1,6 +1,6 @@ # TODO: add scriptlet and param descriptions, documentation references, and versions # Note: content blocking products do not support scriptlets -adg_any_not_cb: +adg_os_any|adg_ext_any: name: abort-on-property-write version_added: 1.0.4 aliases: diff --git a/packages/agtree/src/compatibility-tables/scriptlets/abort-on-stack-trace.yml b/packages/agtree/src/compatibility-tables/scriptlets/abort-on-stack-trace.yml index 3dce8ea8a..b43f04f13 100644 --- a/packages/agtree/src/compatibility-tables/scriptlets/abort-on-stack-trace.yml +++ b/packages/agtree/src/compatibility-tables/scriptlets/abort-on-stack-trace.yml @@ -1,6 +1,6 @@ # TODO: add scriptlet and param descriptions, documentation references, and versions # Note: content blocking products do not support scriptlets -adg_any_not_cb: +adg_os_any|adg_ext_any: name: abort-on-stack-trace version_added: 1.5.0 aliases: diff --git a/packages/agtree/src/compatibility-tables/scriptlets/adjust-setInterval.yml b/packages/agtree/src/compatibility-tables/scriptlets/adjust-setInterval.yml index db1a94504..83eb709a6 100644 --- a/packages/agtree/src/compatibility-tables/scriptlets/adjust-setInterval.yml +++ b/packages/agtree/src/compatibility-tables/scriptlets/adjust-setInterval.yml @@ -1,6 +1,6 @@ # TODO: add scriptlet and param descriptions, documentation references, and versions # Note: content blocking products do not support scriptlets -adg_any_not_cb: +adg_os_any|adg_ext_any: name: adjust-setInterval version_added: 1.0.4 aliases: diff --git a/packages/agtree/src/compatibility-tables/scriptlets/adjust-setTimeout.yml b/packages/agtree/src/compatibility-tables/scriptlets/adjust-setTimeout.yml index 07d84bbfb..a5d60e748 100644 --- a/packages/agtree/src/compatibility-tables/scriptlets/adjust-setTimeout.yml +++ b/packages/agtree/src/compatibility-tables/scriptlets/adjust-setTimeout.yml @@ -1,6 +1,6 @@ # TODO: add scriptlet and param descriptions, documentation references, and versions # Note: content blocking products do not support scriptlets -adg_any_not_cb: +adg_os_any|adg_ext_any: name: adjust-setTimeout version_added: 1.0.4 aliases: diff --git a/packages/agtree/src/compatibility-tables/scriptlets/amazon-apstag.yml b/packages/agtree/src/compatibility-tables/scriptlets/amazon-apstag.yml index ceea6889a..f1af7267c 100644 --- a/packages/agtree/src/compatibility-tables/scriptlets/amazon-apstag.yml +++ b/packages/agtree/src/compatibility-tables/scriptlets/amazon-apstag.yml @@ -1,6 +1,6 @@ # TODO: add scriptlet and param descriptions, documentation references, and versions # Note: content blocking products do not support scriptlets -adg_any_not_cb: +adg_os_any|adg_ext_any: name: amazon-apstag version_added: 1.10.25 aliases: diff --git a/packages/agtree/src/compatibility-tables/scriptlets/call-nothrow.yml b/packages/agtree/src/compatibility-tables/scriptlets/call-nothrow.yml index 19cda63d4..04cca544e 100644 --- a/packages/agtree/src/compatibility-tables/scriptlets/call-nothrow.yml +++ b/packages/agtree/src/compatibility-tables/scriptlets/call-nothrow.yml @@ -1,6 +1,6 @@ # TODO: add scriptlet and param descriptions, documentation references, and versions # Note: content blocking products do not support scriptlets -adg_any_not_cb: +adg_os_any|adg_ext_any: name: call-nothrow version_added: 1.10.1 aliases: diff --git a/packages/agtree/src/compatibility-tables/scriptlets/close-window.yml b/packages/agtree/src/compatibility-tables/scriptlets/close-window.yml index 841d38b63..ab4796bb9 100644 --- a/packages/agtree/src/compatibility-tables/scriptlets/close-window.yml +++ b/packages/agtree/src/compatibility-tables/scriptlets/close-window.yml @@ -1,6 +1,6 @@ # TODO: add scriptlet and param descriptions, documentation references, and versions # Note: content blocking products do not support scriptlets -adg_any_not_cb: +adg_os_any|adg_ext_any: name: close-window version_added: 1.5.0 aliases: diff --git a/packages/agtree/src/compatibility-tables/scriptlets/debug-current-inline-script.yml b/packages/agtree/src/compatibility-tables/scriptlets/debug-current-inline-script.yml index ab777522a..d8a012cd5 100644 --- a/packages/agtree/src/compatibility-tables/scriptlets/debug-current-inline-script.yml +++ b/packages/agtree/src/compatibility-tables/scriptlets/debug-current-inline-script.yml @@ -1,6 +1,6 @@ # TODO: add scriptlet and param descriptions, documentation references, and versions # Note: content blocking products do not support scriptlets -adg_any_not_cb: +adg_os_any|adg_ext_any: name: debug-current-inline-script version_added: 1.0.4 docs: https://github.com/AdguardTeam/Scriptlets/blob/master/wiki/about-scriptlets.md#debug-current-inline-script diff --git a/packages/agtree/src/compatibility-tables/scriptlets/debug-on-property-read.yml b/packages/agtree/src/compatibility-tables/scriptlets/debug-on-property-read.yml index 06beee99b..1f4c4ed23 100644 --- a/packages/agtree/src/compatibility-tables/scriptlets/debug-on-property-read.yml +++ b/packages/agtree/src/compatibility-tables/scriptlets/debug-on-property-read.yml @@ -1,6 +1,6 @@ # TODO: add scriptlet and param descriptions, documentation references, and versions # Note: content blocking products do not support scriptlets -adg_any_not_cb: +adg_os_any|adg_ext_any: name: debug-on-property-read version_added: 1.0.4 docs: https://github.com/AdguardTeam/Scriptlets/blob/master/wiki/about-scriptlets.md#debug-on-property-read diff --git a/packages/agtree/src/compatibility-tables/scriptlets/debug-on-property-write.yml b/packages/agtree/src/compatibility-tables/scriptlets/debug-on-property-write.yml index ac1ecfdab..a43f6becb 100644 --- a/packages/agtree/src/compatibility-tables/scriptlets/debug-on-property-write.yml +++ b/packages/agtree/src/compatibility-tables/scriptlets/debug-on-property-write.yml @@ -1,6 +1,6 @@ # TODO: add scriptlet and param descriptions, documentation references, and versions # Note: content blocking products do not support scriptlets -adg_any_not_cb: +adg_os_any|adg_ext_any: name: debug-on-property-write version_added: 1.0.4 docs: https://github.com/AdguardTeam/Scriptlets/blob/master/wiki/about-scriptlets.md#debug-on-property-write diff --git a/packages/agtree/src/compatibility-tables/scriptlets/didomi-loader.yml b/packages/agtree/src/compatibility-tables/scriptlets/didomi-loader.yml index 06dccff30..34d5533f4 100644 --- a/packages/agtree/src/compatibility-tables/scriptlets/didomi-loader.yml +++ b/packages/agtree/src/compatibility-tables/scriptlets/didomi-loader.yml @@ -1,6 +1,6 @@ # TODO: add scriptlet and param descriptions, documentation references, and versions # Note: content blocking products do not support scriptlets -adg_any_not_cb: +adg_os_any|adg_ext_any: name: didomi-loader version_added: 1.10.25 docs: https://github.com/AdguardTeam/Scriptlets/blob/master/wiki/about-scriptlets.md#didomi-loader diff --git a/packages/agtree/src/compatibility-tables/scriptlets/dir-string.yml b/packages/agtree/src/compatibility-tables/scriptlets/dir-string.yml index 49dbf415d..905cdbb00 100644 --- a/packages/agtree/src/compatibility-tables/scriptlets/dir-string.yml +++ b/packages/agtree/src/compatibility-tables/scriptlets/dir-string.yml @@ -1,6 +1,6 @@ # TODO: add scriptlet and param descriptions, documentation references, and versions # Note: content blocking products do not support scriptlets -adg_any_not_cb: +adg_os_any|adg_ext_any: name: dir-string version_added: 1.0.4 docs: https://github.com/AdguardTeam/Scriptlets/blob/master/wiki/about-scriptlets.md#dir-string diff --git a/packages/agtree/src/compatibility-tables/scriptlets/disable-newtab-links.yml b/packages/agtree/src/compatibility-tables/scriptlets/disable-newtab-links.yml index c4fe936da..5bd7ec089 100644 --- a/packages/agtree/src/compatibility-tables/scriptlets/disable-newtab-links.yml +++ b/packages/agtree/src/compatibility-tables/scriptlets/disable-newtab-links.yml @@ -1,6 +1,6 @@ # TODO: add scriptlet and param descriptions, documentation references, and versions # Note: content blocking products do not support scriptlets -adg_any_not_cb: +adg_os_any|adg_ext_any: name: disable-newtab-links version_added: 1.0.4 aliases: diff --git a/packages/agtree/src/compatibility-tables/scriptlets/evaldata-prune.yml b/packages/agtree/src/compatibility-tables/scriptlets/evaldata-prune.yml index fdade97ee..1a1f396c0 100644 --- a/packages/agtree/src/compatibility-tables/scriptlets/evaldata-prune.yml +++ b/packages/agtree/src/compatibility-tables/scriptlets/evaldata-prune.yml @@ -1,6 +1,6 @@ # TODO: add scriptlet and param descriptions, documentation references, and versions # Note: content blocking products do not support scriptlets -adg_any_not_cb: +adg_os_any|adg_ext_any: name: evaldata-prune version_added: 1.9.37 aliases: diff --git a/packages/agtree/src/compatibility-tables/scriptlets/fingerprintjs2.yml b/packages/agtree/src/compatibility-tables/scriptlets/fingerprintjs2.yml index 552469658..5b8f6fbb8 100644 --- a/packages/agtree/src/compatibility-tables/scriptlets/fingerprintjs2.yml +++ b/packages/agtree/src/compatibility-tables/scriptlets/fingerprintjs2.yml @@ -1,6 +1,6 @@ # TODO: add scriptlet and param descriptions, documentation references, and versions # Note: content blocking products do not support scriptlets -adg_any_not_cb: +adg_os_any|adg_ext_any: name: fingerprintjs2 version_added: 1.10.25 aliases: diff --git a/packages/agtree/src/compatibility-tables/scriptlets/fingerprintjs3.yml b/packages/agtree/src/compatibility-tables/scriptlets/fingerprintjs3.yml index c7c230fcb..dd823bbde 100644 --- a/packages/agtree/src/compatibility-tables/scriptlets/fingerprintjs3.yml +++ b/packages/agtree/src/compatibility-tables/scriptlets/fingerprintjs3.yml @@ -1,6 +1,6 @@ # TODO: add scriptlet and param descriptions, documentation references, and versions # Note: content blocking products do not support scriptlets -adg_any_not_cb: +adg_os_any|adg_ext_any: name: fingerprintjs3 version_added: 1.10.25 aliases: diff --git a/packages/agtree/src/compatibility-tables/scriptlets/gemius.yml b/packages/agtree/src/compatibility-tables/scriptlets/gemius.yml index 836c3a371..8d512cb52 100644 --- a/packages/agtree/src/compatibility-tables/scriptlets/gemius.yml +++ b/packages/agtree/src/compatibility-tables/scriptlets/gemius.yml @@ -1,6 +1,6 @@ # TODO: add scriptlet and param descriptions, documentation references, and versions # Note: content blocking products do not support scriptlets -adg_any_not_cb: +adg_os_any|adg_ext_any: name: gemius version_added: 1.10.25 docs: https://github.com/AdguardTeam/Scriptlets/blob/master/wiki/about-scriptlets.md#gemius diff --git a/packages/agtree/src/compatibility-tables/scriptlets/google-analytics-ga.yml b/packages/agtree/src/compatibility-tables/scriptlets/google-analytics-ga.yml index 264f0ab2a..0102f2463 100644 --- a/packages/agtree/src/compatibility-tables/scriptlets/google-analytics-ga.yml +++ b/packages/agtree/src/compatibility-tables/scriptlets/google-analytics-ga.yml @@ -1,6 +1,6 @@ # TODO: add scriptlet and param descriptions, documentation references, and versions # Note: content blocking products do not support scriptlets -adg_any_not_cb: +adg_os_any|adg_ext_any: name: google-analytics-ga version_added: 1.10.25 aliases: diff --git a/packages/agtree/src/compatibility-tables/scriptlets/google-analytics.yml b/packages/agtree/src/compatibility-tables/scriptlets/google-analytics.yml index fdd1be6d1..4015ad320 100644 --- a/packages/agtree/src/compatibility-tables/scriptlets/google-analytics.yml +++ b/packages/agtree/src/compatibility-tables/scriptlets/google-analytics.yml @@ -1,6 +1,6 @@ # TODO: add scriptlet and param descriptions, documentation references, and versions # Note: content blocking products do not support scriptlets -adg_any_not_cb: +adg_os_any|adg_ext_any: name: google-analytics version_added: 1.10.25 aliases: diff --git a/packages/agtree/src/compatibility-tables/scriptlets/google-ima3.yml b/packages/agtree/src/compatibility-tables/scriptlets/google-ima3.yml index 591e0b7ec..4eaf7ece4 100644 --- a/packages/agtree/src/compatibility-tables/scriptlets/google-ima3.yml +++ b/packages/agtree/src/compatibility-tables/scriptlets/google-ima3.yml @@ -1,6 +1,6 @@ # TODO: add scriptlet and param descriptions, documentation references, and versions # Note: content blocking products do not support scriptlets -adg_any_not_cb: +adg_os_any|adg_ext_any: name: google-ima3 version_added: 1.10.25 aliases: diff --git a/packages/agtree/src/compatibility-tables/scriptlets/googlesyndication-adsbygoogle.yml b/packages/agtree/src/compatibility-tables/scriptlets/googlesyndication-adsbygoogle.yml index 492829a58..3c275e11c 100644 --- a/packages/agtree/src/compatibility-tables/scriptlets/googlesyndication-adsbygoogle.yml +++ b/packages/agtree/src/compatibility-tables/scriptlets/googlesyndication-adsbygoogle.yml @@ -1,6 +1,6 @@ # TODO: add scriptlet and param descriptions, documentation references, and versions # Note: content blocking products do not support scriptlets -adg_any_not_cb: +adg_os_any|adg_ext_any: name: googlesyndication-adsbygoogle version_added: 1.10.25 aliases: diff --git a/packages/agtree/src/compatibility-tables/scriptlets/googletagservices-gpt.yml b/packages/agtree/src/compatibility-tables/scriptlets/googletagservices-gpt.yml index f6a1f1c95..b53309431 100644 --- a/packages/agtree/src/compatibility-tables/scriptlets/googletagservices-gpt.yml +++ b/packages/agtree/src/compatibility-tables/scriptlets/googletagservices-gpt.yml @@ -1,6 +1,6 @@ # TODO: add scriptlet and param descriptions, documentation references, and versions # Note: content blocking products do not support scriptlets -adg_any_not_cb: +adg_os_any|adg_ext_any: name: googletagservices-gpt version_added: 1.10.25 aliases: diff --git a/packages/agtree/src/compatibility-tables/scriptlets/hide-in-shadow-dom.yml b/packages/agtree/src/compatibility-tables/scriptlets/hide-in-shadow-dom.yml index abe327ff7..b62bf97d2 100644 --- a/packages/agtree/src/compatibility-tables/scriptlets/hide-in-shadow-dom.yml +++ b/packages/agtree/src/compatibility-tables/scriptlets/hide-in-shadow-dom.yml @@ -1,6 +1,6 @@ # TODO: add scriptlet and param descriptions, documentation references, and versions # Note: content blocking products do not support scriptlets -adg_any_not_cb: +adg_os_any|adg_ext_any: name: hide-in-shadow-dom version_added: 1.3.0 docs: https://github.com/AdguardTeam/Scriptlets/blob/master/wiki/about-scriptlets.md#hide-in-shadow-dom diff --git a/packages/agtree/src/compatibility-tables/scriptlets/href-sanitizer.yml b/packages/agtree/src/compatibility-tables/scriptlets/href-sanitizer.yml index 6f9c76ed8..119489faa 100644 --- a/packages/agtree/src/compatibility-tables/scriptlets/href-sanitizer.yml +++ b/packages/agtree/src/compatibility-tables/scriptlets/href-sanitizer.yml @@ -1,6 +1,6 @@ # TODO: add scriptlet and param descriptions, documentation references, and versions # Note: content blocking products do not support scriptlets -adg_any_not_cb: +adg_os_any|adg_ext_any: name: href-sanitizer version_added: 1.10.25 aliases: diff --git a/packages/agtree/src/compatibility-tables/scriptlets/inject-css-in-shadow-dom.yml b/packages/agtree/src/compatibility-tables/scriptlets/inject-css-in-shadow-dom.yml index 192f5b4e6..80087a5c2 100644 --- a/packages/agtree/src/compatibility-tables/scriptlets/inject-css-in-shadow-dom.yml +++ b/packages/agtree/src/compatibility-tables/scriptlets/inject-css-in-shadow-dom.yml @@ -1,6 +1,6 @@ # TODO: add scriptlet and param descriptions, documentation references, and versions # Note: content blocking products do not support scriptlets -adg_any_not_cb: +adg_os_any|adg_ext_any: name: inject-css-in-shadow-dom version_added: 1.8.2 docs: https://github.com/AdguardTeam/Scriptlets/blob/master/wiki/about-scriptlets.md#inject-css-in-shadow-dom diff --git a/packages/agtree/src/compatibility-tables/scriptlets/json-prune-fetch-response.yml b/packages/agtree/src/compatibility-tables/scriptlets/json-prune-fetch-response.yml index 6a72e50fe..95918b879 100644 --- a/packages/agtree/src/compatibility-tables/scriptlets/json-prune-fetch-response.yml +++ b/packages/agtree/src/compatibility-tables/scriptlets/json-prune-fetch-response.yml @@ -1,6 +1,6 @@ # TODO: add scriptlet and param descriptions, documentation references, and versions # Note: content blocking products do not support scriptlets -adg_any_not_cb: +adg_os_any|adg_ext_any: name: json-prune-fetch-response version_added: 1.10.25 aliases: diff --git a/packages/agtree/src/compatibility-tables/scriptlets/json-prune-xhr-response.yml b/packages/agtree/src/compatibility-tables/scriptlets/json-prune-xhr-response.yml index f3f0c8cca..877fa6ac4 100644 --- a/packages/agtree/src/compatibility-tables/scriptlets/json-prune-xhr-response.yml +++ b/packages/agtree/src/compatibility-tables/scriptlets/json-prune-xhr-response.yml @@ -1,6 +1,6 @@ # TODO: add scriptlet and param descriptions, documentation references, and versions # Note: content blocking products do not support scriptlets -adg_any_not_cb: +adg_os_any|adg_ext_any: name: json-prune-xhr-response version_added: 1.10.25 aliases: diff --git a/packages/agtree/src/compatibility-tables/scriptlets/json-prune.yml b/packages/agtree/src/compatibility-tables/scriptlets/json-prune.yml index e76708c8b..9bb2448d8 100644 --- a/packages/agtree/src/compatibility-tables/scriptlets/json-prune.yml +++ b/packages/agtree/src/compatibility-tables/scriptlets/json-prune.yml @@ -1,6 +1,6 @@ # TODO: add scriptlet and param descriptions, documentation references, and versions # Note: content blocking products do not support scriptlets -adg_any_not_cb: +adg_os_any|adg_ext_any: name: json-prune version_added: 1.1.0 aliases: diff --git a/packages/agtree/src/compatibility-tables/scriptlets/log-addEventListener.yml b/packages/agtree/src/compatibility-tables/scriptlets/log-addEventListener.yml index 841e5f64b..7125694e6 100644 --- a/packages/agtree/src/compatibility-tables/scriptlets/log-addEventListener.yml +++ b/packages/agtree/src/compatibility-tables/scriptlets/log-addEventListener.yml @@ -1,6 +1,6 @@ # TODO: add scriptlet and param descriptions, documentation references, and versions # Note: content blocking products do not support scriptlets -adg_any_not_cb: +adg_os_any|adg_ext_any: name: log-addEventListener version_added: 1.0.4 aliases: diff --git a/packages/agtree/src/compatibility-tables/scriptlets/log-eval.yml b/packages/agtree/src/compatibility-tables/scriptlets/log-eval.yml index 513afe952..798a5d5db 100644 --- a/packages/agtree/src/compatibility-tables/scriptlets/log-eval.yml +++ b/packages/agtree/src/compatibility-tables/scriptlets/log-eval.yml @@ -1,6 +1,6 @@ # TODO: add scriptlet and param descriptions, documentation references, and versions # Note: content blocking products do not support scriptlets -adg_any_not_cb: +adg_os_any|adg_ext_any: name: log-eval version_added: 1.0.4 docs: https://github.com/AdguardTeam/Scriptlets/blob/master/wiki/about-scriptlets.md#log-eval diff --git a/packages/agtree/src/compatibility-tables/scriptlets/log-on-stack-trace.yml b/packages/agtree/src/compatibility-tables/scriptlets/log-on-stack-trace.yml index dc8cd2a6d..5006665c4 100644 --- a/packages/agtree/src/compatibility-tables/scriptlets/log-on-stack-trace.yml +++ b/packages/agtree/src/compatibility-tables/scriptlets/log-on-stack-trace.yml @@ -1,6 +1,6 @@ # TODO: add scriptlet and param descriptions, documentation references, and versions # Note: content blocking products do not support scriptlets -adg_any_not_cb: +adg_os_any|adg_ext_any: name: log-on-stack-trace version_added: 1.5.0 docs: https://github.com/AdguardTeam/Scriptlets/blob/master/wiki/about-scriptlets.md#log-on-stack-trace diff --git a/packages/agtree/src/compatibility-tables/scriptlets/log.yml b/packages/agtree/src/compatibility-tables/scriptlets/log.yml index 18c4914c2..84f1ae669 100644 --- a/packages/agtree/src/compatibility-tables/scriptlets/log.yml +++ b/packages/agtree/src/compatibility-tables/scriptlets/log.yml @@ -1,6 +1,6 @@ # TODO: add scriptlet and param descriptions, documentation references, and versions # Note: content blocking products do not support scriptlets -adg_any_not_cb: +adg_os_any|adg_ext_any: name: log version_added: 1.0.4 aliases: diff --git a/packages/agtree/src/compatibility-tables/scriptlets/m3u-prune.yml b/packages/agtree/src/compatibility-tables/scriptlets/m3u-prune.yml index e86bce127..47c067e5a 100644 --- a/packages/agtree/src/compatibility-tables/scriptlets/m3u-prune.yml +++ b/packages/agtree/src/compatibility-tables/scriptlets/m3u-prune.yml @@ -1,6 +1,6 @@ # TODO: add scriptlet and param descriptions, documentation references, and versions # Note: content blocking products do not support scriptlets -adg_any_not_cb: +adg_os_any|adg_ext_any: name: m3u-prune version_added: 1.9.1 aliases: diff --git a/packages/agtree/src/compatibility-tables/scriptlets/matomo.yml b/packages/agtree/src/compatibility-tables/scriptlets/matomo.yml index c95981555..911522107 100644 --- a/packages/agtree/src/compatibility-tables/scriptlets/matomo.yml +++ b/packages/agtree/src/compatibility-tables/scriptlets/matomo.yml @@ -1,6 +1,6 @@ # TODO: add scriptlet and param descriptions, documentation references, and versions # Note: content blocking products do not support scriptlets -adg_any_not_cb: +adg_os_any|adg_ext_any: name: matomo version_added: 1.10.25 docs: https://github.com/AdguardTeam/Scriptlets/blob/master/wiki/about-scriptlets.md#matomo diff --git a/packages/agtree/src/compatibility-tables/scriptlets/metrika-yandex-tag.yml b/packages/agtree/src/compatibility-tables/scriptlets/metrika-yandex-tag.yml index 3b01c6f44..2d60b7fd1 100644 --- a/packages/agtree/src/compatibility-tables/scriptlets/metrika-yandex-tag.yml +++ b/packages/agtree/src/compatibility-tables/scriptlets/metrika-yandex-tag.yml @@ -1,6 +1,6 @@ # TODO: add scriptlet and param descriptions, documentation references, and versions # Note: content blocking products do not support scriptlets -adg_any_not_cb: +adg_os_any|adg_ext_any: name: metrika-yandex-tag version_added: 1.10.25 docs: https://github.com/AdguardTeam/Scriptlets/blob/master/wiki/about-scriptlets.md#metrika-yandex-tag diff --git a/packages/agtree/src/compatibility-tables/scriptlets/metrika-yandex-watch.yml b/packages/agtree/src/compatibility-tables/scriptlets/metrika-yandex-watch.yml index 163ba9403..18eec57f5 100644 --- a/packages/agtree/src/compatibility-tables/scriptlets/metrika-yandex-watch.yml +++ b/packages/agtree/src/compatibility-tables/scriptlets/metrika-yandex-watch.yml @@ -1,6 +1,6 @@ # TODO: add scriptlet and param descriptions, documentation references, and versions # Note: content blocking products do not support scriptlets -adg_any_not_cb: +adg_os_any|adg_ext_any: name: metrika-yandex-watch version_added: 1.10.25 docs: https://github.com/AdguardTeam/Scriptlets/blob/master/wiki/about-scriptlets.md#metrika-yandex-watch diff --git a/packages/agtree/src/compatibility-tables/scriptlets/naver-wcslog.yml b/packages/agtree/src/compatibility-tables/scriptlets/naver-wcslog.yml index 4a3b238c3..95dc4e1f9 100644 --- a/packages/agtree/src/compatibility-tables/scriptlets/naver-wcslog.yml +++ b/packages/agtree/src/compatibility-tables/scriptlets/naver-wcslog.yml @@ -1,6 +1,6 @@ # TODO: add scriptlet and param descriptions, documentation references, and versions # Note: content blocking products do not support scriptlets -adg_any_not_cb: +adg_os_any|adg_ext_any: name: naver-wcslog version_added: 1.10.25 docs: https://github.com/AdguardTeam/Scriptlets/blob/master/wiki/about-scriptlets.md#naver-wcslog diff --git a/packages/agtree/src/compatibility-tables/scriptlets/no-protected-audience.yml b/packages/agtree/src/compatibility-tables/scriptlets/no-protected-audience.yml index 43cccb170..9088e5368 100644 --- a/packages/agtree/src/compatibility-tables/scriptlets/no-protected-audience.yml +++ b/packages/agtree/src/compatibility-tables/scriptlets/no-protected-audience.yml @@ -1,6 +1,6 @@ # TODO: add scriptlet and param descriptions, documentation references, and versions # Note: content blocking products do not support scriptlets -adg_any_not_cb: +adg_os_any|adg_ext_any: name: no-protected-audience version_added: 1.10.25 docs: https://github.com/AdguardTeam/Scriptlets/blob/master/wiki/about-scriptlets.md#no-protected-audience diff --git a/packages/agtree/src/compatibility-tables/scriptlets/no-topics.yml b/packages/agtree/src/compatibility-tables/scriptlets/no-topics.yml index a292b318d..e0ccc5e04 100644 --- a/packages/agtree/src/compatibility-tables/scriptlets/no-topics.yml +++ b/packages/agtree/src/compatibility-tables/scriptlets/no-topics.yml @@ -1,6 +1,6 @@ # TODO: add scriptlet and param descriptions, documentation references, and versions # Note: content blocking products do not support scriptlets -adg_any_not_cb: +adg_os_any|adg_ext_any: name: no-topics version_added: 1.6.18 docs: https://github.com/AdguardTeam/Scriptlets/blob/master/wiki/about-scriptlets.md#no-topics diff --git a/packages/agtree/src/compatibility-tables/scriptlets/noeval.yml b/packages/agtree/src/compatibility-tables/scriptlets/noeval.yml index 66d973d76..11328198d 100644 --- a/packages/agtree/src/compatibility-tables/scriptlets/noeval.yml +++ b/packages/agtree/src/compatibility-tables/scriptlets/noeval.yml @@ -1,6 +1,6 @@ # TODO: add scriptlet and param descriptions, documentation references, and versions # Note: content blocking products do not support scriptlets -adg_any_not_cb: +adg_os_any|adg_ext_any: name: noeval version_added: 1.0.4 aliases: diff --git a/packages/agtree/src/compatibility-tables/scriptlets/nowebrtc.yml b/packages/agtree/src/compatibility-tables/scriptlets/nowebrtc.yml index 82735cef7..7effb2925 100644 --- a/packages/agtree/src/compatibility-tables/scriptlets/nowebrtc.yml +++ b/packages/agtree/src/compatibility-tables/scriptlets/nowebrtc.yml @@ -1,6 +1,6 @@ # TODO: add scriptlet and param descriptions, documentation references, and versions # Note: content blocking products do not support scriptlets -adg_any_not_cb: +adg_os_any|adg_ext_any: name: nowebrtc version_added: 1.0.4 aliases: diff --git a/packages/agtree/src/compatibility-tables/scriptlets/pardot-1.0.yml b/packages/agtree/src/compatibility-tables/scriptlets/pardot-1.0.yml index f727e48fd..6d0c43c1f 100644 --- a/packages/agtree/src/compatibility-tables/scriptlets/pardot-1.0.yml +++ b/packages/agtree/src/compatibility-tables/scriptlets/pardot-1.0.yml @@ -1,6 +1,6 @@ # TODO: add scriptlet and param descriptions, documentation references, and versions # Note: content blocking products do not support scriptlets -adg_any_not_cb: +adg_os_any|adg_ext_any: name: pardot-1.0 version_added: 1.10.25 docs: https://github.com/AdguardTeam/Scriptlets/blob/master/wiki/about-scriptlets.md#pardot-1.0 diff --git a/packages/agtree/src/compatibility-tables/scriptlets/prebid.yml b/packages/agtree/src/compatibility-tables/scriptlets/prebid.yml index d9e11f26f..18270eed7 100644 --- a/packages/agtree/src/compatibility-tables/scriptlets/prebid.yml +++ b/packages/agtree/src/compatibility-tables/scriptlets/prebid.yml @@ -1,6 +1,6 @@ # TODO: add scriptlet and param descriptions, documentation references, and versions # Note: content blocking products do not support scriptlets -adg_any_not_cb: +adg_os_any|adg_ext_any: name: prebid version_added: 1.10.25 docs: https://github.com/AdguardTeam/Scriptlets/blob/master/wiki/about-scriptlets.md#prebid diff --git a/packages/agtree/src/compatibility-tables/scriptlets/prevent-addEventListener.yml b/packages/agtree/src/compatibility-tables/scriptlets/prevent-addEventListener.yml index 2d349c786..c8f5742de 100644 --- a/packages/agtree/src/compatibility-tables/scriptlets/prevent-addEventListener.yml +++ b/packages/agtree/src/compatibility-tables/scriptlets/prevent-addEventListener.yml @@ -1,6 +1,6 @@ # TODO: add scriptlet and param descriptions, documentation references, and versions # Note: content blocking products do not support scriptlets -adg_any_not_cb: +adg_os_any|adg_ext_any: name: prevent-addEventListener version_added: 1.0.4 aliases: diff --git a/packages/agtree/src/compatibility-tables/scriptlets/prevent-adfly.yml b/packages/agtree/src/compatibility-tables/scriptlets/prevent-adfly.yml index 508ec22a0..d4e7d4fab 100644 --- a/packages/agtree/src/compatibility-tables/scriptlets/prevent-adfly.yml +++ b/packages/agtree/src/compatibility-tables/scriptlets/prevent-adfly.yml @@ -1,6 +1,6 @@ # TODO: add scriptlet and param descriptions, documentation references, and versions # Note: content blocking products do not support scriptlets -adg_any_not_cb: +adg_os_any|adg_ext_any: name: prevent-adfly version_added: 1.0.4 aliases: diff --git a/packages/agtree/src/compatibility-tables/scriptlets/prevent-bab.yml b/packages/agtree/src/compatibility-tables/scriptlets/prevent-bab.yml index 7096dcb82..61d73c3ee 100644 --- a/packages/agtree/src/compatibility-tables/scriptlets/prevent-bab.yml +++ b/packages/agtree/src/compatibility-tables/scriptlets/prevent-bab.yml @@ -1,6 +1,6 @@ # TODO: add scriptlet and param descriptions, documentation references, and versions # Note: content blocking products do not support scriptlets -adg_any_not_cb: +adg_os_any|adg_ext_any: name: prevent-bab version_added: 1.0.4 docs: https://github.com/AdguardTeam/Scriptlets/blob/master/wiki/about-scriptlets.md#prevent-bab diff --git a/packages/agtree/src/compatibility-tables/scriptlets/prevent-element-src-loading.yml b/packages/agtree/src/compatibility-tables/scriptlets/prevent-element-src-loading.yml index 429c456c6..a245f4ec0 100644 --- a/packages/agtree/src/compatibility-tables/scriptlets/prevent-element-src-loading.yml +++ b/packages/agtree/src/compatibility-tables/scriptlets/prevent-element-src-loading.yml @@ -1,6 +1,6 @@ # TODO: add scriptlet and param descriptions, documentation references, and versions # Note: content blocking products do not support scriptlets -adg_any_not_cb: +adg_os_any|adg_ext_any: name: prevent-element-src-loading version_added: 1.6.2 docs: https://github.com/AdguardTeam/Scriptlets/blob/master/wiki/about-scriptlets.md#prevent-element-src-loading diff --git a/packages/agtree/src/compatibility-tables/scriptlets/prevent-eval-if.yml b/packages/agtree/src/compatibility-tables/scriptlets/prevent-eval-if.yml index 3a71d445a..71529a6dc 100644 --- a/packages/agtree/src/compatibility-tables/scriptlets/prevent-eval-if.yml +++ b/packages/agtree/src/compatibility-tables/scriptlets/prevent-eval-if.yml @@ -1,6 +1,6 @@ # TODO: add scriptlet and param descriptions, documentation references, and versions # Note: content blocking products do not support scriptlets -adg_any_not_cb: +adg_os_any|adg_ext_any: name: prevent-eval-if version_added: 1.0.4 aliases: diff --git a/packages/agtree/src/compatibility-tables/scriptlets/prevent-fab-3.2.0.yml b/packages/agtree/src/compatibility-tables/scriptlets/prevent-fab-3.2.0.yml index 719f97a9c..d9ac6a612 100644 --- a/packages/agtree/src/compatibility-tables/scriptlets/prevent-fab-3.2.0.yml +++ b/packages/agtree/src/compatibility-tables/scriptlets/prevent-fab-3.2.0.yml @@ -1,6 +1,6 @@ # TODO: add scriptlet and param descriptions, documentation references, and versions # Note: content blocking products do not support scriptlets -adg_any_not_cb: +adg_os_any|adg_ext_any: name: prevent-fab-3.2.0 version_added: 1.0.4 aliases: diff --git a/packages/agtree/src/compatibility-tables/scriptlets/prevent-fetch.yml b/packages/agtree/src/compatibility-tables/scriptlets/prevent-fetch.yml index 7001d19ac..2bef5268a 100644 --- a/packages/agtree/src/compatibility-tables/scriptlets/prevent-fetch.yml +++ b/packages/agtree/src/compatibility-tables/scriptlets/prevent-fetch.yml @@ -1,6 +1,6 @@ # TODO: add scriptlet and param descriptions, documentation references, and versions # Note: content blocking products do not support scriptlets -adg_any_not_cb: +adg_os_any|adg_ext_any: name: prevent-fetch version_added: 1.3.18 aliases: diff --git a/packages/agtree/src/compatibility-tables/scriptlets/prevent-popads-net.yml b/packages/agtree/src/compatibility-tables/scriptlets/prevent-popads-net.yml index 6aaa10890..f7491b23f 100644 --- a/packages/agtree/src/compatibility-tables/scriptlets/prevent-popads-net.yml +++ b/packages/agtree/src/compatibility-tables/scriptlets/prevent-popads-net.yml @@ -1,6 +1,6 @@ # TODO: add scriptlet and param descriptions, documentation references, and versions # Note: content blocking products do not support scriptlets -adg_any_not_cb: +adg_os_any|adg_ext_any: name: prevent-popads-net version_added: 1.0.4 aliases: diff --git a/packages/agtree/src/compatibility-tables/scriptlets/prevent-refresh.yml b/packages/agtree/src/compatibility-tables/scriptlets/prevent-refresh.yml index fc70376b2..d1361a4a4 100644 --- a/packages/agtree/src/compatibility-tables/scriptlets/prevent-refresh.yml +++ b/packages/agtree/src/compatibility-tables/scriptlets/prevent-refresh.yml @@ -1,6 +1,6 @@ # TODO: add scriptlet and param descriptions, documentation references, and versions # Note: content blocking products do not support scriptlets -adg_any_not_cb: +adg_os_any|adg_ext_any: name: prevent-refresh version_added: 1.6.2 aliases: diff --git a/packages/agtree/src/compatibility-tables/scriptlets/prevent-requestAnimationFrame.yml b/packages/agtree/src/compatibility-tables/scriptlets/prevent-requestAnimationFrame.yml index 91e69d4d9..5bb52b26c 100644 --- a/packages/agtree/src/compatibility-tables/scriptlets/prevent-requestAnimationFrame.yml +++ b/packages/agtree/src/compatibility-tables/scriptlets/prevent-requestAnimationFrame.yml @@ -1,6 +1,6 @@ # TODO: add scriptlet and param descriptions, documentation references, and versions # Note: content blocking products do not support scriptlets -adg_any_not_cb: +adg_os_any|adg_ext_any: name: prevent-requestAnimationFrame version_added: 1.1.15 aliases: diff --git a/packages/agtree/src/compatibility-tables/scriptlets/prevent-setInterval.yml b/packages/agtree/src/compatibility-tables/scriptlets/prevent-setInterval.yml index b247c7504..c83732e6f 100644 --- a/packages/agtree/src/compatibility-tables/scriptlets/prevent-setInterval.yml +++ b/packages/agtree/src/compatibility-tables/scriptlets/prevent-setInterval.yml @@ -1,6 +1,6 @@ # TODO: add scriptlet and param descriptions, documentation references, and versions # Note: content blocking products do not support scriptlets -adg_any_not_cb: +adg_os_any|adg_ext_any: name: prevent-setInterval version_added: 1.0.4 aliases: diff --git a/packages/agtree/src/compatibility-tables/scriptlets/prevent-setTimeout.yml b/packages/agtree/src/compatibility-tables/scriptlets/prevent-setTimeout.yml index c3a16ee50..46475eed8 100644 --- a/packages/agtree/src/compatibility-tables/scriptlets/prevent-setTimeout.yml +++ b/packages/agtree/src/compatibility-tables/scriptlets/prevent-setTimeout.yml @@ -1,6 +1,6 @@ # TODO: add scriptlet and param descriptions, documentation references, and versions # Note: content blocking products do not support scriptlets -adg_any_not_cb: +adg_os_any|adg_ext_any: name: prevent-setTimeout version_added: 1.0.4 aliases: diff --git a/packages/agtree/src/compatibility-tables/scriptlets/prevent-window-open.yml b/packages/agtree/src/compatibility-tables/scriptlets/prevent-window-open.yml index d9905dbb7..c4e7000c3 100644 --- a/packages/agtree/src/compatibility-tables/scriptlets/prevent-window-open.yml +++ b/packages/agtree/src/compatibility-tables/scriptlets/prevent-window-open.yml @@ -1,6 +1,6 @@ # TODO: add scriptlet and param descriptions, documentation references, and versions # Note: content blocking products do not support scriptlets -adg_any_not_cb: +adg_os_any|adg_ext_any: name: prevent-window-open version_added: 1.0.4 aliases: diff --git a/packages/agtree/src/compatibility-tables/scriptlets/prevent-xhr.yml b/packages/agtree/src/compatibility-tables/scriptlets/prevent-xhr.yml index e3a14a1b7..c3dfcbd10 100644 --- a/packages/agtree/src/compatibility-tables/scriptlets/prevent-xhr.yml +++ b/packages/agtree/src/compatibility-tables/scriptlets/prevent-xhr.yml @@ -1,6 +1,6 @@ # TODO: add scriptlet and param descriptions, documentation references, and versions # Note: content blocking products do not support scriptlets -adg_any_not_cb: +adg_os_any|adg_ext_any: name: prevent-xhr version_added: 1.5.0 aliases: diff --git a/packages/agtree/src/compatibility-tables/scriptlets/remove-attr.yml b/packages/agtree/src/compatibility-tables/scriptlets/remove-attr.yml index 5b6ac2e69..87699ba2e 100644 --- a/packages/agtree/src/compatibility-tables/scriptlets/remove-attr.yml +++ b/packages/agtree/src/compatibility-tables/scriptlets/remove-attr.yml @@ -1,6 +1,6 @@ # TODO: add scriptlet and param descriptions, documentation references, and versions # Note: content blocking products do not support scriptlets -adg_any_not_cb: +adg_os_any|adg_ext_any: name: remove-attr version_added: 1.0.4 aliases: diff --git a/packages/agtree/src/compatibility-tables/scriptlets/remove-class.yml b/packages/agtree/src/compatibility-tables/scriptlets/remove-class.yml index e7820f56f..238f68b6e 100644 --- a/packages/agtree/src/compatibility-tables/scriptlets/remove-class.yml +++ b/packages/agtree/src/compatibility-tables/scriptlets/remove-class.yml @@ -1,6 +1,6 @@ # TODO: add scriptlet and param descriptions, documentation references, and versions # Note: content blocking products do not support scriptlets -adg_any_not_cb: +adg_os_any|adg_ext_any: name: remove-class version_added: 1.1.1 aliases: diff --git a/packages/agtree/src/compatibility-tables/scriptlets/remove-cookie.yml b/packages/agtree/src/compatibility-tables/scriptlets/remove-cookie.yml index 6eea3a9a6..b91cb3fd4 100644 --- a/packages/agtree/src/compatibility-tables/scriptlets/remove-cookie.yml +++ b/packages/agtree/src/compatibility-tables/scriptlets/remove-cookie.yml @@ -1,6 +1,6 @@ # TODO: add scriptlet and param descriptions, documentation references, and versions # Note: content blocking products do not support scriptlets -adg_any_not_cb: +adg_os_any|adg_ext_any: name: remove-cookie version_added: 1.0.4 aliases: diff --git a/packages/agtree/src/compatibility-tables/scriptlets/remove-in-shadow-dom.yml b/packages/agtree/src/compatibility-tables/scriptlets/remove-in-shadow-dom.yml index 975ed66db..8a2db392c 100644 --- a/packages/agtree/src/compatibility-tables/scriptlets/remove-in-shadow-dom.yml +++ b/packages/agtree/src/compatibility-tables/scriptlets/remove-in-shadow-dom.yml @@ -1,6 +1,6 @@ # TODO: add scriptlet and param descriptions, documentation references, and versions # Note: content blocking products do not support scriptlets -adg_any_not_cb: +adg_os_any|adg_ext_any: name: remove-in-shadow-dom version_added: 1.3.14 docs: https://github.com/AdguardTeam/Scriptlets/blob/master/wiki/about-scriptlets.md#remove-in-shadow-dom diff --git a/packages/agtree/src/compatibility-tables/scriptlets/remove-node-text.yml b/packages/agtree/src/compatibility-tables/scriptlets/remove-node-text.yml index b3e30aa4a..c8bd2234a 100644 --- a/packages/agtree/src/compatibility-tables/scriptlets/remove-node-text.yml +++ b/packages/agtree/src/compatibility-tables/scriptlets/remove-node-text.yml @@ -1,6 +1,6 @@ # TODO: add scriptlet and param descriptions, documentation references, and versions # Note: content blocking products do not support scriptlets -adg_any_not_cb: +adg_os_any|adg_ext_any: name: remove-node-text version_added: 1.9.37 aliases: diff --git a/packages/agtree/src/compatibility-tables/scriptlets/scorecardresearch-beacon.yml b/packages/agtree/src/compatibility-tables/scriptlets/scorecardresearch-beacon.yml index 872607d12..f071d36c7 100644 --- a/packages/agtree/src/compatibility-tables/scriptlets/scorecardresearch-beacon.yml +++ b/packages/agtree/src/compatibility-tables/scriptlets/scorecardresearch-beacon.yml @@ -1,6 +1,6 @@ # TODO: add scriptlet and param descriptions, documentation references, and versions # Note: content blocking products do not support scriptlets -adg_any_not_cb: +adg_os_any|adg_ext_any: name: scorecardresearch-beacon version_added: 1.10.25 aliases: diff --git a/packages/agtree/src/compatibility-tables/scriptlets/set-attr.yml b/packages/agtree/src/compatibility-tables/scriptlets/set-attr.yml index 8e9df60f5..8fae3b4f7 100644 --- a/packages/agtree/src/compatibility-tables/scriptlets/set-attr.yml +++ b/packages/agtree/src/compatibility-tables/scriptlets/set-attr.yml @@ -1,6 +1,6 @@ # TODO: add scriptlet and param descriptions, documentation references, and versions # Note: content blocking products do not support scriptlets -adg_any_not_cb: +adg_os_any|adg_ext_any: name: set-attr version_added: 1.5.0 aliases: diff --git a/packages/agtree/src/compatibility-tables/scriptlets/set-constant.yml b/packages/agtree/src/compatibility-tables/scriptlets/set-constant.yml index 358efcc00..5a4d999ff 100644 --- a/packages/agtree/src/compatibility-tables/scriptlets/set-constant.yml +++ b/packages/agtree/src/compatibility-tables/scriptlets/set-constant.yml @@ -1,6 +1,6 @@ # TODO: add scriptlet and param descriptions, documentation references, and versions # Note: content blocking products do not support scriptlets -adg_any_not_cb: +adg_os_any|adg_ext_any: name: set-constant version_added: 1.0.4 aliases: diff --git a/packages/agtree/src/compatibility-tables/scriptlets/set-cookie-reload.yml b/packages/agtree/src/compatibility-tables/scriptlets/set-cookie-reload.yml index b97603a92..7e2200b42 100644 --- a/packages/agtree/src/compatibility-tables/scriptlets/set-cookie-reload.yml +++ b/packages/agtree/src/compatibility-tables/scriptlets/set-cookie-reload.yml @@ -1,6 +1,6 @@ # TODO: add scriptlet and param descriptions, documentation references, and versions # Note: content blocking products do not support scriptlets -adg_any_not_cb: +adg_os_any|adg_ext_any: name: set-cookie-reload version_added: 1.3.14 aliases: diff --git a/packages/agtree/src/compatibility-tables/scriptlets/set-cookie.yml b/packages/agtree/src/compatibility-tables/scriptlets/set-cookie.yml index c0476db3c..95f8b6a79 100644 --- a/packages/agtree/src/compatibility-tables/scriptlets/set-cookie.yml +++ b/packages/agtree/src/compatibility-tables/scriptlets/set-cookie.yml @@ -1,6 +1,6 @@ # TODO: add scriptlet and param descriptions, documentation references, and versions # Note: content blocking products do not support scriptlets -adg_any_not_cb: +adg_os_any|adg_ext_any: name: set-cookie version_added: 1.2.3 aliases: diff --git a/packages/agtree/src/compatibility-tables/scriptlets/set-local-storage-item.yml b/packages/agtree/src/compatibility-tables/scriptlets/set-local-storage-item.yml index abb7e6b83..c566b63cf 100644 --- a/packages/agtree/src/compatibility-tables/scriptlets/set-local-storage-item.yml +++ b/packages/agtree/src/compatibility-tables/scriptlets/set-local-storage-item.yml @@ -1,6 +1,6 @@ # TODO: add scriptlet and param descriptions, documentation references, and versions # Note: content blocking products do not support scriptlets -adg_any_not_cb: +adg_os_any|adg_ext_any: name: set-local-storage-item version_added: 1.4.3 aliases: diff --git a/packages/agtree/src/compatibility-tables/scriptlets/set-popads-dummy.yml b/packages/agtree/src/compatibility-tables/scriptlets/set-popads-dummy.yml index 8033de08f..646543cdf 100644 --- a/packages/agtree/src/compatibility-tables/scriptlets/set-popads-dummy.yml +++ b/packages/agtree/src/compatibility-tables/scriptlets/set-popads-dummy.yml @@ -1,6 +1,6 @@ # TODO: add scriptlet and param descriptions, documentation references, and versions # Note: content blocking products do not support scriptlets -adg_any_not_cb: +adg_os_any|adg_ext_any: name: set-popads-dummy version_added: 1.0.4 aliases: diff --git a/packages/agtree/src/compatibility-tables/scriptlets/set-session-storage-item.yml b/packages/agtree/src/compatibility-tables/scriptlets/set-session-storage-item.yml index f6c34bfee..e2d4aec2d 100644 --- a/packages/agtree/src/compatibility-tables/scriptlets/set-session-storage-item.yml +++ b/packages/agtree/src/compatibility-tables/scriptlets/set-session-storage-item.yml @@ -1,6 +1,6 @@ # TODO: add scriptlet and param descriptions, documentation references, and versions # Note: content blocking products do not support scriptlets -adg_any_not_cb: +adg_os_any|adg_ext_any: name: set-session-storage-item version_added: 1.4.3 aliases: diff --git a/packages/agtree/src/compatibility-tables/scriptlets/spoof-css.yml b/packages/agtree/src/compatibility-tables/scriptlets/spoof-css.yml index 60c428401..07410145e 100644 --- a/packages/agtree/src/compatibility-tables/scriptlets/spoof-css.yml +++ b/packages/agtree/src/compatibility-tables/scriptlets/spoof-css.yml @@ -1,6 +1,6 @@ # TODO: add scriptlet and param descriptions, documentation references, and versions # Note: content blocking products do not support scriptlets -adg_any_not_cb: +adg_os_any|adg_ext_any: name: spoof-css version_added: 1.10.1 aliases: diff --git a/packages/agtree/src/compatibility-tables/scriptlets/trusted-click-element.yml b/packages/agtree/src/compatibility-tables/scriptlets/trusted-click-element.yml index 825769e09..fc5d72f67 100644 --- a/packages/agtree/src/compatibility-tables/scriptlets/trusted-click-element.yml +++ b/packages/agtree/src/compatibility-tables/scriptlets/trusted-click-element.yml @@ -1,6 +1,6 @@ # TODO: add scriptlet and param descriptions, documentation references, and versions # Note: content blocking products do not support scriptlets -adg_any_not_cb: +adg_os_any|adg_ext_any: name: trusted-click-element version_added: 1.7.3 parameters: diff --git a/packages/agtree/src/compatibility-tables/scriptlets/trusted-create-element.yml b/packages/agtree/src/compatibility-tables/scriptlets/trusted-create-element.yml index 87d1a15bb..37f9cc102 100644 --- a/packages/agtree/src/compatibility-tables/scriptlets/trusted-create-element.yml +++ b/packages/agtree/src/compatibility-tables/scriptlets/trusted-create-element.yml @@ -1,6 +1,6 @@ # TODO: add scriptlet and param descriptions, documentation references, and versions # Note: content blocking products do not support scriptlets -adg_any_not_cb: +adg_os_any|adg_ext_any: name: trusted-create-element version_added: 1.10.1 parameters: diff --git a/packages/agtree/src/compatibility-tables/scriptlets/trusted-dispatch-event.yml b/packages/agtree/src/compatibility-tables/scriptlets/trusted-dispatch-event.yml index 36c093710..9bb66bdf0 100644 --- a/packages/agtree/src/compatibility-tables/scriptlets/trusted-dispatch-event.yml +++ b/packages/agtree/src/compatibility-tables/scriptlets/trusted-dispatch-event.yml @@ -1,6 +1,6 @@ # TODO: add scriptlet and param descriptions, documentation references, and versions # Note: content blocking products do not support scriptlets -adg_any_not_cb: +adg_os_any|adg_ext_any: name: trusted-dispatch-event parameters: - name: event diff --git a/packages/agtree/src/compatibility-tables/scriptlets/trusted-prune-inbound-object.yml b/packages/agtree/src/compatibility-tables/scriptlets/trusted-prune-inbound-object.yml index 1fb097662..d6b2db538 100644 --- a/packages/agtree/src/compatibility-tables/scriptlets/trusted-prune-inbound-object.yml +++ b/packages/agtree/src/compatibility-tables/scriptlets/trusted-prune-inbound-object.yml @@ -1,6 +1,6 @@ # TODO: add scriptlet and param descriptions, documentation references, and versions # Note: content blocking products do not support scriptlets -adg_any_not_cb: +adg_os_any|adg_ext_any: name: trusted-prune-inbound-object version_added: 1.9.91 parameters: diff --git a/packages/agtree/src/compatibility-tables/scriptlets/trusted-replace-fetch-response.yml b/packages/agtree/src/compatibility-tables/scriptlets/trusted-replace-fetch-response.yml index a7e80667e..27073ab10 100644 --- a/packages/agtree/src/compatibility-tables/scriptlets/trusted-replace-fetch-response.yml +++ b/packages/agtree/src/compatibility-tables/scriptlets/trusted-replace-fetch-response.yml @@ -1,6 +1,6 @@ # TODO: add scriptlet and param descriptions, documentation references, and versions # Note: content blocking products do not support scriptlets -adg_any_not_cb: +adg_os_any|adg_ext_any: name: trusted-replace-fetch-response version_added: 1.7.3 parameters: diff --git a/packages/agtree/src/compatibility-tables/scriptlets/trusted-replace-node-text.yml b/packages/agtree/src/compatibility-tables/scriptlets/trusted-replace-node-text.yml index 344c5df00..4443363cb 100644 --- a/packages/agtree/src/compatibility-tables/scriptlets/trusted-replace-node-text.yml +++ b/packages/agtree/src/compatibility-tables/scriptlets/trusted-replace-node-text.yml @@ -1,6 +1,6 @@ # TODO: add scriptlet and param descriptions, documentation references, and versions # Note: content blocking products do not support scriptlets -adg_any_not_cb: +adg_os_any|adg_ext_any: name: trusted-replace-node-text version_added: 1.9.37 parameters: diff --git a/packages/agtree/src/compatibility-tables/scriptlets/trusted-replace-xhr-response.yml b/packages/agtree/src/compatibility-tables/scriptlets/trusted-replace-xhr-response.yml index 6a4fd38db..1d0ddd776 100644 --- a/packages/agtree/src/compatibility-tables/scriptlets/trusted-replace-xhr-response.yml +++ b/packages/agtree/src/compatibility-tables/scriptlets/trusted-replace-xhr-response.yml @@ -1,6 +1,6 @@ # TODO: add scriptlet and param descriptions, documentation references, and versions # Note: content blocking products do not support scriptlets -adg_any_not_cb: +adg_os_any|adg_ext_any: name: trusted-replace-xhr-response version_added: 1.7.3 parameters: diff --git a/packages/agtree/src/compatibility-tables/scriptlets/trusted-set-attr.yml b/packages/agtree/src/compatibility-tables/scriptlets/trusted-set-attr.yml index 82f3c4bd6..5b3e95230 100644 --- a/packages/agtree/src/compatibility-tables/scriptlets/trusted-set-attr.yml +++ b/packages/agtree/src/compatibility-tables/scriptlets/trusted-set-attr.yml @@ -1,6 +1,6 @@ # TODO: add scriptlet and param descriptions, documentation references, and versions # Note: content blocking products do not support scriptlets -adg_any_not_cb: +adg_os_any|adg_ext_any: name: trusted-set-attr version_added: 1.10.1 parameters: diff --git a/packages/agtree/src/compatibility-tables/scriptlets/trusted-set-constant.yml b/packages/agtree/src/compatibility-tables/scriptlets/trusted-set-constant.yml index 4d06d13d7..d5897b0a8 100644 --- a/packages/agtree/src/compatibility-tables/scriptlets/trusted-set-constant.yml +++ b/packages/agtree/src/compatibility-tables/scriptlets/trusted-set-constant.yml @@ -1,6 +1,6 @@ # TODO: add scriptlet and param descriptions, documentation references, and versions # Note: content blocking products do not support scriptlets -adg_any_not_cb: +adg_os_any|adg_ext_any: name: trusted-set-constant version_added: 1.8.2 parameters: diff --git a/packages/agtree/src/compatibility-tables/scriptlets/trusted-set-cookie-reload.yml b/packages/agtree/src/compatibility-tables/scriptlets/trusted-set-cookie-reload.yml index 23a4650f8..773f67891 100644 --- a/packages/agtree/src/compatibility-tables/scriptlets/trusted-set-cookie-reload.yml +++ b/packages/agtree/src/compatibility-tables/scriptlets/trusted-set-cookie-reload.yml @@ -1,6 +1,6 @@ # TODO: add scriptlet and param descriptions, documentation references, and versions # Note: content blocking products do not support scriptlets -adg_any_not_cb: +adg_os_any|adg_ext_any: name: trusted-set-cookie-reload version_added: 1.7.10 parameters: diff --git a/packages/agtree/src/compatibility-tables/scriptlets/trusted-set-cookie.yml b/packages/agtree/src/compatibility-tables/scriptlets/trusted-set-cookie.yml index 982c17be1..79dac2fda 100644 --- a/packages/agtree/src/compatibility-tables/scriptlets/trusted-set-cookie.yml +++ b/packages/agtree/src/compatibility-tables/scriptlets/trusted-set-cookie.yml @@ -1,6 +1,6 @@ # TODO: add scriptlet and param descriptions, documentation references, and versions # Note: content blocking products do not support scriptlets -adg_any_not_cb: +adg_os_any|adg_ext_any: name: trusted-set-cookie version_added: 1.7.3 parameters: diff --git a/packages/agtree/src/compatibility-tables/scriptlets/trusted-set-local-storage-item.yml b/packages/agtree/src/compatibility-tables/scriptlets/trusted-set-local-storage-item.yml index 074272530..68be3e4a9 100644 --- a/packages/agtree/src/compatibility-tables/scriptlets/trusted-set-local-storage-item.yml +++ b/packages/agtree/src/compatibility-tables/scriptlets/trusted-set-local-storage-item.yml @@ -1,6 +1,6 @@ # TODO: add scriptlet and param descriptions, documentation references, and versions # Note: content blocking products do not support scriptlets -adg_any_not_cb: +adg_os_any|adg_ext_any: name: trusted-set-local-storage-item version_added: 1.7.3 parameters: diff --git a/packages/agtree/src/compatibility-tables/scriptlets/trusted-suppress-native-method.yml b/packages/agtree/src/compatibility-tables/scriptlets/trusted-suppress-native-method.yml index 6b3b49a00..96e2a9bbb 100644 --- a/packages/agtree/src/compatibility-tables/scriptlets/trusted-suppress-native-method.yml +++ b/packages/agtree/src/compatibility-tables/scriptlets/trusted-suppress-native-method.yml @@ -1,6 +1,6 @@ # TODO: add scriptlet and param descriptions, documentation references, and versions # Note: content blocking products do not support scriptlets -adg_any_not_cb: +adg_os_any|adg_ext_any: name: trusted-suppress-native-method version_added: 1.10.25 parameters: diff --git a/packages/agtree/src/compatibility-tables/scriptlets/xml-prune.yml b/packages/agtree/src/compatibility-tables/scriptlets/xml-prune.yml index 5a087009f..50bc27662 100644 --- a/packages/agtree/src/compatibility-tables/scriptlets/xml-prune.yml +++ b/packages/agtree/src/compatibility-tables/scriptlets/xml-prune.yml @@ -1,6 +1,6 @@ # TODO: add scriptlet and param descriptions, documentation references, and versions # Note: content blocking products do not support scriptlets -adg_any_not_cb: +adg_os_any|adg_ext_any: name: xml-prune version_added: 1.7.3 aliases: diff --git a/packages/agtree/src/compatibility-tables/types.ts b/packages/agtree/src/compatibility-tables/types.ts index d80ae1f46..903832b3d 100644 --- a/packages/agtree/src/compatibility-tables/types.ts +++ b/packages/agtree/src/compatibility-tables/types.ts @@ -3,75 +3,35 @@ */ /** - * List of properties names for modifier data. + * Map with shared storage. + * The idea is to avoid storing the same value multiple times in the map, + * so the value is stored in the `shared` array and the map refers to the index in the `shared` array. * - * @see {@link https://github.com/AdguardTeam/tsurlfilter/blob/master/packages/agtree/src/compatibility-tables/modifiers/README.md#file-structure} + * @template K Type of the map keys. + * @template V Type of the map values. */ -export const enum SpecificKey { - Name = 'name', - Aliases = 'aliases', - Description = 'description', - Docs = 'docs', - Deprecated = 'deprecated', - DeprecationMessage = 'deprecation_message', - Removed = 'removed', - RemovalMessage = 'removal_message', - Conflicts = 'conflicts', - InverseConflicts = 'inverse_conflicts', - Assignable = 'assignable', - Negatable = 'negatable', - BlockOnly = 'block_only', - ExceptionOnly = 'exception_only', - ValueOptional = 'value_optional', - ValueFormat = 'value_format', - // TODO: following fields should be handled later - // VersionAdded = 'version_added', - // VersionRemoved = 'version_removed', -} +interface MapWithSharedStorage { + /** + * Shared storage. + */ + shared: V[]; -/** - * Specific platform modifier data type - * where all properties are required. - */ -export type SpecificPlatformModifierData = { - [SpecificKey.Name]: string; - [SpecificKey.Aliases]: string[] | null; - [SpecificKey.Description]: string | null; - [SpecificKey.Docs]: string | null; - [SpecificKey.Deprecated]: boolean; - [SpecificKey.DeprecationMessage]: string | null; - [SpecificKey.Removed]: boolean; - [SpecificKey.RemovalMessage]: string | null; - [SpecificKey.Conflicts]: string[] | null; - [SpecificKey.InverseConflicts]: boolean; - [SpecificKey.Assignable]: boolean; - [SpecificKey.Negatable]: boolean; - [SpecificKey.BlockOnly]: boolean; - [SpecificKey.ExceptionOnly]: boolean; - [SpecificKey.ValueOptional]: boolean; - [SpecificKey.ValueFormat]: string | null; - // TODO: following fields should be handled later - // [SpecificKey.VersionAdded]?: string | null; - // [SpecificKey.VersionRemoved]?: string | null; -}; - -/** - * Modifier data is an object where - * - `key` — blocker id, e.g. 'adg_os_any', 'ubo_ext_any', etc. - * - `value` — specific platform data, e.g. `{ name: 'domain', aliases: ['from'], ... }` - */ -export type ModifierData = { - [key: string]: SpecificPlatformModifierData; -}; + /** + * Map of the values where the value is a pointer to the shared storage (refers to the index in the `shared` array). + */ + map: Record; +} /** - * Raw compatibility tables data object combined from yaml files. + * Compatibility table row. + * + * @template T Type of the compatibility data. */ -export type RawModifierData = { - [key: string]: ModifierData; -}; +export type CompatibilityTableRow = MapWithSharedStorage; /** - * Modifier data map prepared from raw modifiers data. + * Compatibility table. + * + * @template T Type of the compatibility data. */ -export type ModifierDataMap = Map; +export type CompatibilityTable = MapWithSharedStorage>; diff --git a/packages/agtree/src/compatibility-tables/utils/platform-helpers.ts b/packages/agtree/src/compatibility-tables/utils/platform-helpers.ts new file mode 100644 index 000000000..b0bb9c95a --- /dev/null +++ b/packages/agtree/src/compatibility-tables/utils/platform-helpers.ts @@ -0,0 +1,118 @@ +/* eslint-disable no-bitwise */ +/** + * @file Provides platform mapping and helper functions. + */ + +import { GenericPlatform, SpecificPlatform } from '../platforms'; + +/** + * Map of specific platforms string names to their corresponding enum values. + */ +export const SPECIFIC_PLATFORM_MAP: Map = new Map([ + ['adg_os_windows', SpecificPlatform.AdgOsWindows], + ['adg_os_mac', SpecificPlatform.AdgOsMac], + ['adg_os_android', SpecificPlatform.AdgOsAndroid], + + ['adg_ext_chrome', SpecificPlatform.AdgExtChrome], + ['adg_ext_opera', SpecificPlatform.AdgExtOpera], + ['adg_ext_edge', SpecificPlatform.AdgExtEdge], + ['adg_ext_firefox', SpecificPlatform.AdgExtFirefox], + + ['adg_cb_android', SpecificPlatform.AdgCbAndroid], + ['adg_cb_ios', SpecificPlatform.AdgCbIos], + ['adg_cb_safari', SpecificPlatform.AdgCbSafari], + + ['ubo_ext_chrome', SpecificPlatform.UboExtChrome], + ['ubo_ext_opera', SpecificPlatform.UboExtOpera], + ['ubo_ext_edge', SpecificPlatform.UboExtEdge], + ['ubo_ext_firefox', SpecificPlatform.UboExtFirefox], + + ['abp_ext_chrome', SpecificPlatform.AbpExtChrome], + ['abp_ext_opera', SpecificPlatform.AbpExtOpera], + ['abp_ext_edge', SpecificPlatform.AbpExtEdge], + ['abp_ext_firefox', SpecificPlatform.AbpExtFirefox], +]); + +/** + * Map of specific platforms enum values to their corresponding string names. + * + * @note Reverse of {@link SPECIFIC_PLATFORM_MAP}. + */ +export const SPECIFIC_PLATFORM_MAP_REVERSE: Map = new Map( + [...SPECIFIC_PLATFORM_MAP].map(([key, value]) => [value, key]), +); + +/** + * Map of generic platforms string names to their corresponding enum values. + */ +export const GENERIC_PLATFORM_MAP: Map = new Map([ + ['adg_os_any', GenericPlatform.AdgOsAny], + ['adg_safari_any', GenericPlatform.AdgSafariAny], + ['adg_ext_chromium', GenericPlatform.AdgExtChromium], + ['adg_ext_any', GenericPlatform.AdgExtAny], + ['adg_any', GenericPlatform.AdgAny], + + ['ubo_ext_chromium', GenericPlatform.UboExtChromium], + ['ubo_ext_any', GenericPlatform.UboExtAny], + ['ubo_any', GenericPlatform.UboAny], + + ['abp_ext_chromium', GenericPlatform.AbpExtChromium], + ['abp_ext_any', GenericPlatform.AbpExtAny], + ['abp_any', GenericPlatform.AbpAny], + + ['any', GenericPlatform.Any], +]); + +/** + * Check if the platform is a generic platform. + * + * @param platform Platform to check. + * + * @returns True if the platform is a generic platform, false otherwise. + */ +export const isGenericPlatform = (platform: number): boolean => { + // if more than one bit is set, it's a generic platform + return !!(platform & (platform - 1)); +}; + +/** + * 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. + */ +export const getPlatformId = (platform: string): SpecificPlatform | GenericPlatform => { + 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. + */ +export const getSpecificPlatformName = (platform: SpecificPlatform): string => { + const specificPlatform = SPECIFIC_PLATFORM_MAP_REVERSE.get(platform); + + if (!specificPlatform) { + throw new Error(`Unknown platform: ${platform}`); + } + + return specificPlatform; +}; diff --git a/packages/agtree/src/compatibility-tables/utils/zod-camelcase.ts b/packages/agtree/src/compatibility-tables/utils/zod-camelcase.ts new file mode 100644 index 000000000..f011a3a9e --- /dev/null +++ b/packages/agtree/src/compatibility-tables/utils/zod-camelcase.ts @@ -0,0 +1,23 @@ +/** + * @file Zod camelCase utility. + */ + +import type zod from 'zod'; +// eslint-disable-next-line import/no-extraneous-dependencies +import camelCaseKeys from 'camelcase-keys'; +import { type CamelCasedPropertiesDeep } from 'type-fest'; + +/** + * Transforms Zod schema to camelCase. + * + * @param zod Zod schema. + * + * @returns Zod schema with camelCase properties. + * + * @see {@link https://github.com/colinhacks/zod/issues/486#issuecomment-1501097361} + */ +export const zodToCamelCase = ( + zod: T, +): zod.ZodEffects> => { + return zod.transform((val) => camelCaseKeys(val) as CamelCasedPropertiesDeep); +}; diff --git a/packages/agtree/src/compatibility-tables/wiki/modifiers-compatibility-table-extended.md b/packages/agtree/src/compatibility-tables/wiki/modifiers-compatibility-table-extended.md new file mode 100644 index 000000000..d7be5ecb5 --- /dev/null +++ b/packages/agtree/src/compatibility-tables/wiki/modifiers-compatibility-table-extended.md @@ -0,0 +1,2310 @@ + +# Modifiers Compatibility Table + +This table is generated from the compatibility data. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
AdGuarduBlock OriginAdblock Plus / AdBlock
CoreLibsChromiumFirefoxSafari CBAndroid CBChromiumFirefoxChromiumFirefox
+ _ + + _ + + _ + + _ + + _ + + _ +
+ all + + all + + all + + all + + all + + all +
+ app +
+ badfilter + + badfilter + + badfilter + + badfilter + + badfilter + + badfilter +
+ content +
+ cookie + + cookie + + cookie +
+ csp + + csp + + csp + + csp + + csp + + csp + + csp +
+ denyallow + + denyallow + + denyallow + + denyallow + + denyallow + + denyallow +
+ document + + document + + document + + document + + document + (doc) + + document + (doc) + + document + + document +
+ domain + (from) + + domain + (from) + + domain + (from) + + domain + (from) + + domain + (from) + + domain + (from) + + domain + (from) + + domain + + domain +
+ elemhide + (ehide) + + elemhide + (ehide) + + elemhide + (ehide) + + elemhide + (ehide) + + elemhide + (ehide) + + elemhide + (ehide) + + elemhide + (ehide) + + elemhide + (ehide) + + elemhide + (ehide) +
+ empty + + empty + + empty + + empty + + empty +
+ extension +
+ first-party + (1p, ~third-party) + + first-party + (1p, ~third-party) + + first-party + (1p, ~third-party) + + first-party + (1p, ~third-party) + + first-party + (1p, ~third-party) + + first-party + (1p, ~third-party) + + first-party + (1p, ~third-party) +
+ font + + font + + font + + font + + font + + font + + font + + font + + font +
+ genericblock + + genericblock + + genericblock + + genericblock + + genericblock + + genericblock +
+ generichide + (ghide) + + generichide + (ghide) + + generichide + (ghide) + + generichide + (ghide) + + generichide + (ghide) + + generichide + (ghide) + + generichide + (ghide) + + generichide + + generichide +
+ header + + header + + header + + header + + header +
+ hls +
+ image + + image + + image + + image + + image + + image + + image + + image + + image +
+ important + + important + + important + + important + + important + + important + + important +
+ inline-font + + inline-font + + inline-font + + inline-font + + inline-font +
+ inline-script + + inline-script + + inline-script + + inline-script + + inline-script +
+ jsinject + + jsinject + + jsinject + + jsinject +
+ jsonprune +
+ match-case + + match-case + + match-case + + match-case + + match-case + + match-case + + match-case + + match-case + + match-case +
+ media + + media + + media + + media + + media + + media + + media + + media + + media +
+ method + + method + + method + + method + + method +
+ mp4 + + mp4 + + mp4 + + mp4 + + mp4 +
+ network +
+ object + + object + + object + + object + + object + + object + + object + + object + + object +
+ object-subrequest + + object-subrequest + + object-subrequest + + object-subrequest + + object-subrequest +
+ other + + other + + other + + other + + other + + other + + other + + other + + other +
+ permissions +
+ ping + + ping + + ping + + ping + + ping + + ping + + ping + + ping + + ping +
+ popup + + popup + + popup + + popup + + popup + + popup + + popup + + popup + + popup +
+ redirect + + redirect + + redirect + + redirect + + redirect + + rewrite + + rewrite +
+ redirect-rule + + redirect-rule + + redirect-rule + + redirect-rule + + redirect-rule +
+ referrerpolicy +
+ removeheader + + removeheader + + removeheader +
+ removeparam + + removeparam + + removeparam + + removeparam + + removeparam +
+ replace + + replace + + replace +
+ script + + script + + script + + script + + script + + script + + script + + script + + script +
+ specifichide + (shide) + + specifichide + (shide) + + specifichide + (shide) + + specifichide + (shide) + + specifichide + (shide) + + specifichide + (shide) + + specifichide + (shide) +
+ stealth + + stealth + + stealth +
+ stylesheet + + stylesheet + + stylesheet + + stylesheet + + stylesheet + + stylesheet + (css) + + stylesheet + (css) + + stylesheet + + stylesheet +
+ subdocument + + subdocument + + subdocument + + subdocument + + subdocument + + subdocument + (frame) + + subdocument + (frame) + + subdocument + + subdocument +
+ third-party + (3p) + + third-party + (3p) + + third-party + (3p) + + third-party + (3p) + + third-party + (3p) + + 3p + (third-party) + + 3p + (third-party) + + third-party + + third-party +
+ to + + to + + to + + to + + to +
+ urlblock + + urlblock + + urlblock + + urlblock + + urlblock +
+ webrtc + + webrtc + + webrtc + + webrtc + + webrtc + + webrtc + + webrtc + + webrtc + + webrtc +
+ websocket + + websocket + + websocket + + websocket + + websocket + + websocket + + websocket + + websocket +
+ xmlhttprequest + (xhr) + + xmlhttprequest + (xhr) + + xmlhttprequest + (xhr) + + xmlhttprequest + (xhr) + + xmlhttprequest + (xhr) + + xhr + (xmlhttprequest) + + xhr + (xmlhttprequest) + + xmlhttprequest + + xmlhttprequest +
+ cname + + cname +
+ popunder + + popunder +
+ strict1p + + strict1p +
+ strict3p + + strict3p +
+ diff --git a/packages/agtree/src/compatibility-tables/wiki/modifiers-compatibility-table.md b/packages/agtree/src/compatibility-tables/wiki/modifiers-compatibility-table.md new file mode 100644 index 000000000..e6ec2b8e5 --- /dev/null +++ b/packages/agtree/src/compatibility-tables/wiki/modifiers-compatibility-table.md @@ -0,0 +1,64 @@ + +# Modifiers Compatibility Table + +This table is generated from the compatibility data. + +| AdGuard | uBlock Origin | Adblock Plus / AdBlock | +| ---------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------- | +| [_](https://adguard.app/kb/general/ad-filtering/create-own-filters/#noop-modifier) | [_](https://github.com/gorhill/uBlock/wiki/Static-filter-syntax#_-aka-noop) | | +| [all](https://adguard.app/kb/general/ad-filtering/create-own-filters/#all-modifier) | [all](https://github.com/gorhill/uBlock/wiki/Static-filter-syntax#all) | | +| [app](https://adguard.app/kb/general/ad-filtering/create-own-filters/#app-modifier) | | | +| [badfilter](https://adguard.app/kb/general/ad-filtering/create-own-filters/#badfilter-modifier) | [badfilter](https://github.com/gorhill/uBlock/wiki/Static-filter-syntax#badfilter) | | +| [content](https://adguard.app/kb/general/ad-filtering/create-own-filters/#content-modifier) | | | +| [cookie](https://adguard.app/kb/general/ad-filtering/create-own-filters/#cookie-modifier) | | | +| [csp](https://adguard.app/kb/general/ad-filtering/create-own-filters/#csp-modifier) | [csp](https://github.com/gorhill/uBlock/wiki/Static-filter-syntax#csp) | [csp](https://help.adblockplus.org/hc/en-us/articles/360062733293-How-to-write-filters#content-security-policies) | +| [denyallow](https://adguard.app/kb/general/ad-filtering/create-own-filters/#denyallow-modifier) | [denyallow](https://github.com/gorhill/uBlock/wiki/Static-filter-syntax#denyallow) | | +| [document](https://adguard.app/kb/general/ad-filtering/create-own-filters/#document-modifier) | [document](https://github.com/gorhill/uBlock/wiki/Static-filter-syntax#document) (doc) | [document](https://help.adblockplus.org/hc/en-us/articles/360062733293-How-to-write-filters#allowlist) | +| [domain](https://adguard.app/kb/general/ad-filtering/create-own-filters/#domain-modifier) (from) | [domain](https://github.com/gorhill/uBlock/wiki/Static-filter-syntax#from) (from) | [domain](https://help.adblockplus.org/hc/en-us/articles/360062733293-How-to-write-filters#domain-restrictions) | +| [elemhide](https://adguard.app/kb/general/ad-filtering/create-own-filters/#elemhide-modifier) (ehide) | [elemhide](https://github.com/gorhill/uBlock/wiki/Static-filter-syntax#elemhide-1) (ehide) | [elemhide](https://help.adblockplus.org/hc/en-us/articles/360062733293-How-to-write-filters#type-options) (ehide) | +| [empty](https://adguard.app/kb/general/ad-filtering/create-own-filters/#empty-modifier) | [empty](https://github.com/gorhill/uBlock/wiki/Static-filter-syntax#empty) | | +| [extension](https://adguard.app/kb/general/ad-filtering/create-own-filters/#extension-modifier) | | | +| [first-party](https://adguard.app/kb/general/ad-filtering/create-own-filters/#third-party-modifier) (1p, ~third-party) | [first-party](https://github.com/gorhill/uBlock/wiki/Static-filter-syntax#1p) (1p, ~third-party) | | +| [font](https://adguard.app/kb/general/ad-filtering/create-own-filters/#font-modifier) | [font](https://help.adblockplus.org/hc/en-us/articles/360062733293#options) | [font](https://help.adblockplus.org/hc/en-us/articles/360062733293#options) | +| [genericblock](https://adguard.app/kb/general/ad-filtering/create-own-filters/#genericblock-modifier) | | [genericblock](https://help.adblockplus.org/hc/en-us/articles/360062733293-How-to-write-filters#type-options) | +| [generichide](https://adguard.app/kb/general/ad-filtering/create-own-filters/#generichide-modifier) (ghide) | [generichide](https://github.com/gorhill/uBlock/wiki/Static-filter-syntax#generichide) (ghide) | [generichide](https://help.adblockplus.org/hc/en-us/articles/360062733293-How-to-write-filters#type-options) | +| [header](https://adguard.app/kb/general/ad-filtering/create-own-filters/#header-modifier) | [header](https://github.com/gorhill/uBlock/wiki/Static-filter-syntax#header) | | +| [hls](https://adguard.app/kb/general/ad-filtering/create-own-filters/#hls-modifier) | | | +| [image](https://adguard.app/kb/general/ad-filtering/create-own-filters/#image-modifier) | [image](https://help.adblockplus.org/hc/en-us/articles/360062733293#options) | [image](https://help.adblockplus.org/hc/en-us/articles/360062733293#options) | +| [important](https://adguard.app/kb/general/ad-filtering/create-own-filters/#important-modifier) | [important](https://github.com/gorhill/uBlock/wiki/Static-filter-syntax#important) | | +| [inline-font](https://adguard.app/kb/general/ad-filtering/create-own-filters/#inline-font-modifier) | [inline-font](https://github.com/gorhill/uBlock/wiki/Static-filter-syntax#inline-font) | | +| [inline-script](https://adguard.app/kb/general/ad-filtering/create-own-filters/#inline-script-modifier) | [inline-script](https://github.com/gorhill/uBlock/wiki/Static-filter-syntax#inline-script) | | +| [jsinject](https://adguard.app/kb/general/ad-filtering/create-own-filters/#jsinject-modifier) | | | +| [jsonprune](https://adguard.app/kb/general/ad-filtering/create-own-filters/#jsonprune-modifier) | | | +| [match-case](https://adguard.app/kb/general/ad-filtering/create-own-filters/#match-case-modifier) | [match-case](https://github.com/gorhill/uBlock/wiki/Static-filter-syntax#match-case) | [match-case](https://help.adblockplus.org/hc/en-us/articles/360062733293-How-to-write-filters#type-options) | +| [media](https://adguard.app/kb/general/ad-filtering/create-own-filters/#media-modifier) | [media](https://help.adblockplus.org/hc/en-us/articles/360062733293#options) | [media](https://help.adblockplus.org/hc/en-us/articles/360062733293#options) | +| [method](https://adguard.app/kb/general/ad-filtering/create-own-filters/#method-modifier) | [method](https://github.com/gorhill/uBlock/wiki/Static-filter-syntax#method) | | +| [mp4](https://adguard.app/kb/general/ad-filtering/create-own-filters/#mp4-modifier) | [mp4](https://github.com/gorhill/uBlock/wiki/Static-filter-syntax#mp4) | | +| [network](https://adguard.app/kb/general/ad-filtering/create-own-filters/#network-modifier) | | | +| [object](https://adguard.app/kb/general/ad-filtering/create-own-filters/#object-modifier) | [object](https://help.adblockplus.org/hc/en-us/articles/360062733293-How-to-write-filters#type-options) | [object](https://help.adblockplus.org/hc/en-us/articles/360062733293-How-to-write-filters#type-options) | +| [object-subrequest](https://adguard.app/kb/general/ad-filtering/create-own-filters/#object-subrequest-modifier) | | | +| [other](https://adguard.app/kb/general/ad-filtering/create-own-filters/#other-modifier) | [other](https://help.adblockplus.org/hc/en-us/articles/360062733293-How-to-write-filters#type-options) | [other](https://help.adblockplus.org/hc/en-us/articles/360062733293-How-to-write-filters#type-options) | +| [permissions](https://adguard.app/kb/general/ad-filtering/create-own-filters/#permissions-modifier) | | | +| [ping](https://adguard.app/kb/general/ad-filtering/create-own-filters/#ping-modifier) | [ping](https://help.adblockplus.org/hc/en-us/articles/360062733293-How-to-write-filters#type-options) | [ping](https://help.adblockplus.org/hc/en-us/articles/360062733293-How-to-write-filters#type-options) | +| [popup](https://adguard.app/kb/general/ad-filtering/create-own-filters/#popup-modifier) | [popup](https://help.adblockplus.org/hc/en-us/articles/360062733293-How-to-write-filters#type-options) | [popup](https://help.adblockplus.org/hc/en-us/articles/360062733293-How-to-write-filters#type-options) | +| [redirect](https://adguard.app/kb/general/ad-filtering/create-own-filters/#redirect-modifier) | [redirect](https://github.com/gorhill/uBlock/wiki/Static-filter-syntax#redirect) | [rewrite](https://help.adblockplus.org/hc/en-us/articles/360062733293#rewrite) | +| [redirect-rule](https://adguard.app/kb/general/ad-filtering/create-own-filters/#redirect-rule-modifier) | [redirect-rule](https://github.com/gorhill/uBlock/wiki/Static-filter-syntax#redirect-rule) | | +| [referrerpolicy](https://adguard.app/kb/general/ad-filtering/create-own-filters/#referrerpolicy-modifier) | | | +| [removeheader](https://adguard.app/kb/general/ad-filtering/create-own-filters/#removeheader-modifier) | | | +| [removeparam](https://adguard.app/kb/general/ad-filtering/create-own-filters/#removeparam-modifier) | [removeparam](https://github.com/gorhill/uBlock/wiki/Static-filter-syntax#removeparam) | | +| [replace](https://adguard.app/kb/general/ad-filtering/create-own-filters/#replace-modifier) | [replace](https://github.com/gorhill/uBlock/wiki/Static-filter-syntax#replace) | | +| [script](https://adguard.app/kb/general/ad-filtering/create-own-filters/#script-modifier) | [script](https://help.adblockplus.org/hc/en-us/articles/360062733293#options) | [script](https://help.adblockplus.org/hc/en-us/articles/360062733293-How-to-write-filters#type-options) | +| [specifichide](https://adguard.app/kb/general/ad-filtering/create-own-filters/#specifichide-modifier) (shide) | [specifichide](https://github.com/gorhill/uBlock/wiki/Static-filter-syntax#specifichide) (shide) | | +| [stealth](https://adguard.app/kb/general/ad-filtering/create-own-filters/#stealth-modifier) | | | +| [stylesheet](https://adguard.app/kb/general/ad-filtering/create-own-filters/#stylesheet-modifier) | [stylesheet](https://github.com/gorhill/uBlock/wiki/Static-filter-syntax#css) (css) | [stylesheet](https://help.adblockplus.org/hc/en-us/articles/360062733293-How-to-write-filters#type-options) | +| [subdocument](https://adguard.app/kb/general/ad-filtering/create-own-filters/#subdocument-modifier) | [subdocument](https://github.com/gorhill/uBlock/wiki/Static-filter-syntax#frame) (frame) | [subdocument](https://help.adblockplus.org/hc/en-us/articles/360062733293-How-to-write-filters#type-options) | +| [third-party](https://adguard.app/kb/general/ad-filtering/create-own-filters/#third-party-modifier) (3p) | [3p](https://github.com/gorhill/uBlock/wiki/Static-filter-syntax#3p) (third-party) | [third-party](https://help.adblockplus.org/hc/en-us/articles/360062733293#party-requests) | +| [to](https://adguard.com/kb/general/ad-filtering/create-own-filters/#to-modifier) | [to](https://github.com/gorhill/uBlock/wiki/Static-filter-syntax#to) | | +| [urlblock](https://adguard.app/kb/general/ad-filtering/create-own-filters/#urlblock-modifier) | | | +| [webrtc](https://adguard.app/kb/general/ad-filtering/create-own-filters/#webrtc-modifier) | [webrtc](https://github.com/gorhill/uBlock/wiki/Static-filter-syntax) | [webrtc](https://help.adblockplus.org/hc/en-us/articles/360062733293-How-to-write-filters#type-options) | +| [websocket](https://adguard.app/kb/general/ad-filtering/create-own-filters/#websocket-modifier) | [websocket](https://help.adblockplus.org/hc/en-us/articles/360062733293-How-to-write-filters#type-options) | [websocket](https://help.adblockplus.org/hc/en-us/articles/360062733293-How-to-write-filters#type-options) | +| [xmlhttprequest](https://adguard.app/kb/general/ad-filtering/create-own-filters/#xmlhttprequest-modifier) (xhr) | [xhr](https://github.com/gorhill/uBlock/wiki/Static-filter-syntax#xhr) (xmlhttprequest) | [xmlhttprequest](https://help.adblockplus.org/hc/en-us/articles/360062733293-How-to-write-filters#type-options) | +| | [cname](https://github.com/gorhill/uBlock/wiki/Static-filter-syntax#cname) | | +| | [popunder](https://github.com/gorhill/uBlock/wiki/Static-filter-syntax#popunder) | | +| | [strict1p](https://github.com/gorhill/uBlock/wiki/Static-filter-syntax#strict1p) | | +| | [strict3p](https://github.com/gorhill/uBlock/wiki/Static-filter-syntax#strict3p) | | diff --git a/packages/agtree/src/compatibility-tables/wiki/redirects-compatibility-table.md b/packages/agtree/src/compatibility-tables/wiki/redirects-compatibility-table.md new file mode 100644 index 000000000..6a98a42b2 --- /dev/null +++ b/packages/agtree/src/compatibility-tables/wiki/redirects-compatibility-table.md @@ -0,0 +1,60 @@ + +# Redirects Compatibility Table + +This table is generated from the compatibility data. + +| AdGuard | uBlock Origin | Adblock Plus / AdBlock | +| --------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------- | +| [1x1-transparent.gif](https://github.com/AdguardTeam/Scriptlets/blob/master/wiki/about-redirects.md#1x1-transparent.gif) (1x1.gif, 1x1-transparent-gif) | [1x1.gif](https://github.com/gorhill/uBlock/wiki/Resources-Library#available-empty-redirect-resources) | [1x1-transparent-gif](https://help.adblockplus.org/hc/en-us/articles/360062733293#rewrite) | +| [2x2-transparent.png](https://github.com/AdguardTeam/Scriptlets/blob/master/wiki/about-redirects.md#2x2-transparent.png) (2x2.png, 2x2-transparent-png) | [2x2.png](https://github.com/gorhill/uBlock/wiki/Resources-Library#available-empty-redirect-resources) | [2x2-transparent-png](https://help.adblockplus.org/hc/en-us/articles/360062733293#rewrite) | +| [32x32-transparent.png](https://github.com/AdguardTeam/Scriptlets/blob/master/wiki/about-redirects.md#32x32-transparent.png) (32x32.png, 32x32-transparent-png) | [32x32.png](https://github.com/gorhill/uBlock/wiki/Resources-Library#available-empty-redirect-resources) | [32x32-transparent-png](https://help.adblockplus.org/hc/en-us/articles/360062733293#rewrite) | +| [3x2-transparent.png](https://github.com/AdguardTeam/Scriptlets/blob/master/wiki/about-redirects.md#3x2-transparent.png) (3x2.png, 3x2-transparent-png) | [3x2.png](https://github.com/gorhill/uBlock/wiki/Resources-Library#available-empty-redirect-resources) | [3x2-transparent-png](https://help.adblockplus.org/hc/en-us/articles/360062733293#rewrite) | +| [amazon-apstag](https://github.com/AdguardTeam/Scriptlets/blob/master/wiki/about-redirects.md#amazon-apstag) (ubo-amazon_apstag.js, amazon_apstag.js) | [amazon_apstag.js](https://github.com/gorhill/uBlock/wiki/Resources-Library#amazon_apstagjs-) | | +| ati-smarttag | | | +| click2load.html (click2load.html, ubo-click2load.html) | click2load.html | | +| didomi-loader | | | +| empty | empty | | +| fingerprintjs2 (fingerprint2.js) | fingerprint2.js | | +| fingerprintjs3 (fingerprint3.js) | fingerprint3.js | | +| gemius | | | +| google-analytics (ubo-google-analytics_analytics.js, google-analytics_analytics.js, googletagmanager-gtm, ubo-googletagmanager_gtm.js, googletagmanager_gtm.js) | google-analytics_analytics.js | | +| google-analytics-ga (ubo-google-analytics_ga.js, google-analytics_ga.js) | google-analytics_ga.js | | +| google-ima3 (ubo-google-ima.js, google-ima.js) | google-ima.js | | +| googlesyndication-adsbygoogle (ubo-googlesyndication_adsbygoogle.js, googlesyndication_adsbygoogle.js) | googlesyndication_adsbygoogle.js | | +| googletagservices-gpt (ubo-googletagservices_gpt.js, googletagservices_gpt.js) | googletagservices_gpt.js | | +| matomo | | | +| metrika-yandex-tag | | | +| metrika-yandex-watch | | | +| naver-wcslog | | | +| no-protected-audience | | | +| no-topics | | | +| noeval (noeval.js, silent-noeval.js, ubo-noeval.js, ubo-silent-noeval.js, ubo-noeval, ubo-silent-noeval) | noeval.js | | +| noopcss (noop.css, blank-css) | noop.css | blank-css | +| noopframe (noop.html, blank-html) | noop.html | blank-html | +| noopjs (noop.js, blank-js) | noop.js | blank-js | +| noopjson (noop.json) | noop.json | | +| noopmp3-0.1s (noop-0.1s.mp3, blank-mp3) | noop-0.1s.mp3 | blank-mp3 | +| noopmp4-1s (noop-1s.mp4, blank-mp4) | noop-1s.mp4 | blank-mp4 | +| nooptext (noop.txt, blank-text) | noop.txt | blank-text | +| noopvast-2.0 | | | +| noopvast-3.0 | | | +| noopvast-4.0 | | | +| noopvmap-1.0 (noop-vmap1.0.xml) | noop-vmap1.0.xml | | +| nowebrtc (nowebrtc.js, ubo-nowebrtc.js, ubo-nowebrtc) | nowebrtc.js | | +| pardot-1.0 | | | +| prebid | | | +| prebid-ads (prebid-ads.js) | prebid-ads.js | | +| prevent-bab (nobab.js) | nobab.js | | +| prevent-bab2 (nobab2.js) | nobab2.js | | +| prevent-fab-3.2.0 (nofab.js) | nofab.js | | +| prevent-popads-net (popads.js) | popads.js | | +| scorecardresearch-beacon (scorecardresearch_beacon.js) | scorecardresearch_beacon.js | | +| set-popads-dummy (popads-dummy.js) | popads-dummy.js | | +| | amazon_ads.js | | +| | ampproject_v0.js | | +| | chartbeat.js | | +| | google-analytics_cx_api.js | | +| | google-analytics_inpage_linkid.js | | +| | hd-main.js | | +| | noop-0.5s.mp3 | | +| | outbrain-widget.js | | diff --git a/packages/agtree/src/compatibility-tables/wiki/scriptlets-compatibility-table.md b/packages/agtree/src/compatibility-tables/wiki/scriptlets-compatibility-table.md new file mode 100644 index 000000000..9e6eab462 --- /dev/null +++ b/packages/agtree/src/compatibility-tables/wiki/scriptlets-compatibility-table.md @@ -0,0 +1,94 @@ + +# Scriptlets Compatibility Table + +This table is generated from the compatibility data. + +| AdGuard | uBlock Origin | Adblock Plus / AdBlock | +| ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------- | +| [abort-current-inline-script](https://github.com/AdguardTeam/Scriptlets/blob/master/wiki/about-scriptlets.md#abort-current-inline-script) (abort-current-script.js, ubo-abort-current-script.js, acs.js, ubo-acs.js, ubo-abort-current-script, ubo-acs, abort-current-inline-script.js, ubo-abort-current-inline-script.js, acis.js, ubo-acis.js, ubo-abort-current-inline-script, ubo-acis, abp-abort-current-inline-script) | [abort-current-script.js](https://github.com/gorhill/uBlock/wiki/Resources-Library#abort-current-scriptjs-) (acs.js, abort-current-inline-script.js, acis.js) | [abort-current-inline-script](https://help.adblockplus.org/hc/en-us/articles/1500002338501-Snippet-filters-tutorial#snippets-ref) | +| [abort-on-property-read](https://github.com/AdguardTeam/Scriptlets/blob/master/wiki/about-scriptlets.md#abort-on-property-read) (abort-on-property-read.js, ubo-abort-on-property-read.js, aopr.js, ubo-aopr.js, ubo-abort-on-property-read, ubo-aopr, abp-abort-on-property-read) | [abort-on-property-read.js](https://github.com/gorhill/uBlock/wiki/Resources-Library#abort-on-property-readjs-) (aopr.js) | [abort-on-property-read](https://help.adblockplus.org/hc/en-us/articles/1500002338501-Snippet-filters-tutorial#snippets-ref) | +| [abort-on-property-write](https://github.com/AdguardTeam/Scriptlets/blob/master/wiki/about-scriptlets.md#abort-on-property-write) (abort-on-property-write.js, ubo-abort-on-property-write.js, aopw.js, ubo-aopw.js, ubo-abort-on-property-write, ubo-aopw, abp-abort-on-property-write) | [abort-on-property-write.js](https://github.com/gorhill/uBlock/wiki/Resources-Library#abort-on-property-writejs-) (aopw.js) | [abort-on-property-write](https://help.adblockplus.org/hc/en-us/articles/1500002338501-Snippet-filters-tutorial#snippets-ref) | +| [abort-on-stack-trace](https://github.com/AdguardTeam/Scriptlets/blob/master/wiki/about-scriptlets.md#abort-on-stack-trace) (abort-on-stack-trace.js, ubo-abort-on-stack-trace.js, aost.js, ubo-aost.js, ubo-abort-on-stack-trace, ubo-aost, abp-abort-on-stack-trace) | [abort-on-stack-trace.js](https://github.com/gorhill/uBlock/wiki/Resources-Library#abort-on-stack-tracejs-) (aost.js) | | +| [adjust-setInterval](https://github.com/AdguardTeam/Scriptlets/blob/master/wiki/about-scriptlets.md#adjust-setInterval) (nano-setInterval-booster.js, ubo-nano-setInterval-booster.js, nano-sib.js, ubo-nano-sib.js, adjust-setInterval.js, ubo-adjust-setInterval.js, ubo-nano-setInterval-booster, ubo-nano-sib, ubo-adjust-setInterval) | [adjust-setInterval.js](https://github.com/gorhill/uBlock/wiki/Resources-Library#adjust-setIntervaljs-) (nano-setInterval-booster.js, nano-sib.js) | | +| [adjust-setTimeout](https://github.com/AdguardTeam/Scriptlets/blob/master/wiki/about-scriptlets.md#adjust-setTimeout) (adjust-setTimeout.js, ubo-adjust-setTimeout.js, nano-setTimeout-booster.js, ubo-nano-setTimeout-booster.js, nano-stb.js, ubo-nano-stb.js, ubo-adjust-setTimeout, ubo-nano-setTimeout-booster, ubo-nano-stb) | [adjust-setTimeout.js](https://github.com/gorhill/uBlock/wiki/Resources-Library#adjust-setTimeoutjs-) (nano-setTimeout-booster.js, nano-stb.js) | | +| [amazon-apstag](https://github.com/AdguardTeam/Scriptlets/blob/master/wiki/about-scriptlets.md#amazon-apstag) (ubo-amazon_apstag.js, amazon_apstag.js) | | | +| [call-nothrow](https://github.com/AdguardTeam/Scriptlets/blob/master/wiki/about-scriptlets.md#call-nothrow) (call-nothrow.js, ubo-call-nothrow.js, ubo-call-nothrow) | [call-nothrow.js](https://github.com/gorhill/uBlock/wiki/Resources-Library#call-nothrowjs-) | | +| [close-window](https://github.com/AdguardTeam/Scriptlets/blob/master/wiki/about-scriptlets.md#close-window) (window-close-if.js, ubo-window-close-if.js, ubo-window-close-if, close-window.js, ubo-close-window.js, ubo-close-window) | [close-window.js](https://github.com/gorhill/uBlock/wiki/Resources-Library#close-windowjs-) (window-close-if.js) | | +| [debug-current-inline-script](https://github.com/AdguardTeam/Scriptlets/blob/master/wiki/about-scriptlets.md#debug-current-inline-script) | | | +| [debug-on-property-read](https://github.com/AdguardTeam/Scriptlets/blob/master/wiki/about-scriptlets.md#debug-on-property-read) | | | +| [debug-on-property-write](https://github.com/AdguardTeam/Scriptlets/blob/master/wiki/about-scriptlets.md#debug-on-property-write) | | | +| [didomi-loader](https://github.com/AdguardTeam/Scriptlets/blob/master/wiki/about-scriptlets.md#didomi-loader) | | | +| [dir-string](https://github.com/AdguardTeam/Scriptlets/blob/master/wiki/about-scriptlets.md#dir-string) | | | +| [disable-newtab-links](https://github.com/AdguardTeam/Scriptlets/blob/master/wiki/about-scriptlets.md#disable-newtab-links) (disable-newtab-links.js, ubo-disable-newtab-links.js, ubo-disable-newtab-links) | [disable-newtab-links.js](https://github.com/gorhill/uBlock/wiki/Resources-Library#disable-newtab-linksjs-) | | +| [evaldata-prune](https://github.com/AdguardTeam/Scriptlets/blob/master/wiki/about-scriptlets.md#evaldata-prune) (evaldata-prune.js, ubo-evaldata-prune.js, ubo-evaldata-prune) | [evaldata-prune.js](https://github.com/gorhill/uBlock/wiki/Resources-Library#evaldata-prunejs-) | | +| [fingerprintjs2](https://github.com/AdguardTeam/Scriptlets/blob/master/wiki/about-scriptlets.md#fingerprintjs2) (ubo-fingerprint2.js, fingerprint2.js) | | | +| [fingerprintjs3](https://github.com/AdguardTeam/Scriptlets/blob/master/wiki/about-scriptlets.md#fingerprintjs3) (ubo-fingerprint3.js, fingerprint3.js) | | | +| [gemius](https://github.com/AdguardTeam/Scriptlets/blob/master/wiki/about-scriptlets.md#gemius) | | | +| [google-analytics](https://github.com/AdguardTeam/Scriptlets/blob/master/wiki/about-scriptlets.md#google-analytics) (ubo-google-analytics_analytics.js, google-analytics_analytics.js, googletagmanager-gtm, ubo-googletagmanager_gtm.js, googletagmanager_gtm.js) | | | +| [google-analytics-ga](https://github.com/AdguardTeam/Scriptlets/blob/master/wiki/about-scriptlets.md#google-analytics-ga) (ubo-google-analytics_ga.js, google-analytics_ga.js) | | | +| [google-ima3](https://github.com/AdguardTeam/Scriptlets/blob/master/wiki/about-scriptlets.md#google-ima3) (ubo-google-ima.js, google-ima.js) | | | +| [googlesyndication-adsbygoogle](https://github.com/AdguardTeam/Scriptlets/blob/master/wiki/about-scriptlets.md#googlesyndication-adsbygoogle) (ubo-googlesyndication_adsbygoogle.js, googlesyndication_adsbygoogle.js) | | | +| [googletagservices-gpt](https://github.com/AdguardTeam/Scriptlets/blob/master/wiki/about-scriptlets.md#googletagservices-gpt) (ubo-googletagservices_gpt.js, googletagservices_gpt.js) | | | +| [hide-in-shadow-dom](https://github.com/AdguardTeam/Scriptlets/blob/master/wiki/about-scriptlets.md#hide-in-shadow-dom) | | | +| [href-sanitizer](https://github.com/AdguardTeam/Scriptlets/blob/master/wiki/about-scriptlets.md#href-sanitizer) (href-sanitizer.js, ubo-href-sanitizer.js, ubo-href-sanitizer) | [href-sanitizer.js](https://github.com/gorhill/uBlock/wiki/Resources-Library#href-sanitizerjs-) | | +| [inject-css-in-shadow-dom](https://github.com/AdguardTeam/Scriptlets/blob/master/wiki/about-scriptlets.md#inject-css-in-shadow-dom) | | | +| [json-prune](https://github.com/AdguardTeam/Scriptlets/blob/master/wiki/about-scriptlets.md#json-prune) (json-prune.js, ubo-json-prune.js, ubo-json-prune, abp-json-prune) | [json-prune.js](https://github.com/gorhill/uBlock/wiki/Resources-Library#json-prunejs-) | [json-prune](https://help.adblockplus.org/hc/en-us/articles/1500002338501-Snippet-filters-tutorial#snippets-ref) | +| [json-prune-fetch-response](https://github.com/AdguardTeam/Scriptlets/blob/master/wiki/about-scriptlets.md#json-prune-fetch-response) (json-prune-fetch-response.js, ubo-json-prune-fetch-response.js, ubo-json-prune-fetch-response) | [json-prune-fetch-response.js](https://github.com/gorhill/uBlock/wiki/Resources-Library#json-prune-fetch-responsejs-) | | +| [json-prune-xhr-response](https://github.com/AdguardTeam/Scriptlets/blob/master/wiki/about-scriptlets.md#json-prune-xhr-response) (json-prune-xhr-response.js, ubo-json-prune-xhr-response.js, ubo-json-prune-xhr-response) | [json-prune-xhr-response.js](https://github.com/gorhill/uBlock/wiki/Resources-Library#json-prune-xhr-responsejs-) | | +| [log](https://github.com/AdguardTeam/Scriptlets/blob/master/wiki/about-scriptlets.md#log) (abp-log) | | | +| [log-addEventListener](https://github.com/AdguardTeam/Scriptlets/blob/master/wiki/about-scriptlets.md#log-addEventListener) (addEventListener-logger.js, ubo-addEventListener-logger.js, aell.js, ubo-aell.js, ubo-addEventListener-logger, ubo-aell) | | | +| [log-eval](https://github.com/AdguardTeam/Scriptlets/blob/master/wiki/about-scriptlets.md#log-eval) | | | +| [log-on-stack-trace](https://github.com/AdguardTeam/Scriptlets/blob/master/wiki/about-scriptlets.md#log-on-stack-trace) | | | +| [m3u-prune](https://github.com/AdguardTeam/Scriptlets/blob/master/wiki/about-scriptlets.md#m3u-prune) (m3u-prune.js, ubo-m3u-prune.js, ubo-m3u-prune) | [m3u-prune.js](https://github.com/gorhill/uBlock/wiki/Resources-Library#m3u-prunejs-) | | +| [matomo](https://github.com/AdguardTeam/Scriptlets/blob/master/wiki/about-scriptlets.md#matomo) | | | +| [metrika-yandex-tag](https://github.com/AdguardTeam/Scriptlets/blob/master/wiki/about-scriptlets.md#metrika-yandex-tag) | | | +| [metrika-yandex-watch](https://github.com/AdguardTeam/Scriptlets/blob/master/wiki/about-scriptlets.md#metrika-yandex-watch) | | | +| [naver-wcslog](https://github.com/AdguardTeam/Scriptlets/blob/master/wiki/about-scriptlets.md#naver-wcslog) | | | +| [no-protected-audience](https://github.com/AdguardTeam/Scriptlets/blob/master/wiki/about-scriptlets.md#no-protected-audience) | | | +| [no-topics](https://github.com/AdguardTeam/Scriptlets/blob/master/wiki/about-scriptlets.md#no-topics) | | | +| [noeval](https://github.com/AdguardTeam/Scriptlets/blob/master/wiki/about-scriptlets.md#noeval) (noeval.js, silent-noeval.js, ubo-noeval.js, ubo-silent-noeval.js, ubo-noeval, ubo-silent-noeval) | | | +| [nowebrtc](https://github.com/AdguardTeam/Scriptlets/blob/master/wiki/about-scriptlets.md#nowebrtc) (nowebrtc.js, ubo-nowebrtc.js, ubo-nowebrtc) | [nowebrtc.js](https://github.com/gorhill/uBlock/wiki/Resources-Library#nowebrtcjs-) | | +| [pardot-1.0](https://github.com/AdguardTeam/Scriptlets/blob/master/wiki/about-scriptlets.md#pardot-1.0) | | | +| [prebid](https://github.com/AdguardTeam/Scriptlets/blob/master/wiki/about-scriptlets.md#prebid) | | | +| [prevent-addEventListener](https://github.com/AdguardTeam/Scriptlets/blob/master/wiki/about-scriptlets.md#prevent-addEventListener) (addEventListener-defuser.js, ubo-addEventListener-defuser.js, aeld.js, ubo-aeld.js, ubo-addEventListener-defuser, ubo-aeld, abp-prevent-listener) | [addEventListener-defuser.js](https://github.com/gorhill/uBlock/wiki/Resources-Library#addEventListener-defuserjs-) (aeld.js, prevent-addEventListener.js) | [prevent-listener](https://help.adblockplus.org/hc/en-us/articles/1500002338501-Snippet-filters-tutorial#snippets-ref) | +| [prevent-adfly](https://github.com/AdguardTeam/Scriptlets/blob/master/wiki/about-scriptlets.md#prevent-adfly) (adfly-defuser.js, ubo-adfly-defuser.js, ubo-adfly-defuser) | | | +| [prevent-bab](https://github.com/AdguardTeam/Scriptlets/blob/master/wiki/about-scriptlets.md#prevent-bab) | | | +| [prevent-element-src-loading](https://github.com/AdguardTeam/Scriptlets/blob/master/wiki/about-scriptlets.md#prevent-element-src-loading) | | | +| [prevent-eval-if](https://github.com/AdguardTeam/Scriptlets/blob/master/wiki/about-scriptlets.md#prevent-eval-if) (noeval-if.js, ubo-noeval-if.js, ubo-noeval-if) | [noeval-if.js](https://github.com/gorhill/uBlock/wiki/Resources-Library#noeval-ifjs-) (prevent-eval-if.js) | | +| [prevent-fab-3.2.0](https://github.com/AdguardTeam/Scriptlets/blob/master/wiki/about-scriptlets.md#prevent-fab-3.2.0) (nofab.js, ubo-nofab.js, fuckadblock.js-3.2.0, ubo-fuckadblock.js-3.2.0, ubo-nofab) | | | +| [prevent-fetch](https://github.com/AdguardTeam/Scriptlets/blob/master/wiki/about-scriptlets.md#prevent-fetch) (prevent-fetch.js, no-fetch-if.js, ubo-no-fetch-if.js, ubo-no-fetch-if) | [prevent-fetch.js](https://github.com/gorhill/uBlock/wiki/Resources-Library#prevent-fetchjs-) (no-fetch-if.js) | | +| [prevent-popads-net](https://github.com/AdguardTeam/Scriptlets/blob/master/wiki/about-scriptlets.md#prevent-popads-net) (popads.net.js, ubo-popads.net.js, ubo-popads.net) | | | +| [prevent-refresh](https://github.com/AdguardTeam/Scriptlets/blob/master/wiki/about-scriptlets.md#prevent-refresh) (prevent-refresh.js, refresh-defuser.js, refresh-defuser, ubo-prevent-refresh.js, ubo-prevent-refresh, ubo-refresh-defuser.js, ubo-refresh-defuser) | [prevent-refresh.js](https://github.com/gorhill/uBlock/wiki/Resources-Library#prevent-refreshjs-) (refresh-defuser.js) | | +| [prevent-requestAnimationFrame](https://github.com/AdguardTeam/Scriptlets/blob/master/wiki/about-scriptlets.md#prevent-requestAnimationFrame) (no-requestAnimationFrame-if.js, ubo-no-requestAnimationFrame-if.js, norafif.js, ubo-norafif.js, ubo-no-requestAnimationFrame-if, ubo-norafif) | [no-requestAnimationFrame-if.js](https://github.com/gorhill/uBlock/wiki/Resources-Library#no-requestAnimationFrame-ifjs-) (norafif.js, prevent-requestAnimationFrame.js) | | +| [prevent-setInterval](https://github.com/AdguardTeam/Scriptlets/blob/master/wiki/about-scriptlets.md#prevent-setInterval) (no-setInterval-if.js, ubo-no-setInterval-if.js, setInterval-defuser.js, ubo-setInterval-defuser.js, nosiif.js, ubo-nosiif.js, sid.js, ubo-sid.js, ubo-no-setInterval-if, ubo-setInterval-defuser, ubo-nosiif, ubo-sid) | [no-setInterval-if.js](https://github.com/gorhill/uBlock/wiki/Resources-Library#no-setInterval-ifjs-) (nosiif.js, prevent-setInterval.js, setInterval-defuser.js) | | +| [prevent-setTimeout](https://github.com/AdguardTeam/Scriptlets/blob/master/wiki/about-scriptlets.md#prevent-setTimeout) (no-setTimeout-if.js, ubo-no-setTimeout-if.js, nostif.js, ubo-nostif.js, ubo-no-setTimeout-if, ubo-nostif, setTimeout-defuser.js, ubo-setTimeout-defuser.js, ubo-setTimeout-defuser, std.js, ubo-std.js, ubo-std) | [no-setTimeout-if.js](https://github.com/gorhill/uBlock/wiki/Resources-Library#no-setTimeout-ifjs-) (nostif.js, prevent-setTimeout.js, setTimeout-defuser.js) | | +| [prevent-window-open](https://github.com/AdguardTeam/Scriptlets/blob/master/wiki/about-scriptlets.md#prevent-window-open) (window.open-defuser.js, ubo-window.open-defuser.js, ubo-window.open-defuser, nowoif.js, ubo-nowoif.js, ubo-nowoif, no-window-open-if.js, ubo-no-window-open-if.js, ubo-no-window-open-if) | [no-window-open-if.js](https://github.com/gorhill/uBlock/wiki/Resources-Library#no-window-open-ifjs-) (nowoif.js, prevent-window-open.js, window.open-defuser.js) | | +| [prevent-xhr](https://github.com/AdguardTeam/Scriptlets/blob/master/wiki/about-scriptlets.md#prevent-xhr) (no-xhr-if.js, ubo-no-xhr-if.js, ubo-no-xhr-if) | [no-xhr-if.js](https://github.com/gorhill/uBlock/wiki/Resources-Library#no-xhr-ifjs-) (prevent-xhr.js) | | +| [remove-attr](https://github.com/AdguardTeam/Scriptlets/blob/master/wiki/about-scriptlets.md#remove-attr) (remove-attr.js, ubo-remove-attr.js, ra.js, ubo-ra.js, ubo-remove-attr, ubo-ra) | [remove-attr.js](https://github.com/gorhill/uBlock/wiki/Resources-Library#remove-attrjs-) (ra.js) | | +| [remove-class](https://github.com/AdguardTeam/Scriptlets/blob/master/wiki/about-scriptlets.md#remove-class) (remove-class.js, ubo-remove-class.js, rc.js, ubo-rc.js, ubo-remove-class, ubo-rc) | [remove-class.js](https://github.com/gorhill/uBlock/wiki/Resources-Library#remove-classjs-) (rc.js) | | +| [remove-cookie](https://github.com/AdguardTeam/Scriptlets/blob/master/wiki/about-scriptlets.md#remove-cookie) (cookie-remover.js, ubo-cookie-remover.js, ubo-cookie-remover, remove-cookie.js, ubo-remove-cookie.js, ubo-remove-cookie, abp-cookie-remover) | [remove-cookie.js](https://github.com/gorhill/uBlock/wiki/Resources-Library#remove-cookiejs-) (cookie-remover.js) | [cookie-remover](https://help.adblockplus.org/hc/en-us/articles/1500002338501-Snippet-filters-tutorial#snippets-ref) | +| [remove-in-shadow-dom](https://github.com/AdguardTeam/Scriptlets/blob/master/wiki/about-scriptlets.md#remove-in-shadow-dom) | | | +| [remove-node-text](https://github.com/AdguardTeam/Scriptlets/blob/master/wiki/about-scriptlets.md#remove-node-text) (remove-node-text.js, ubo-remove-node-text.js, rmnt.js, ubo-rmnt.js, ubo-remove-node-text, ubo-rmnt) | [remove-node-text.js](https://github.com/gorhill/uBlock/wiki/Resources-Library#remove-node-textjs-) (rmnt.js) | | +| [scorecardresearch-beacon](https://github.com/AdguardTeam/Scriptlets/blob/master/wiki/about-scriptlets.md#scorecardresearch-beacon) (ubo-scorecardresearch_beacon.js, scorecardresearch_beacon.js) | | | +| [set-attr](https://github.com/AdguardTeam/Scriptlets/blob/master/wiki/about-scriptlets.md#set-attr) (set-attr.js, ubo-set-attr.js, ubo-set-attr) | [set-attr.js](https://github.com/gorhill/uBlock/wiki/Resources-Library#set-attrjs-) | | +| [set-constant](https://github.com/AdguardTeam/Scriptlets/blob/master/wiki/about-scriptlets.md#set-constant) (set-constant.js, ubo-set-constant.js, set.js, ubo-set.js, ubo-set-constant, ubo-set) | [set-constant.js](https://github.com/gorhill/uBlock/wiki/Resources-Library#set-constantjs-) (set.js) | [override-property-read](https://help.adblockplus.org/hc/en-us/articles/1500002338501-Snippet-filters-tutorial#snippets-ref) | +| [set-cookie](https://github.com/AdguardTeam/Scriptlets/blob/master/wiki/about-scriptlets.md#set-cookie) (set-cookie.js, ubo-set-cookie.js, ubo-set-cookie) | [set-cookie.js](https://github.com/gorhill/uBlock/wiki/Resources-Library#set-cookiejs-) | | +| [set-cookie-reload](https://github.com/AdguardTeam/Scriptlets/blob/master/wiki/about-scriptlets.md#set-cookie-reload) (set-cookie-reload.js, ubo-set-cookie-reload.js, ubo-set-cookie-reload) | [set-cookie-reload.js](https://github.com/gorhill/uBlock/wiki/Resources-Library#set-cookie-reloadjs-) | | +| [set-local-storage-item](https://github.com/AdguardTeam/Scriptlets/blob/master/wiki/about-scriptlets.md#set-local-storage-item) (set-local-storage-item.js, ubo-set-local-storage-item.js, ubo-set-local-storage-item) | [set-local-storage-item.js](https://github.com/gorhill/uBlock/wiki/Resources-Library#set-local-storage-itemjs-) | | +| [set-popads-dummy](https://github.com/AdguardTeam/Scriptlets/blob/master/wiki/about-scriptlets.md#set-popads-dummy) (popads-dummy.js, ubo-popads-dummy.js, ubo-popads-dummy) | | | +| [set-session-storage-item](https://github.com/AdguardTeam/Scriptlets/blob/master/wiki/about-scriptlets.md#set-session-storage-item) (set-session-storage-item.js, ubo-set-session-storage-item.js, ubo-set-session-storage-item) | [set-session-storage-item.js](https://github.com/gorhill/uBlock/wiki/Resources-Library#set-session-storage-itemjs-) | | +| [spoof-css](https://github.com/AdguardTeam/Scriptlets/blob/master/wiki/about-scriptlets.md#spoof-css) (spoof-css.js, ubo-spoof-css.js, ubo-spoof-css) | [spoof-css.js](https://github.com/gorhill/uBlock/wiki/Resources-Library#spoof-cssjs-) | | +| trusted-click-element | | | +| trusted-create-element | | | +| trusted-dispatch-event | | | +| trusted-prune-inbound-object | | | +| trusted-replace-fetch-response | | | +| trusted-replace-node-text | | | +| trusted-replace-xhr-response | | | +| trusted-set-attr | | | +| trusted-set-constant | | | +| trusted-set-cookie | | | +| trusted-set-cookie-reload | | | +| trusted-set-local-storage-item | | | +| trusted-suppress-native-method | | | +| [xml-prune](https://github.com/AdguardTeam/Scriptlets/blob/master/wiki/about-scriptlets.md#xml-prune) (xml-prune.js, ubo-xml-prune.js, ubo-xml-prune) | [xml-prune.js](https://github.com/gorhill/uBlock/wiki/Resources-Library#xml-prunejs-) | | diff --git a/packages/agtree/src/converter/misc/network-rule-modifier.ts b/packages/agtree/src/converter/misc/network-rule-modifier.ts index 60af72a5e..5c2d7bb9f 100644 --- a/packages/agtree/src/converter/misc/network-rule-modifier.ts +++ b/packages/agtree/src/converter/misc/network-rule-modifier.ts @@ -2,8 +2,6 @@ * @file Network rule modifier list converter. */ -import scriptlets from '@adguard/scriptlets'; - import { type Modifier, type ModifierList } from '../../parser/common'; import { SEMICOLON, SPACE } from '../../utils/constants'; import { createModifierNode } from '../../ast-utils/modifiers'; @@ -12,12 +10,7 @@ import { RuleConversionError } from '../../errors/rule-conversion-error'; import { MultiValueMap } from '../../utils/multi-value-map'; import { createConversionResult, type ConversionResult } from '../base-interfaces/conversion-result'; import { cloneModifierListNode } from '../../ast-utils/clone'; - -// Since scriptlets library doesn't have ESM exports, we should import -// the whole module and then extract the required functions from it here. -// Otherwise importing AGTree will cause an error in ESM environment, -// because scriptlets library doesn't support named exports. -const { redirects } = scriptlets; +import { GenericPlatform, redirectsCompatibilityTable } from '../../compatibility-tables'; /** * Modifier conversion interface. @@ -184,11 +177,12 @@ export class NetworkRuleModifierListConverter extends ConverterBase { ? REDIRECT_MODIFIER : modifierNode.modifier.value; - // Try to convert the redirect resource name to ADG format - // This function returns undefined if the resource name is unknown - const convertedRedirectResource = redirects.convertRedirectNameToAdg(redirectResource); + const convertedRedirectResource = redirectsCompatibilityTable.getFirst( + redirectResource, + GenericPlatform.AdgAny, + )?.name; - // Check if the modifier name or the redirect resource name is different from the original modifier + // 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.modifier.value diff --git a/packages/agtree/src/index.ts b/packages/agtree/src/index.ts index d573f741a..4a2b32f84 100644 --- a/packages/agtree/src/index.ts +++ b/packages/agtree/src/index.ts @@ -126,6 +126,23 @@ export { export { METADATA_HEADERS } from './converter/data/metadata'; export { EXT_CSS_PSEUDO_CLASSES, EXT_CSS_LEGACY_ATTRIBUTES, FORBIDDEN_CSS_FUNCTIONS } from './converter/data/css'; +export { + GenericPlatform, + SpecificPlatform, + modifiersCompatibilityTable, + redirectsCompatibilityTable, + scriptletsCompatibilityTable, + parseRawPlatforms, + type CompatibilityTable, + type CompatibilityTableRow, + type ProductRecords, + type RowByProduct, + type RowsByProduct, + isGenericPlatform, + getPlatformId, + getSpecificPlatformName, +} from './compatibility-tables'; + // Re-export everything from ECSSTree export * as ECSSTree from '@adguard/ecss-tree'; diff --git a/packages/agtree/src/utils/adblockers.ts b/packages/agtree/src/utils/adblockers.ts index 5a17ecbe1..d3ea1bc33 100644 --- a/packages/agtree/src/utils/adblockers.ts +++ b/packages/agtree/src/utils/adblockers.ts @@ -5,7 +5,7 @@ /** * Possible adblock syntaxes (supported by this library) */ -export const enum AdblockSyntax { +export enum AdblockSyntax { /** * Common syntax, which is supported by more than one adblocker (or by all adblockers). * diff --git a/packages/agtree/src/utils/deep-freeze.ts b/packages/agtree/src/utils/deep-freeze.ts new file mode 100644 index 000000000..7f8c32f0e --- /dev/null +++ b/packages/agtree/src/utils/deep-freeze.ts @@ -0,0 +1,27 @@ +/** + * Simple deep freeze implementation. + * It freezes the object and all its properties recursively. + * + * @param object Object to freeze. + * + * @returns Frozen object. + * + * @template T Type of the object to freeze. + * + * @see {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/freeze#deep_freezing} + */ +export const deepFreeze = (object: T): Readonly => { + // Retrieve the property names defined on object + const propNames = Reflect.ownKeys(object) as Array; + + // 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); +}; diff --git a/packages/agtree/src/validator/README.md b/packages/agtree/src/validator/README.md index c34f9a159..96cfc39d1 100644 --- a/packages/agtree/src/validator/README.md +++ b/packages/agtree/src/validator/README.md @@ -10,9 +10,6 @@ It is used by [AGLint] to validate filtering rules. - [Modifier validator API](#modifier-validator-api) - [`exists()`](#modifier-validator-api--exists) - [`validate()`](#modifier-validator-api--validate) - - [`getAdgDocumentationLink()`, - `getUboDocumentationLink()`, - `getAbpDocumentationLink()`](#modifier-validator-api--getdocumentationlink) ## Modifier validator API @@ -190,46 +187,6 @@ import { type AdblockSyntax, ModifierParser, modifierValidator } from '@adguard/ } ``` -### `getAdgDocumentationLink()`, `getUboDocumentationLink()`, `getAbpDocumentationLink()` - - - -Returns specified adblocker syntax documentation URL for given modifier, or `null` if there is no such URL. - -```ts -getAdgDocumentationLink = (modifier: Modifier): string | null; -``` - -```ts -getUboDocumentationLink = (modifier: Modifier): string | null; -``` - -```ts -getAbpDocumentationLink = (modifier: Modifier): string | null; -``` - -where `Modifier` is a [common parser type][parser-modifier-type]. - - - - -[**Examples of `getAdgDocumentationLink()`, `getUboDocumentationLink()`, and `getAbpDocumentationLink()` usage:**](#modifier-validator-api--getdocumentationlink--examples) - -```ts -import { ModifierParser, modifierValidator } from '@adguard/agtree'; - -// ModifierParser.parse() converts a string modifier into the AGTree `Modifier` type - -// `https://adguard.app/kb/general/ad-filtering/create-own-filters/#denyallow-modifier` is returned -modifierValidator.getAdgDocumentationLink(ModifierParser.parse('denyallow=example.com')); - -// `null` is returned because $permissions modifier is not supported by Ublock Origin -modifierValidator.getUboDocumentationLink(ModifierParser.parse('permissions=autoplay=()')); - -// `https://help.adblockplus.org/hc/en-us/articles/360062733293-How-to-write-filters#type-options` is returned -modifierValidator.getAbpDocumentationLink(ModifierParser.parse('popup')); -``` - [compatibility-tables-url]: https://github.com/AdguardTeam/tsurlfilter/tree/master/packages/agtree/src/compatibility-tables [parser-modifier-type]: https://github.com/AdguardTeam/tsurlfilter/blob/865ff8a6100f804a6392f68b61b76e6d7a2c611d/packages/agtree/src/parser/common.ts#L754 [AGLint]: https://github.com/AdguardTeam/AGLint diff --git a/packages/agtree/src/validator/helpers.ts b/packages/agtree/src/validator/helpers.ts index 5d3b37413..4f6b8383d 100644 --- a/packages/agtree/src/validator/helpers.ts +++ b/packages/agtree/src/validator/helpers.ts @@ -1,4 +1,3 @@ -import { type ModifierData, type ModifierDataMap, type SpecificPlatformModifierData } from '../compatibility-tables'; import { UNDERSCORE } from '../utils/constants'; import { VALIDATION_ERROR_PREFIX } from './constants'; @@ -51,61 +50,3 @@ export const getInvalidValidationResult = (error: string): ValidationResult => { export const getValueRequiredValidationResult = (modifierName: string): ValidationResult => { return getInvalidValidationResult(`${VALIDATION_ERROR_PREFIX.VALUE_REQUIRED}: '${modifierName}'`); }; - -/** - * Collects names and aliases for all supported modifiers. - * Deprecated and removed modifiers are included because they are known and existent - * and they should be validated properly. - * - * @param dataMap Parsed all modifiers data. - * - * @returns Set of all modifier names (and their aliases). - */ -export const getAllModifierNames = (dataMap: ModifierDataMap): Set => { - const names = new Set(); - dataMap.forEach((modifierData: ModifierData) => { - Object.keys(modifierData).forEach((blockerId) => { - const blockerData = modifierData[blockerId]; - names.add(blockerData.name); - if (!blockerData.aliases) { - return; - } - blockerData.aliases.forEach((alias) => names.add(alias)); - }); - }); - return names; -}; - -/** - * Returns modifier data for given modifier name and adblocker. - * - * @param modifiersData Parsed all modifiers data map. - * @param blockerPrefix Prefix of the adblocker, e.g. 'adg_', 'ubo_', or 'abp_'. - * @param modifierName Modifier name. - * - * @returns Modifier data or `null` if not found. - */ -export const getSpecificBlockerData = ( - modifiersData: ModifierDataMap, - blockerPrefix: string, - modifierName: string, -): SpecificPlatformModifierData | null => { - let specificBlockerData: SpecificPlatformModifierData | null = null; - - modifiersData.forEach((modifierData: ModifierData) => { - Object.keys(modifierData).forEach((blockerId) => { - const blockerData = modifierData[blockerId]; - if (blockerData.name === modifierName - || (blockerData.aliases && blockerData.aliases.includes(modifierName))) { - // modifier is found by name or alias - // so its support by specific adblocker should be checked - if (blockerId.startsWith(blockerPrefix)) { - // so maybe other data objects should be checked as well (not sure) - specificBlockerData = blockerData; - } - } - }); - }); - - return specificBlockerData; -}; diff --git a/packages/agtree/src/validator/index.ts b/packages/agtree/src/validator/index.ts index 40ad8221f..09bacef8c 100644 --- a/packages/agtree/src/validator/index.ts +++ b/packages/agtree/src/validator/index.ts @@ -2,7 +2,6 @@ * @file Validator for modifiers. */ -import { type ModifierDataMap, getModifiersData, SpecificKey } from '../compatibility-tables'; import { type Modifier } from '../parser/common'; import { AdblockSyntax } from '../utils/adblockers'; import { NEWLINE, SPACE, UNDERSCORE } from '../utils/constants'; @@ -12,17 +11,29 @@ import { getInvalidValidationResult, getValueRequiredValidationResult, isValidNoopModifier, - getSpecificBlockerData, - getAllModifierNames, } from './helpers'; import { validateValue } from './value'; import { clone } from '../utils/clone'; +import { modifiersCompatibilityTable } from '../compatibility-tables/modifiers'; +import { GenericPlatform } from '../compatibility-tables/platforms'; + +const convertSyntaxToGenericPlatform = (syntax: AdblockSyntax): GenericPlatform => { + switch (syntax) { + case AdblockSyntax.Adg: + return GenericPlatform.AdgAny; + case AdblockSyntax.Ubo: + return GenericPlatform.UboAny; + case AdblockSyntax.Abp: + return GenericPlatform.AbpAny; + default: + throw new Error(`Unknown syntax: ${syntax}`); + } +}; /** * Fully checks whether the given `modifier` valid for given blocker `syntax`: * is it supported by the blocker, deprecated, assignable, negatable, etc. * - * @param modifiersData Parsed all modifiers data map. * @param syntax Adblock syntax to check the modifier for. * 'Common' is not supported, it should be specific — 'AdGuard', 'uBlockOrigin', or 'AdblockPlus'. * @param modifier Parsed modifier AST node. @@ -32,7 +43,6 @@ import { clone } from '../utils/clone'; * @returns Result of modifier validation. */ const validateForSpecificSyntax = ( - modifiersData: ModifierDataMap, syntax: AdblockSyntax, modifier: Modifier, isException: boolean, @@ -49,7 +59,10 @@ const validateForSpecificSyntax = ( } // needed for validation of negation, assignment, etc. - const specificBlockerData = getSpecificBlockerData(modifiersData, blockerPrefix, modifierName); + const specificBlockerData = modifiersCompatibilityTable.getFirst( + modifierName, + convertSyntaxToGenericPlatform(syntax), + ); // if no specific blocker data is found if (!specificBlockerData) { @@ -57,37 +70,37 @@ const validateForSpecificSyntax = ( } // e.g. 'object-subrequest' - if (specificBlockerData[SpecificKey.Removed]) { + if (specificBlockerData.removed) { return getInvalidValidationResult(`${VALIDATION_ERROR_PREFIX.REMOVED}: '${modifierName}'`); } - if (specificBlockerData[SpecificKey.Deprecated]) { - if (!specificBlockerData[SpecificKey.DeprecationMessage]) { + if (specificBlockerData.deprecated) { + if (!specificBlockerData.deprecationMessage) { throw new Error(`${SOURCE_DATA_ERROR_PREFIX.NO_DEPRECATION_MESSAGE}: '${modifierName}'`); } // prepare the message which is multiline in the yaml file - const warn = specificBlockerData[SpecificKey.DeprecationMessage].replace(NEWLINE, SPACE); + const warn = specificBlockerData.deprecationMessage.replace(NEWLINE, SPACE); return { valid: true, warn, }; } - if (specificBlockerData[SpecificKey.BlockOnly] && isException) { + if (specificBlockerData.blockOnly && isException) { return getInvalidValidationResult(`${VALIDATION_ERROR_PREFIX.BLOCK_ONLY}: '${modifierName}'`); } - if (specificBlockerData[SpecificKey.ExceptionOnly] && !isException) { + if (specificBlockerData.exceptionOnly && !isException) { return getInvalidValidationResult(`${VALIDATION_ERROR_PREFIX.EXCEPTION_ONLY}: '${modifierName}'`); } // e.g. '~domain=example.com' - if (!specificBlockerData[SpecificKey.Negatable] && modifier.exception) { + if (!specificBlockerData.negatable && modifier.exception) { return getInvalidValidationResult(`${VALIDATION_ERROR_PREFIX.NOT_NEGATABLE_MODIFIER}: '${modifierName}'`); } // e.g. 'domain' - if (specificBlockerData[SpecificKey.Assignable]) { + if (specificBlockerData.assignable) { if (!modifier.value) { // TODO: ditch value_optional after custom validators are implemented for value_format for all modifiers. // This checking should be done in each separate custom validator, @@ -97,7 +110,7 @@ const validateForSpecificSyntax = ( * Some assignable modifiers can be used without a value, * e.g. '@@||example.com^$cookie'. */ - if (specificBlockerData[SpecificKey.ValueOptional]) { + if (specificBlockerData.valueOptional) { return { valid: true }; } // for other assignable modifiers the value is required @@ -111,11 +124,11 @@ const validateForSpecificSyntax = ( * https://github.com/AdguardTeam/AdguardBrowserExtension/issues/2107 */ - if (!specificBlockerData[SpecificKey.ValueFormat]) { + if (!specificBlockerData.valueFormat) { throw new Error(`${SOURCE_DATA_ERROR_PREFIX.NO_VALUE_FORMAT_FOR_ASSIGNABLE}: '${modifierName}'`); } - return validateValue(modifier, specificBlockerData[SpecificKey.ValueFormat]); + return validateValue(modifier, specificBlockerData.valueFormat); } if (modifier?.value) { @@ -126,48 +139,11 @@ const validateForSpecificSyntax = ( return { valid: true }; }; -/** - * Returns documentation URL for given modifier and adblocker. - * - * @param modifiersData Parsed all modifiers data map. - * @param blockerPrefix Prefix of the adblocker, e.g. 'adg_', 'ubo_', or 'abp_'. - * @param modifier Parsed modifier AST node. - * - * @returns Documentation URL or `null` if not found. - */ -const getBlockerDocumentationLink = ( - modifiersData: ModifierDataMap, - blockerPrefix: string, - modifier: Modifier, -): string | null => { - const specificBlockerData = getSpecificBlockerData(modifiersData, blockerPrefix, modifier.modifier.value); - return specificBlockerData?.docs || null; -}; - // TODO: move to modifier.ts and use index.ts only for exporting /** * Modifier validator class. */ class ModifierValidator { - /** - * Map of all modifiers data parsed from yaml files. - */ - private modifiersData: ModifierDataMap; - - /** - * List of all modifier names for any adblocker. - * - * Please note that **deprecated** modifiers are **included** as well. - */ - private allModifierNames: Set; - - constructor() { - // data map based on yaml files - this.modifiersData = getModifiersData(); - - this.allModifierNames = getAllModifierNames(this.modifiersData); - } - /** * Simply checks whether the modifier exists in any adblocker. * @@ -177,8 +153,9 @@ class ModifierValidator { * * @returns True if modifier exists, false otherwise. */ + // eslint-disable-next-line class-methods-use-this public exists = (modifier: Modifier): boolean => { - return this.allModifierNames.has(modifier.modifier.value); + return modifiersCompatibilityTable.existsAny(modifier.modifier.value); }; /** @@ -219,49 +196,7 @@ class ModifierValidator { if (syntax === AdblockSyntax.Common) { return { valid: true }; } - return validateForSpecificSyntax(this.modifiersData, syntax, modifier, isException); - }; - - /** - * Returns AdGuard documentation URL for given modifier. - * - * @param modifier Parsed modifier AST node. - * - * @returns AdGuard documentation URL or `null` if not found. - */ - public getAdgDocumentationLink = (modifier: Modifier): string | null => { - if (!this.exists(modifier)) { - return null; - } - return getBlockerDocumentationLink(this.modifiersData, BLOCKER_PREFIX[AdblockSyntax.Adg], modifier); - }; - - /** - * Returns Ublock Origin documentation URL for given modifier. - * - * @param modifier Parsed modifier AST node. - * - * @returns Ublock Origin documentation URL or `null` if not found. - */ - public getUboDocumentationLink = (modifier: Modifier): string | null => { - if (!this.exists(modifier)) { - return null; - } - return getBlockerDocumentationLink(this.modifiersData, BLOCKER_PREFIX[AdblockSyntax.Ubo], modifier); - }; - - /** - * Returns AdBlock Plus documentation URL for given modifier. - * - * @param modifier Parsed modifier AST node. - * - * @returns AdBlock Plus documentation URL or `null` if not found. - */ - public getAbpDocumentationLink = (modifier: Modifier): string | null => { - if (!this.exists(modifier)) { - return null; - } - return getBlockerDocumentationLink(this.modifiersData, BLOCKER_PREFIX[AdblockSyntax.Abp], modifier); + return validateForSpecificSyntax(syntax, modifier, isException); }; } diff --git a/packages/agtree/test/compatibility-tables/modifiers.test.ts b/packages/agtree/test/compatibility-tables/modifiers.test.ts new file mode 100644 index 000000000..07ebf9ce9 --- /dev/null +++ b/packages/agtree/test/compatibility-tables/modifiers.test.ts @@ -0,0 +1,54 @@ +import { modifiersCompatibilityTable } from '../../src/compatibility-tables/modifiers'; +import { GenericPlatform, SpecificPlatform } from '../../src/compatibility-tables/platforms'; + +const baseThirdPartyData = { + name: 'third-party', + aliases: ['3p'], + // ... +}; + +describe('Modifiers Compatibility Table', () => { + it('modifiersCompatibilityTable.existsAny', () => { + expect(modifiersCompatibilityTable.existsAny('_')).toBeTruthy(); + expect(modifiersCompatibilityTable.existsAny('____')).toBeTruthy(); + expect(modifiersCompatibilityTable.existsAny('third-party')).toBeTruthy(); + + expect(modifiersCompatibilityTable.existsAny('nonexistent')).toBeFalsy(); + }); + + it('modifiersCompatibilityTable.exists', () => { + expect(modifiersCompatibilityTable.exists('_', SpecificPlatform.AdgExtChrome)).toBeTruthy(); + expect(modifiersCompatibilityTable.exists('nonexistent', SpecificPlatform.AbpExtChrome)).toBeFalsy(); + + expect(modifiersCompatibilityTable.exists('_', GenericPlatform.AdgExtAny)).toBeTruthy(); + expect(modifiersCompatibilityTable.exists('nonexistent', GenericPlatform.AbpExtAny)).toBeFalsy(); + }); + + it('modifiersCompatibilityTable.getSingle', () => { + expect( + modifiersCompatibilityTable.getSingle('third-party', SpecificPlatform.AdgExtChrome), + ).toMatchObject(baseThirdPartyData); + + expect(modifiersCompatibilityTable.getSingle('nonexistent', SpecificPlatform.AbpExtChrome)).toBeNull(); + + // docs url differs + expect( + modifiersCompatibilityTable.getSingle('third-party', SpecificPlatform.AdgExtChrome)?.docs, + ).not.toEqual( + modifiersCompatibilityTable.getSingle('third-party', SpecificPlatform.AbpExtChrome)?.docs, + ); + }); + + it('modifiersCompatibilityTable.getMultiple', () => { + expect(modifiersCompatibilityTable.getMultiple('third-party', GenericPlatform.AdgExtAny)).toMatchObject({ + [SpecificPlatform.AdgExtChrome]: baseThirdPartyData, + [SpecificPlatform.AdgExtOpera]: baseThirdPartyData, + [SpecificPlatform.AdgExtEdge]: baseThirdPartyData, + [SpecificPlatform.AdgExtFirefox]: baseThirdPartyData, + }); + + expect(modifiersCompatibilityTable.getMultiple('nonexistent', GenericPlatform.AdgExtAny)).toBeNull(); + }); + + // TODO: Add more tests +}); diff --git a/packages/agtree/test/compatibility-tables/redirects.test.ts b/packages/agtree/test/compatibility-tables/redirects.test.ts new file mode 100644 index 000000000..690fcd062 --- /dev/null +++ b/packages/agtree/test/compatibility-tables/redirects.test.ts @@ -0,0 +1,46 @@ +import { redirectsCompatibilityTable } from '../../src/compatibility-tables/redirects'; +import { GenericPlatform, SpecificPlatform } from '../../src/compatibility-tables/platforms'; + +const baseNoopJsData = { + name: 'noopjs', + aliases: ['noop.js', 'blank-js'], + // ... +}; + +describe('Redirects Compatibility Table', () => { + it('redirectsCompatibilityTable.existsAny', () => { + expect(redirectsCompatibilityTable.existsAny('noopjs')).toBeTruthy(); + expect(redirectsCompatibilityTable.existsAny('blank-js')).toBeTruthy(); + + expect(redirectsCompatibilityTable.existsAny('nonexistent')).toBeFalsy(); + }); + + it('redirectsCompatibilityTable.exists', () => { + expect(redirectsCompatibilityTable.exists('noopjs', SpecificPlatform.AdgExtChrome)).toBeTruthy(); + expect(redirectsCompatibilityTable.exists('nonexistent', SpecificPlatform.AbpExtChrome)).toBeFalsy(); + + expect(redirectsCompatibilityTable.exists('noopjs', GenericPlatform.AdgExtAny)).toBeTruthy(); + expect(redirectsCompatibilityTable.exists('nonexistent', GenericPlatform.AbpExtAny)).toBeFalsy(); + }); + + it('redirectsCompatibilityTable.getSingle', () => { + expect( + redirectsCompatibilityTable.getSingle('noopjs', SpecificPlatform.AdgExtChrome), + ).toMatchObject(baseNoopJsData); + + expect(redirectsCompatibilityTable.getSingle('nonexistent', SpecificPlatform.AbpExtChrome)).toBeNull(); + }); + + it('redirectsCompatibilityTable.getMultiple', () => { + expect(redirectsCompatibilityTable.getMultiple('noopjs', GenericPlatform.AdgExtAny)).toMatchObject({ + [SpecificPlatform.AdgExtChrome]: baseNoopJsData, + [SpecificPlatform.AdgExtOpera]: baseNoopJsData, + [SpecificPlatform.AdgExtEdge]: baseNoopJsData, + [SpecificPlatform.AdgExtFirefox]: baseNoopJsData, + }); + + expect(redirectsCompatibilityTable.getMultiple('nonexistent', GenericPlatform.AdgExtAny)).toBeNull(); + }); + + // TODO: Add more tests +}); diff --git a/packages/agtree/test/compatibility-tables/scriptlets.test.ts b/packages/agtree/test/compatibility-tables/scriptlets.test.ts new file mode 100644 index 000000000..12ba8e41d --- /dev/null +++ b/packages/agtree/test/compatibility-tables/scriptlets.test.ts @@ -0,0 +1,55 @@ +import { scriptletsCompatibilityTable } from '../../src/compatibility-tables/scriptlets'; +import { GenericPlatform, SpecificPlatform } from '../../src/compatibility-tables/platforms'; + +const baseAbortCurrentInlineScriptData = { + name: 'abort-current-inline-script', + // ... +}; + +describe('Scriptlets Compatibility Table', () => { + it('scriptletsCompatibilityTable.existsAny', () => { + expect(scriptletsCompatibilityTable.existsAny('abort-current-inline-script')).toBeTruthy(); + expect(scriptletsCompatibilityTable.existsAny('abort-on-property-read')).toBeTruthy(); + + expect(scriptletsCompatibilityTable.existsAny('nonexistent')).toBeFalsy(); + }); + + it('scriptletsCompatibilityTable.exists', () => { + expect( + scriptletsCompatibilityTable.exists('abort-current-inline-script', SpecificPlatform.AdgExtChrome), + ).toBeTruthy(); + expect( + scriptletsCompatibilityTable.exists('nonexistent', SpecificPlatform.AbpExtChrome), + ).toBeFalsy(); + + expect( + scriptletsCompatibilityTable.exists('abort-current-inline-script', GenericPlatform.AdgExtAny), + ).toBeTruthy(); + expect( + scriptletsCompatibilityTable.exists('nonexistent', GenericPlatform.AbpExtAny), + ).toBeFalsy(); + }); + + it('scriptletsCompatibilityTable.getSingle', () => { + expect( + scriptletsCompatibilityTable.getSingle('abort-current-inline-script', SpecificPlatform.AdgExtChrome), + ).toMatchObject(baseAbortCurrentInlineScriptData); + + expect(scriptletsCompatibilityTable.getSingle('nonexistent', SpecificPlatform.AbpExtChrome)).toBeNull(); + }); + + it('scriptletsCompatibilityTable.getMultiple', () => { + expect( + scriptletsCompatibilityTable.getMultiple('abort-current-inline-script', GenericPlatform.AdgExtAny), + ).toMatchObject({ + [SpecificPlatform.AdgExtChrome]: baseAbortCurrentInlineScriptData, + [SpecificPlatform.AdgExtOpera]: baseAbortCurrentInlineScriptData, + [SpecificPlatform.AdgExtEdge]: baseAbortCurrentInlineScriptData, + [SpecificPlatform.AdgExtFirefox]: baseAbortCurrentInlineScriptData, + }); + + expect(scriptletsCompatibilityTable.getMultiple('nonexistent', GenericPlatform.AdgExtAny)).toBeNull(); + }); + + // TODO: Add more tests +}); diff --git a/packages/agtree/test/utils/deep-freeze.test.ts b/packages/agtree/test/utils/deep-freeze.test.ts new file mode 100644 index 000000000..b65834574 --- /dev/null +++ b/packages/agtree/test/utils/deep-freeze.test.ts @@ -0,0 +1,78 @@ +import { deepFreeze } from '../../src/utils/deep-freeze'; + +// Sample interface for better type checking in tests +interface SampleObject { + a: number; + b: { + c: number; + d: { + e: number; + }; + }; + f: () => void; + g: number[]; +} + +describe('deepFreeze', () => { + it('should freeze a simple object', () => { + const obj = { a: 1, b: 2 }; + const frozenObj = deepFreeze(obj); + + expect(Object.isFrozen(frozenObj)).toBe(true); + expect(Object.isFrozen(frozenObj.a)).toBe(true); + expect(Object.isFrozen(frozenObj.b)).toBe(true); + }); + + it('should freeze a nested object', () => { + const nestedObj: SampleObject = { + a: 1, + b: { + c: 2, + d: { + e: 3, + }, + }, + f: () => 1, + g: [1, 2, 3], + }; + const frozenObj = deepFreeze(nestedObj); + + expect(Object.isFrozen(frozenObj)).toBe(true); + expect(Object.isFrozen(frozenObj.b)).toBe(true); + expect(Object.isFrozen(frozenObj.b.d)).toBe(true); + }); + + it('should make the object immutable after freezing', () => { + const obj = { a: 1, b: { c: 2 } }; + const frozenObj = deepFreeze(obj); + + expect(() => { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + (frozenObj as any).a = 10; + }).toThrow(TypeError); + + expect(() => { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + (frozenObj.b as any).c = 20; + }).toThrow(TypeError); + }); + + it('should handle functions within the object', () => { + const obj = { + a: 1, + b: () => 1, + }; + const frozenObj = deepFreeze(obj); + + expect(Object.isFrozen(frozenObj)).toBe(true); + expect(Object.isFrozen(frozenObj.b)).toBe(true); + }); + + it('should freeze arrays within the object', () => { + const obj = { a: [1, 2, 3] }; + const frozenObj = deepFreeze(obj); + + expect(Object.isFrozen(frozenObj)).toBe(true); + expect(Object.isFrozen(frozenObj.a)).toBe(true); + }); +}); diff --git a/packages/agtree/test/validator/index.test.ts b/packages/agtree/test/validator/index.test.ts index 520dc43a2..f05aeda40 100644 --- a/packages/agtree/test/validator/index.test.ts +++ b/packages/agtree/test/validator/index.test.ts @@ -6,12 +6,6 @@ import { VALIDATION_ERROR_PREFIX } from '../../src/validator/constants'; import { AdblockSyntax } from '../../src/utils/adblockers'; import { LIST_PARSE_ERROR_PREFIX } from '../../src/parser/misc/list-helpers'; -const DOCS_BASE_URL = { - ADG: 'https://adguard.app/kb/general/ad-filtering/create-own-filters/', - UBO: 'https://github.com/gorhill/uBlock/wiki/Static-filter-syntax', - ABP: 'https://help.adblockplus.org/', -}; - /** * Returns modifier AST node for given rawModifier. * @@ -1293,104 +1287,4 @@ describe('ModifierValidator', () => { }); }); }); - - describe('getAdgDocumentationLink', () => { - describe('has docs', () => { - const modifiers = [ - 'denyallow', - 'domain=example.com', - 'third-party', - 'important', - // deprecated - 'empty', - 'mp4', - // 'webrtc' is removed and not supported but it has docs url - 'webrtc', - ]; - test.each(modifiers)('%s', (rawModifier) => { - const modifier = getModifier(rawModifier); - const docsUrl = modifierValidator.getAdgDocumentationLink(modifier); - expect(docsUrl?.startsWith(DOCS_BASE_URL.ADG)).toBeTruthy(); - }); - }); - - describe('no docs', () => { - const modifiers = [ - // not existent - 'protobuf', - // not supported by ADG - 'cname', - ]; - test.each(modifiers)('%s', (rawModifier) => { - const modifier = getModifier(rawModifier); - const docsUrl = modifierValidator.getAdgDocumentationLink(modifier); - expect(docsUrl).toBeNull(); - }); - }); - }); - - describe('getUboDocumentationLink', () => { - describe('has docs', () => { - const modifiers = [ - 'cname', - 'from=example.com', - 'third-party', - 'important', - // deprecated modifiers - 'empty', - 'mp4', - // 'webrtc' is removed and not supported but it has docs url - 'webrtc', - ]; - test.each(modifiers)('%s', (rawModifier) => { - const modifier = getModifier(rawModifier); - const docsUrl = modifierValidator.getUboDocumentationLink(modifier); - expect(docsUrl?.startsWith(DOCS_BASE_URL.UBO)).toBeTruthy(); - }); - }); - - describe('no docs', () => { - const modifiers = [ - // not existent - 'protobuf', - // not supported by UBO - 'removeheader', - ]; - test.each(modifiers)('%s', (rawModifier) => { - const modifier = getModifier(rawModifier); - const docsUrl = modifierValidator.getUboDocumentationLink(modifier); - expect(docsUrl).toBeNull(); - }); - }); - }); - - describe('getAbpDocumentationLink', () => { - describe('has docs', () => { - const modifiers = [ - 'domain=example.com', - 'third-party', - 'webrtc', - ]; - test.each(modifiers)('%s', (rawModifier) => { - const modifier = getModifier(rawModifier); - const docsUrl = modifierValidator.getAbpDocumentationLink(modifier); - expect(docsUrl?.startsWith(DOCS_BASE_URL.ABP)).toBeTruthy(); - }); - }); - - describe('no docs', () => { - const modifiers = [ - // not existent - 'protobuf', - // not supported by ABP - 'denyallow', - 'important', - ]; - test.each(modifiers)('%s', (rawModifier) => { - const modifier = getModifier(rawModifier); - const docsUrl = modifierValidator.getAbpDocumentationLink(modifier); - expect(docsUrl).toBeNull(); - }); - }); - }); }); diff --git a/packages/agtree/tsconfig.eslint.json b/packages/agtree/tsconfig.eslint.json index 9f336c244..827b5bd1f 100644 --- a/packages/agtree/tsconfig.eslint.json +++ b/packages/agtree/tsconfig.eslint.json @@ -6,6 +6,7 @@ "rollup.config.ts", "scripts/**/*.ts", "scripts/.eslintrc.cjs", + "src/compatibility-tables/extractors/.eslintrc.cjs", "src/**/*.ts", "test/**/*.ts", ] diff --git a/packages/agtree/tsconfig.json b/packages/agtree/tsconfig.json index eb45011fc..ea1cb18f5 100644 --- a/packages/agtree/tsconfig.json +++ b/packages/agtree/tsconfig.json @@ -19,7 +19,8 @@ "rootDir": "./" }, "include": [ - "./src" + "./src", + "./scripts" ], "exclude": [ "./node_modules", @@ -27,7 +28,6 @@ ], "ts-node": { "swc": true, - "esm": true, "compilerOptions": { "module": "ESNext" } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index f8dca064d..2a263028f 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -90,9 +90,6 @@ importers: '@adguard/ecss-tree': specifier: ^1.0.8 version: 1.0.8 - '@adguard/scriptlets': - specifier: ^1.9.61 - version: 1.10.25 clone-deep: specifier: ^4.0.1 version: 4.0.1 @@ -108,6 +105,9 @@ importers: xregexp: specifier: ^5.1.1 version: 5.1.1 + zod: + specifier: ^3.23.4 + version: 3.23.4 devDependencies: '@babel/core': specifier: ^7.22.5 @@ -136,9 +136,6 @@ importers: '@rollup/plugin-typescript': specifier: ^11.1.2 version: 11.1.6(rollup@3.29.4)(typescript@5.4.2) - '@rollup/plugin-yaml': - specifier: ^4.1.1 - version: 4.1.2(rollup@3.29.4) '@swc/core': specifier: ^1.3.100 version: 1.4.8(@swc/helpers@0.5.7) @@ -155,7 +152,7 @@ importers: specifier: ^11.0.4 version: 11.0.4 '@types/jest': - specifier: ^29.5.3 + specifier: ^29.5.12 version: 29.5.12 '@types/js-yaml': specifier: ^4.0.5 @@ -172,6 +169,9 @@ importers: '@typescript-eslint/parser': specifier: ^5.60.1 version: 5.62.0(eslint@8.54.0)(typescript@5.4.2) + camelcase-keys: + specifier: ^7.0.2 + version: 7.0.2 eslint: specifier: ^8.43.0 version: 8.54.0 @@ -202,12 +202,18 @@ importers: jsdoc: specifier: ^4.0.2 version: 4.0.2 + markdown-table: + specifier: ^3.0.3 + version: 3.0.3 markdownlint: specifier: ^0.29.0 version: 0.29.0 markdownlint-cli: specifier: ^0.35.0 version: 0.35.0 + prettier: + specifier: ^3.3.2 + version: 3.3.2 regenerator-runtime: specifier: ^0.14.0 version: 0.14.1 @@ -226,21 +232,18 @@ importers: rollup-plugin-polyfill-node: specifier: ^0.12.0 version: 0.12.0(rollup@3.29.4) - superstruct: - specifier: ^1.0.3 - version: 1.0.4 ts-node: specifier: ^10.9.2 version: 10.9.2(@swc/core@1.4.8)(@types/node@20.11.30)(typescript@5.4.2) + tsx: + specifier: ^4.7.3 + version: 4.7.3 + type-fest: + specifier: ^4.18.0 + version: 4.18.0 typescript: specifier: ^5.0.4 version: 5.4.2 - yaml-jest-transform: - specifier: ^2.0.2 - version: 2.0.2 - zod: - specifier: ^3.22.2 - version: 3.22.4 packages/css-tokenizer: devDependencies: @@ -1060,13 +1063,6 @@ packages: - debug dev: false - /@adguard/scriptlets@1.10.25: - resolution: {integrity: sha512-q5s7PZ0oIizmcYQa/UI++MxQ7Cb3pdy1K9VY7yj+wtJ/xevEo/nxSLhnU/ijhSMvlAdFlGEkY898munZNfCUYA==} - dependencies: - '@babel/runtime': 7.24.1 - js-yaml: 3.14.1 - dev: false - /@adguard/scriptlets@1.11.1: resolution: {integrity: sha512-HRDgDeHmYXEvplVec9ABOwV6Hwh9nN5E6rMSdb8yioPrHsj5orI5BQ2ABz+s2JgC9fjshauvk818jWTtDxX9aw==} dependencies: @@ -4016,21 +4012,6 @@ packages: typescript: 4.7.4 dev: true - /@rollup/plugin-yaml@4.1.2(rollup@3.29.4): - resolution: {integrity: sha512-RpupciIeZMUqhgFE97ba0s98mOFS7CWzN3EJNhJkqSv9XLlWYtwVdtE6cDw6ASOF/sZVFS7kRJXftaqM2Vakdw==} - engines: {node: '>=14.0.0'} - peerDependencies: - rollup: ^1.20.0||^2.0.0||^3.0.0||^4.0.0 - peerDependenciesMeta: - rollup: - optional: true - dependencies: - '@rollup/pluginutils': 5.1.0(rollup@3.29.4) - js-yaml: 4.1.0 - rollup: 3.29.4 - tosource: 2.0.0-alpha.3 - dev: true - /@rollup/pluginutils@3.1.0(rollup@2.77.3): resolution: {integrity: sha512-GksZ6pr6TpIjHm8h9lSQ8pi8BE9VeubNT0OMJ3B5uZJ8pz73NPiqOtCog/x2/QzM1ENChPKxMDhiQuRHsqc+lg==} engines: {node: '>= 8.0.0'} @@ -7312,6 +7293,16 @@ packages: quick-lru: 4.0.1 dev: true + /camelcase-keys@7.0.2: + resolution: {integrity: sha512-Rjs1H+A9R+Ig+4E/9oyB66UC5Mj9Xq3N//vcLf2WzgdTi/3gUu3Z9KoqmlrEG4VuuLK8wJHofxzdQXz/knhiYg==} + engines: {node: '>=12'} + dependencies: + camelcase: 6.3.0 + map-obj: 4.3.0 + quick-lru: 5.1.1 + type-fest: 1.4.0 + dev: true + /camelcase@5.3.1: resolution: {integrity: sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==} engines: {node: '>=6'} @@ -10911,6 +10902,12 @@ packages: get-intrinsic: 1.2.4 dev: true + /get-tsconfig@4.7.3: + resolution: {integrity: sha512-ZvkrzoUA0PQZM6fy6+/Hce561s+faD1rsNwhnO5FelNjyy7EMGJ3Rz1AQ8GYDWjhRs/7dBLOEJvhK8MiEJOAFg==} + dependencies: + resolve-pkg-maps: 1.0.0 + dev: true + /getpass@0.1.7: resolution: {integrity: sha512-0fzj9JxOLfJ+XGLhR8ze3unN0KZCgZwiSSDz168VERjK8Wl8kVSdcu2kspd4s4wtAa1y/qrVRiAA0WclVsu0ng==} dependencies: @@ -15325,6 +15322,12 @@ packages: engines: {node: '>=4'} dev: true + /prettier@3.3.2: + resolution: {integrity: sha512-rAVeHYMcv8ATV5d508CFdn+8/pHPpXeIid1DdrPwXnaAdH7cqjVbpJaT5eq4yRAFU/lsbwYwSF/n5iNrdJHPQA==} + engines: {node: '>=14'} + hasBin: true + dev: true + /pretty-error@4.0.0: resolution: {integrity: sha512-AoJ5YMAcXKYxKhuJGdcvse+Voc6v1RgnsR3nWcYU7q4t6z0Q6T86sv5Zq8VIRbOWWFpvdGE83LtdSMNd+6Y0xw==} dependencies: @@ -15504,6 +15507,11 @@ packages: engines: {node: '>=8'} dev: true + /quick-lru@5.1.1: + resolution: {integrity: sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==} + engines: {node: '>=10'} + dev: true + /randombytes@2.1.0: resolution: {integrity: sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==} dependencies: @@ -15872,6 +15880,10 @@ packages: engines: {node: '>=8'} dev: true + /resolve-pkg-maps@1.0.0: + resolution: {integrity: sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==} + dev: true + /resolve.exports@2.0.2: resolution: {integrity: sha512-X2UW6Nw3n/aMgDVy+0rSqgHlv39WZAlZrXCdnbyEiKm17DSqHX4MmQMaST3FbeWR5FTuRcUwYAziZajji0Y7mg==} engines: {node: '>=10'} @@ -16976,11 +16988,6 @@ packages: webpack: 5.90.3(@swc/core@1.4.8) dev: true - /superstruct@1.0.4: - resolution: {integrity: sha512-7JpaAoX2NGyoFlI9NBh66BQXGONc+uE+MRS5i2iOBKuS4e+ccgMDjATgZldkah+33DakBxDHiss9kvUcGAO8UQ==} - engines: {node: '>=14.0.0'} - dev: true - /supports-color@5.5.0: resolution: {integrity: sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==} engines: {node: '>=4'} @@ -17251,11 +17258,6 @@ packages: engines: {node: '>=0.4.0'} dev: true - /tosource@2.0.0-alpha.3: - resolution: {integrity: sha512-KAB2lrSS48y91MzFPFuDg4hLbvDiyTjOVgaK7Erw+5AmZXNq4sFRVn8r6yxSLuNs15PaokrDRpS61ERY9uZOug==} - engines: {node: '>=10'} - dev: true - /tough-cookie@2.5.0: resolution: {integrity: sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==} engines: {node: '>=0.8'} @@ -17561,6 +17563,17 @@ packages: typescript: 5.4.4 dev: true + /tsx@4.7.3: + resolution: {integrity: sha512-+fQnMqIp/jxZEXLcj6WzYy9FhcS5/Dfk8y4AtzJ6ejKcKqmfTF8Gso/jtrzDggCF2zTU20gJa6n8XqPYwDAUYQ==} + engines: {node: '>=18.0.0'} + hasBin: true + dependencies: + esbuild: 0.19.12 + get-tsconfig: 4.7.3 + optionalDependencies: + fsevents: 2.3.3 + dev: true + /tuf-js@1.1.7: resolution: {integrity: sha512-i3P9Kgw3ytjELUfpuKVDNBJvk4u5bXL6gskv572mcevPbSKCV3zt3djhmlEQ65yERjIbOSncy7U4cQJaB1CBCg==} engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} @@ -17635,6 +17648,16 @@ packages: engines: {node: '>=8'} dev: true + /type-fest@1.4.0: + resolution: {integrity: sha512-yGSza74xk0UG8k+pLh5oeoYirvIiWo5t0/o3zHHAO2tRDiZcxWP7fywNlXhqb6/r6sWvwi+RsyQMWhVLe4BVuA==} + engines: {node: '>=10'} + dev: true + + /type-fest@4.18.0: + resolution: {integrity: sha512-+dbmiyliDY/2TTcjCS7NpI9yV2iEFlUDk5TKnsbkN7ZoRu5s7bT+zvYtNFhFXC2oLwURGT2frACAZvbbyNBI+w==} + engines: {node: '>=16'} + dev: true + /type-is@1.6.18: resolution: {integrity: sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==} engines: {node: '>= 0.6'} @@ -18459,12 +18482,6 @@ packages: /yallist@4.0.0: resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==} - /yaml-jest-transform@2.0.2: - resolution: {integrity: sha512-RrNFpmRD5kwG1nuYpoOPPVRKhrUXAV1ut+mStfy6/Vsw76K7Afw2NfN1sN3MWpYtd61ESr4dY79/gulKWvLHMw==} - dependencies: - js-yaml: 4.1.0 - dev: true - /yaml@2.4.1: resolution: {integrity: sha512-pIXzoImaqmfOrL7teGUBt/T7ZDnyeGBWyXQBvOVhLkWLN37GXv8NMLK406UY6dS51JfcQHsmcW5cJ441bHg6Lg==} engines: {node: '>= 14'} @@ -18563,6 +18580,11 @@ packages: /zod@3.22.4: resolution: {integrity: sha512-iC+8Io04lddc+mVqQ9AZ7OQ2MrUKGN+oIQyq1vemgt46jwCwLfhq7/pwnBnNXXXZb8VTVLKwp9EDkx+ryxIWmg==} + dev: false + + /zod@3.23.4: + resolution: {integrity: sha512-/AtWOKbBgjzEYYQRNfoGKHObgfAZag6qUJX1VbHo2PRBgS+wfWagEY2mizjfyAPcGesrJOcx/wcl0L9WnVrHFw==} + dev: false github.com/105th/jsdiff/2be2e7df90e8eebd99f0385c7b1dc16c2f4dcc1a: resolution: {tarball: https://codeload.github.com/105th/jsdiff/tar.gz/2be2e7df90e8eebd99f0385c7b1dc16c2f4dcc1a}