From 4936b58d02055259f89cd0d377d80ea97ff398f4 Mon Sep 17 00:00:00 2001 From: HoJeong Go Date: Mon, 27 Jan 2025 15:54:52 +0900 Subject: [PATCH 1/6] feat: improve dialect conversion accuracy --- scripts/update.js | 61 ++-- src/converters/adguard.js | 4 +- src/converters/helpers.js | 99 +++---- src/mappings.json | 577 ++++++++++++++++++++++++-------------- 4 files changed, 450 insertions(+), 291 deletions(-) diff --git a/scripts/update.js b/scripts/update.js index bd5ddbb..1187c2e 100644 --- a/scripts/update.js +++ b/scripts/update.js @@ -33,39 +33,52 @@ async function downloadResource(resourceName) { function extractRedirects(data) { console.log('Extracting resources...'); - const resources = JSON.parse(data); - const mappings = resources.redirects.map((redirect) => [redirect.name, redirect.aliases ?? []]); + /** + * @type {Array<{ dialects: { adg: string; ubo: string; }; hints: string[]; }>} + */ + const mappings = []; - // Integrate adguard mappings - for (const dialect of adguardDialects) { - // Skip adguard exclusives - if (dialect.aliases === undefined) { - continue; + /** + * @type {{ redirects: Array<{ name: string; aliases: string[]; body: string; contentType: string; }> }} + */ + const { redirects } = JSON.parse(data); + for (const redirect of redirects) { + /** + * @type {Set} + */ + const hints = new Set(); + hints.add(redirect.name); + for (const alias of redirect.aliases) { + hints.add(alias); } - // Find an entry with adguard dialect - const entry = mappings.find(([, aliases]) => { - if (aliases.includes(dialect.title)) { - return true; - } - - for (const alias of dialect.aliases) { - if (aliases.includes(alias)) { - return true; + // Register AdGuard dialects + /** + * @type {{ title: string; aliases: string[]; isBlocking: boolean; contentType: string; content: string; }} + */ + const adguardDialect = adguardDialects.find((dialect) => + [dialect.title, ...(dialect.aliases ?? [])].includes(redirect.name), + ); + if (adguardDialect !== undefined) { + hints.add(adguardDialect.title); + if (adguardDialect.aliases !== undefined) { + for (const alias of adguardDialect.aliases) { + hints.add(alias); } } + } - return false; - }); - if (entry === undefined) { + if (hints.size === 1) { continue; } - for (const alias of [dialect.title, ...dialect.aliases]) { - if (entry[1].includes(alias) === false) { - entry[1].push(alias); - } - } + mappings.push({ + dialects: { + adg: adguardDialect?.title, + ubo: redirect.name, + }, + hints: Array.from(hints), + }); } return JSON.stringify(mappings, null, 2); diff --git a/src/converters/adguard.js b/src/converters/adguard.js index 1733e5f..c932305 100644 --- a/src/converters/adguard.js +++ b/src/converters/adguard.js @@ -9,11 +9,11 @@ const createFilter = (rules, filterId = 0) => { export default async function convert(rules, { resourcesPath } = {}) { const filter = createFilter(rules.map(normalizeFilter)); - const conversionResult = await converter.convertStaticRuleSet(filter, { resourcesPath }); + const conversionResult = await converter.convertStaticRuleSet(filter, { resourcesPath: '/a' }); const declarativeRules = await conversionResult.ruleSet.getDeclarativeRules(); return { - rules: declarativeRules.map((rule) => normalizeRule(rule)), + rules: declarativeRules.map((rule) => normalizeRule(rule, { resourcesPath })), errors: conversionResult.errors, limitations: conversionResult.limitations, }; diff --git a/src/converters/helpers.js b/src/converters/helpers.js index 82b8429..be2533e 100644 --- a/src/converters/helpers.js +++ b/src/converters/helpers.js @@ -1,34 +1,54 @@ import mappings from '../mappings.json'; -function getPathBasename(path) { - const lastIndex = path.lastIndexOf('/'); - if (lastIndex === -1) { - return path; - } - return path.slice(lastIndex + 1); -} - -export function generateResourcesMapping() { - const resourcesMapping = new Map(); - for (const [name, aliases] of mappings) { - for (const alias of aliases) { - resourcesMapping.set(alias, name); - } - } - return resourcesMapping; -} - export const DEFAULT_PARAM_MAPPING = { '3p': 'third-party', xhr: 'xmlhttprequest', frame: 'subdocument', }; -export const DEFAULT_RESOURCES_MAPPING = generateResourcesMapping(); -export function normalizeFilter( - filter, - { mapping = DEFAULT_PARAM_MAPPING, resourcesMapping = DEFAULT_RESOURCES_MAPPING } = {}, -) { +/** + * Normalizes redirect resource name into preferred format (if not found, will use 'ubo') + * @param {string} name + * @param {'ubo' | 'adg'} dialect + */ +function normalizeRedirect(name, dialect) { + if (dialect !== 'ubo' && dialect !== 'adg') { + throw new Error(`The redirect resource dialect of "${dialect}" is not supported!`); + } + + console.log(name, dialect); + + /** + * @type {string[]} + */ + const candidates = [name]; + + if (name.indexOf('.') !== -1) { + candidates.push(name.slice(0, name.lastIndexOf('.'))); + } + + const mapping = mappings.find((mapping) => { + for (const candidate of candidates) { + const found = + mapping.hints.includes(candidate) || + mapping.hints.find((hint) => hint.includes(candidate)) !== undefined; + + if (found) { + return true; + } + } + + return false; + }); + + if (mapping === undefined) { + return name; + } + + return mapping.dialects[dialect] ?? mapping.dialects.ubo; +} + +export function normalizeFilter(filter, { mapping = DEFAULT_PARAM_MAPPING } = {}) { let [front, ...back] = filter.split('$'); let params = back.join(',').split(','); @@ -49,24 +69,16 @@ export function normalizeFilter( front = front.toLowerCase(); } - // adguard converter doesn't work with $redirect with slash value - // replace possible $redirect params including a slash - const indexOfRedirect = params.findIndex((p) => p.startsWith('redirect=') && p.includes('/')); + const indexOfRedirect = params.findIndex((p) => p.startsWith('redirect=')); if (indexOfRedirect !== -1) { - const name = resourcesMapping.get(params[indexOfRedirect].slice(9)); - if (name !== undefined) { - params[indexOfRedirect] = 'redirect=' + name; - } + params[indexOfRedirect] = + 'redirect=' + normalizeRedirect(params[indexOfRedirect].slice(9), 'adg'); } - const indexOfRedirectRule = params.findIndex( - (p) => p.startsWith('redirect-rule=') && p.includes('/'), - ); + const indexOfRedirectRule = params.findIndex((p) => p.startsWith('redirect-rule=')); if (indexOfRedirectRule !== -1) { - const name = resourcesMapping.get(params[indexOfRedirectRule].slice(14)); - if (name !== undefined) { - params[indexOfRedirectRule] = 'redirect-rule=' + name; - } + params[indexOfRedirect] = + 'redirect=' + normalizeRedirect(params[indexOfRedirect].slice(14), 'adg'); } if (back.length === 0) { @@ -76,7 +88,7 @@ export function normalizeFilter( return `${front}$${params.join(',')}`; } -export function normalizeRule(rule, { resourcesMapping = DEFAULT_RESOURCES_MAPPING } = {}) { +export function normalizeRule(rule, { resourcesPath } = {}) { if (!rule) { return; } @@ -111,16 +123,7 @@ export function normalizeRule(rule, { resourcesMapping = DEFAULT_RESOURCES_MAPPI } if (newRule.action && newRule.action.type === 'redirect') { - const filename = getPathBasename(newRule.action.redirect.extensionPath); - const preferredFilename = - resourcesMapping.get(filename) ?? - // try searching without an extension - // adguard converter attaches an file extension at the end - resourcesMapping.get(filename.slice(0, filename.lastIndexOf('.'))); - if (preferredFilename !== undefined) { - newRule.action.redirect.extensionPath = - newRule.action.redirect.extensionPath.slice(0, -filename.length) + preferredFilename; - } + newRule.action.redirect.extensionPath = `${resourcesPath}/${normalizeRedirect(newRule.action.redirect.extensionPath.slice(3 /* '/a/'.length */), 'ubo')}`; } return newRule; diff --git a/src/mappings.json b/src/mappings.json index 81e5314..d611b05 100644 --- a/src/mappings.json +++ b/src/mappings.json @@ -1,299 +1,442 @@ [ - [ - "1x1.gif", - [ - "1x1-transparent.gif", + { + "dialects": { + "adg": "1x1-transparent.gif", + "ubo": "1x1.gif" + }, + "hints": [ "1x1.gif", + "1x1-transparent.gif", "1x1-transparent-gif" ] - ], - [ - "2x2.png", - [ - "2x2-transparent.png", + }, + { + "dialects": { + "adg": "2x2-transparent.png", + "ubo": "2x2.png" + }, + "hints": [ "2x2.png", + "2x2-transparent.png", "2x2-transparent-png" ] - ], - [ - "3x2.png", - [ - "3x2-transparent.png", + }, + { + "dialects": { + "adg": "3x2-transparent.png", + "ubo": "3x2.png" + }, + "hints": [ "3x2.png", + "3x2-transparent.png", "3x2-transparent-png" ] - ], - [ - "32x32.png", - [ - "32x32-transparent.png", + }, + { + "dialects": { + "adg": "32x32-transparent.png", + "ubo": "32x32.png" + }, + "hints": [ "32x32.png", + "32x32-transparent.png", "32x32-transparent-png" ] - ], - [ - "amazon_ads.js", - [ + }, + { + "dialects": { + "ubo": "amazon_ads.js" + }, + "hints": [ + "amazon_ads.js", "amazon-adsystem.com/aax2/amzn_ads.js" ] - ], - [ - "amazon_apstag.js", - [] - ], - [ - "ampproject_v0.js", - [ + }, + { + "dialects": { + "adg": "amazon-apstag", + "ubo": "amazon_apstag.js" + }, + "hints": [ + "amazon_apstag.js", + "amazon-apstag", + "ubo-amazon_apstag.js" + ] + }, + { + "dialects": { + "ubo": "ampproject_v0.js" + }, + "hints": [ + "ampproject_v0.js", "ampproject.org/v0.js" ] - ], - [ - "chartbeat.js", - [ + }, + { + "dialects": { + "ubo": "chartbeat.js" + }, + "hints": [ + "chartbeat.js", "static.chartbeat.com/chartbeat.js" ] - ], - [ - "click2load.html", - [] - ], - [ - "doubleclick_instream_ad_status.js", - [ + }, + { + "dialects": { + "adg": "click2load.html", + "ubo": "click2load.html" + }, + "hints": [ + "click2load.html", + "ubo-click2load.html" + ] + }, + { + "dialects": { + "ubo": "doubleclick_instream_ad_status.js" + }, + "hints": [ + "doubleclick_instream_ad_status.js", "doubleclick.net/instream/ad_status.js" ] - ], - [ - "empty", - [] - ], - [ - "fingerprint2.js", - [] - ], - [ - "fingerprint3.js", - [] - ], - [ - "google-analytics_analytics.js", - [ + }, + { + "dialects": { + "adg": "fingerprintjs2", + "ubo": "fingerprint2.js" + }, + "hints": [ + "fingerprint2.js", + "fingerprintjs2", + "ubo-fingerprint2.js" + ] + }, + { + "dialects": { + "adg": "fingerprintjs3", + "ubo": "fingerprint3.js" + }, + "hints": [ + "fingerprint3.js", + "fingerprintjs3", + "ubo-fingerprint3.js" + ] + }, + { + "dialects": { + "adg": "google-analytics", + "ubo": "google-analytics_analytics.js" + }, + "hints": [ + "google-analytics_analytics.js", "google-analytics.com/analytics.js", "googletagmanager_gtm.js", "googletagmanager.com/gtm.js", "google-analytics", "ubo-google-analytics_analytics.js", - "google-analytics_analytics.js", "googletagmanager-gtm", "ubo-googletagmanager_gtm.js" ] - ], - [ - "google-analytics_cx_api.js", - [ + }, + { + "dialects": { + "ubo": "google-analytics_cx_api.js" + }, + "hints": [ + "google-analytics_cx_api.js", "google-analytics.com/cx/api.js" ] - ], - [ - "google-analytics_ga.js", - [ - "google-analytics.com/ga.js" + }, + { + "dialects": { + "adg": "google-analytics-ga", + "ubo": "google-analytics_ga.js" + }, + "hints": [ + "google-analytics_ga.js", + "google-analytics.com/ga.js", + "google-analytics-ga", + "ubo-google-analytics_ga.js" ] - ], - [ - "google-analytics_inpage_linkid.js", - [ + }, + { + "dialects": { + "ubo": "google-analytics_inpage_linkid.js" + }, + "hints": [ + "google-analytics_inpage_linkid.js", "google-analytics.com/inpage_linkid.js" ] - ], - [ - "google-ima.js", - [ + }, + { + "dialects": { + "adg": "google-ima3", + "ubo": "google-ima.js" + }, + "hints": [ + "google-ima.js", "google-ima3", - "ubo-google-ima.js", - "google-ima.js" + "ubo-google-ima.js" ] - ], - [ - "googlesyndication_adsbygoogle.js", - [ + }, + { + "dialects": { + "adg": "googlesyndication-adsbygoogle", + "ubo": "googlesyndication_adsbygoogle.js" + }, + "hints": [ + "googlesyndication_adsbygoogle.js", "googlesyndication.com/adsbygoogle.js", "googlesyndication-adsbygoogle", - "ubo-googlesyndication_adsbygoogle.js", - "googlesyndication_adsbygoogle.js" + "ubo-googlesyndication_adsbygoogle.js" ] - ], - [ - "googletagservices_gpt.js", - [ + }, + { + "dialects": { + "adg": "googletagservices-gpt", + "ubo": "googletagservices_gpt.js" + }, + "hints": [ + "googletagservices_gpt.js", "googletagservices.com/gpt.js", "googletagservices-gpt", - "ubo-googletagservices_gpt.js", - "googletagservices_gpt.js" - ] - ], - [ - "hd-main.js", - [] - ], - [ - "nobab.js", - [ + "ubo-googletagservices_gpt.js" + ] + }, + { + "dialects": { + "adg": "prevent-bab", + "ubo": "nobab.js" + }, + "hints": [ + "nobab.js", "bab-defuser.js", "prevent-bab.js", "prevent-bab", - "nobab.js", "ubo-nobab.js", "ubo-bab-defuser.js", "ubo-nobab", "ubo-bab-defuser" ] - ], - [ - "nobab2.js", - [] - ], - [ - "noeval.js", - [] - ], - [ - "noeval-silent.js", - [ - "silent-noeval.js", - "noeval", + }, + { + "dialects": { + "adg": "prevent-bab2", + "ubo": "nobab2.js" + }, + "hints": [ + "nobab2.js", + "prevent-bab2" + ] + }, + { + "dialects": { + "adg": "noeval", + "ubo": "noeval.js" + }, + "hints": [ "noeval.js", + "noeval", + "silent-noeval.js", "ubo-noeval.js", "ubo-silent-noeval.js", "ubo-noeval", "ubo-silent-noeval" ] - ], - [ - "nofab.js", - [ + }, + { + "dialects": { + "ubo": "noeval-silent.js" + }, + "hints": [ + "noeval-silent.js", + "silent-noeval.js" + ] + }, + { + "dialects": { + "adg": "prevent-fab-3.2.0", + "ubo": "nofab.js" + }, + "hints": [ + "nofab.js", "fuckadblock.js-3.2.0", "prevent-fab-3.2.0", - "nofab.js", "ubo-nofab.js", "ubo-fuckadblock.js-3.2.0", "ubo-nofab" ] - ], - [ - "noop-0.1s.mp3", - [ + }, + { + "dialects": { + "ubo": "noop-0.1s.mp3" + }, + "hints": [ + "noop-0.1s.mp3", "noopmp3-0.1s", - "abp-resource:blank-mp3", - "blank-mp3" - ] - ], - [ - "noop-0.5s.mp3", - [] - ], - [ - "noop-1s.mp4", - [ + "abp-resource:blank-mp3" + ] + }, + { + "dialects": { + "adg": "noopmp4-1s", + "ubo": "noop-1s.mp4" + }, + "hints": [ + "noop-1s.mp4", "noopmp4-1s", "abp-resource:blank-mp4", - "noop-1s.mp4", "blank-mp4" ] - ], - [ - "noop.css", - [] - ], - [ - "noop.html", - [ - "noopframe", + }, + { + "dialects": { + "adg": "noopcss", + "ubo": "noop.css" + }, + "hints": [ + "noop.css", + "noopcss", + "blank-css" + ] + }, + { + "dialects": { + "adg": "noopframe", + "ubo": "noop.html" + }, + "hints": [ "noop.html", + "noopframe", "blank-html" ] - ], - [ - "noop.js", - [ + }, + { + "dialects": { + "adg": "noopjs", + "ubo": "noop.js" + }, + "hints": [ + "noop.js", "noopjs", "abp-resource:blank-js", - "noop.js", "blank-js" ] - ], - [ - "noop.json", - [ - "noopjson", - "noop.json" - ] - ], - [ - "noop.txt", - [ - "nooptext", + }, + { + "dialects": { + "adg": "noopjson", + "ubo": "noop.json" + }, + "hints": [ + "noop.json", + "noopjson" + ] + }, + { + "dialects": { + "adg": "nooptext", + "ubo": "noop.txt" + }, + "hints": [ "noop.txt", + "nooptext", "blank-text" ] - ], - [ - "noop-vast2.xml", - [ - "noopvast-2.0", - "noop-vast2.xml" - ] - ], - [ - "noop-vast3.xml", - [ - "noopvast-3.0", - "noop-vast3.xml" - ] - ], - [ - "noop-vast4.xml", - [ - "noopvast-4.0", - "noop-vast4.xml" - ] - ], - [ - "noop-vmap1.xml", - [ + }, + { + "dialects": { + "adg": "noopvast-2.0", + "ubo": "noop-vast2.xml" + }, + "hints": [ + "noop-vast2.xml", + "noopvast-2.0" + ] + }, + { + "dialects": { + "adg": "noopvast-3.0", + "ubo": "noop-vast3.xml" + }, + "hints": [ + "noop-vast3.xml", + "noopvast-3.0" + ] + }, + { + "dialects": { + "adg": "noopvast-4.0", + "ubo": "noop-vast4.xml" + }, + "hints": [ + "noop-vast4.xml", + "noopvast-4.0" + ] + }, + { + "dialects": { + "adg": "noopvmap-1.0", + "ubo": "noop-vmap1.xml" + }, + "hints": [ + "noop-vmap1.xml", "noop-vmap1.0.xml", - "noopvmap-1.0", - "noop-vmap1.xml" + "noopvmap-1.0" ] - ], - [ - "outbrain-widget.js", - [ + }, + { + "dialects": { + "ubo": "outbrain-widget.js" + }, + "hints": [ + "outbrain-widget.js", "widgets.outbrain.com/outbrain.js" ] - ], - [ - "popads.js", - [ + }, + { + "dialects": { + "ubo": "popads.js" + }, + "hints": [ + "popads.js", "popads.net.js", - "prevent-popads-net.js", - "prevent-popads-net", - "ubo-popads.net.js", - "ubo-popads.net" - ] - ], - [ - "popads-dummy.js", - [] - ], - [ - "prebid-ads.js", - [] - ], - [ - "scorecardresearch_beacon.js", - [ - "scorecardresearch.com/beacon.js" - ] - ] + "prevent-popads-net.js" + ] + }, + { + "dialects": { + "adg": "set-popads-dummy", + "ubo": "popads-dummy.js" + }, + "hints": [ + "popads-dummy.js", + "set-popads-dummy", + "ubo-popads-dummy.js", + "ubo-popads-dummy" + ] + }, + { + "dialects": { + "adg": "prebid-ads", + "ubo": "prebid-ads.js" + }, + "hints": [ + "prebid-ads.js", + "prebid-ads", + "ubo-prebid-ads.js" + ] + }, + { + "dialects": { + "adg": "scorecardresearch-beacon", + "ubo": "scorecardresearch_beacon.js" + }, + "hints": [ + "scorecardresearch_beacon.js", + "scorecardresearch.com/beacon.js", + "scorecardresearch-beacon", + "ubo-scorecardresearch_beacon.js" + ] + } ] \ No newline at end of file From 73acc6f4cc4f1914e71cbb70e3c16aa8d2376ca9 Mon Sep 17 00:00:00 2001 From: HoJeong Go Date: Mon, 27 Jan 2025 15:59:43 +0900 Subject: [PATCH 2/6] chore: remove unnecessary console.log --- src/converters/helpers.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/converters/helpers.js b/src/converters/helpers.js index be2533e..10ba0c0 100644 --- a/src/converters/helpers.js +++ b/src/converters/helpers.js @@ -16,8 +16,6 @@ function normalizeRedirect(name, dialect) { throw new Error(`The redirect resource dialect of "${dialect}" is not supported!`); } - console.log(name, dialect); - /** * @type {string[]} */ From c5255def9f1cd050d442a21ce55ef8604b31ca11 Mon Sep 17 00:00:00 2001 From: HoJeong Go Date: Mon, 27 Jan 2025 17:11:03 +0900 Subject: [PATCH 3/6] fix: type --- scripts/update.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/update.js b/scripts/update.js index 1187c2e..051e9e4 100644 --- a/scripts/update.js +++ b/scripts/update.js @@ -34,7 +34,7 @@ function extractRedirects(data) { console.log('Extracting resources...'); /** - * @type {Array<{ dialects: { adg: string; ubo: string; }; hints: string[]; }>} + * @type {Array<{ dialects: { adg?: string; ubo: string; }; hints: string[]; }>} */ const mappings = []; From c0ee8522fdb6842dc059efb605997eb92f9f3e6f Mon Sep 17 00:00:00 2001 From: HoJeong Go Date: Mon, 27 Jan 2025 17:12:51 +0900 Subject: [PATCH 4/6] chore: remove unused test --- test/unit/converters/helpers.spec.js | 16 +--------------- 1 file changed, 1 insertion(+), 15 deletions(-) diff --git a/test/unit/converters/helpers.spec.js b/test/unit/converters/helpers.spec.js index 7404ddf..cceb6dd 100644 --- a/test/unit/converters/helpers.spec.js +++ b/test/unit/converters/helpers.spec.js @@ -1,10 +1,6 @@ import { describe, it, expect } from 'bun:test'; -import { - generateResourcesMapping, - normalizeFilter, - normalizeRule, -} from '../../../src/converters/helpers.js'; +import { normalizeFilter, normalizeRule } from '../../../src/converters/helpers.js'; describe('normalizeFilter', () => { it('format params', () => { @@ -162,13 +158,3 @@ describe('normalizeRule', () => { }); }); }); - -describe('generateResourcesMapping', () => { - it('filters resources without file extension', () => { - const mapping = generateResourcesMapping(); - - for (const destination of mapping.values()) { - expect(destination.match(/\w+\.\w+|empty/)).not.toBe(null); - } - }); -}); From bd4959168229da7d46f2f6d1d32b3325d014b1c7 Mon Sep 17 00:00:00 2001 From: HoJeong Go Date: Mon, 27 Jan 2025 17:46:20 +0900 Subject: [PATCH 5/6] test: redirect resources aliases --- test/unit/converters/adguard.spec.js | 63 ++++++++++++++++++++++++++++ test/unit/converters/helpers.spec.js | 19 ++------- 2 files changed, 67 insertions(+), 15 deletions(-) diff --git a/test/unit/converters/adguard.spec.js b/test/unit/converters/adguard.spec.js index a65e6e0..6186aad 100644 --- a/test/unit/converters/adguard.spec.js +++ b/test/unit/converters/adguard.spec.js @@ -64,4 +64,67 @@ describe('adguard converter', () => { priority: 101, }); }); + + it('handles $redirect', async () => { + const resourcesPath = '/a'; + const { + rules: [ruleWithAbpAlias], + } = await convertWithAdguard(['||foo.com^$redirect=abp-resource:blank-mp3'], { + resourcesPath, + }); + expect(ruleWithAbpAlias).toEqual({ + action: { + type: 'redirect', + redirect: { + extensionPath: '/a/noop-0.1s.mp3', + }, + }, + condition: { + isUrlFilterCaseSensitive: false, + urlFilter: '||foo.com^', + }, + id: 1, + priority: 1001, + }); + + const { + rules: [ruleWithAdgAlias], + } = await convertWithAdguard(['||foo.com^$redirect=noopmp3-0.1s'], { + resourcesPath, + }); + expect(ruleWithAdgAlias).toEqual({ + action: { + type: 'redirect', + redirect: { + extensionPath: '/a/noop-0.1s.mp3', + }, + }, + condition: { + isUrlFilterCaseSensitive: false, + urlFilter: '||foo.com^', + }, + id: 1, + priority: 1001, + }); + + const { + rules: [ruleWithUboName], + } = await convertWithAdguard(['||foo.com^$redirect=noop-0.1s.mp3'], { + resourcesPath, + }); + expect(ruleWithUboName).toEqual({ + action: { + type: 'redirect', + redirect: { + extensionPath: '/a/noop-0.1s.mp3', + }, + }, + condition: { + isUrlFilterCaseSensitive: false, + urlFilter: '||foo.com^', + }, + id: 1, + priority: 1001, + }); + }); }); diff --git a/test/unit/converters/helpers.spec.js b/test/unit/converters/helpers.spec.js index cceb6dd..956d027 100644 --- a/test/unit/converters/helpers.spec.js +++ b/test/unit/converters/helpers.spec.js @@ -34,17 +34,6 @@ describe('normalizeFilter', () => { expect(normalizeFilter('TEST$match-case')).toEqual('TEST$match-case'); }); }); - - describe('with redirect param', () => { - it('replaces values with slashes', () => { - expect(normalizeFilter('test$redirect=scorecardresearch.com/beacon.js')).toEqual( - 'test$redirect=scorecardresearch_beacon.js', - ); - expect(normalizeFilter('test$redirect-rule=scorecardresearch.com/beacon.js')).toEqual( - 'test$redirect-rule=scorecardresearch_beacon.js', - ); - }); - }); }); describe('normalizeRule', () => { @@ -133,26 +122,26 @@ describe('normalizeRule', () => { }); }); - it('replaces extensionPath respecting existing dirname', () => { + it('respects extensionPath', () => { expect( normalizeRule( { action: { type: 'redirect', redirect: { - extensionPath: '/rule_resources/redirects/alias', + extensionPath: '/a/alias', }, }, }, { - resourcesMapping: new Map([['alias', 'test.js']]), + resourcesPath: '/rule_resources/redirects', }, ), ).toEqual({ action: { type: 'redirect', redirect: { - extensionPath: '/rule_resources/redirects/test.js', + extensionPath: '/rule_resources/redirects/alias', }, }, }); From 7ade65f69177de2650d1cada2f38b893a8c07af4 Mon Sep 17 00:00:00 2001 From: HoJeong Go Date: Mon, 27 Jan 2025 18:43:47 +0900 Subject: [PATCH 6/6] fix: preserve `$redirect-rule=` --- src/converters/helpers.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/converters/helpers.js b/src/converters/helpers.js index 10ba0c0..df64e21 100644 --- a/src/converters/helpers.js +++ b/src/converters/helpers.js @@ -76,7 +76,7 @@ export function normalizeFilter(filter, { mapping = DEFAULT_PARAM_MAPPING } = {} const indexOfRedirectRule = params.findIndex((p) => p.startsWith('redirect-rule=')); if (indexOfRedirectRule !== -1) { params[indexOfRedirect] = - 'redirect=' + normalizeRedirect(params[indexOfRedirect].slice(14), 'adg'); + 'redirect-rule=' + normalizeRedirect(params[indexOfRedirect].slice(14), 'adg'); } if (back.length === 0) {