diff --git a/.gitignore b/.gitignore index f529ab8304..0cd8149116 100644 --- a/.gitignore +++ b/.gitignore @@ -16,3 +16,6 @@ test-results .netlify # VS Code user config .vscode + +# Auto-generated scriptlets file (built from @adguard/scriptlets) +injected/src/features/scriptlets-minimal.js diff --git a/.gitmodules b/.gitmodules index 063005785a..e69de29bb2 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +0,0 @@ -[submodule "injected/src/features/Scriptlets"] - path = injected/src/features/Scriptlets - url = https://github.com/AdguardTeam/Scriptlets.git diff --git a/.prettierignore b/.prettierignore index 161611c702..3ee510be90 100644 --- a/.prettierignore +++ b/.prettierignore @@ -3,7 +3,6 @@ docs/**/* injected/src/types special-pages/pages/**/types injected/integration-test/extension/contentScope.js -injected/src/features/Scriptlets **/*.json **/*.md **/*.html diff --git a/.stylelintrc.json b/.stylelintrc.json index ff395d79d4..8b092df8e4 100644 --- a/.stylelintrc.json +++ b/.stylelintrc.json @@ -1,7 +1,7 @@ { "extends": ["stylelint-config-standard"], "plugins": ["stylelint-csstree-validator"], - "ignoreFiles": ["build/**/*.css", "Sources/**/*.css", "docs/**/*.css", "special-pages/pages/**/*/dist/*.css", "injected/src/features/Scriptlets/**/*"], + "ignoreFiles": ["build/**/*.css", "Sources/**/*.css", "docs/**/*.css", "special-pages/pages/**/*/dist/*.css"], "rules": { "csstree/validator": { "ignoreProperties": ["text-wrap", "view-transition-name"] diff --git a/build-output.eslint.config.js b/build-output.eslint.config.js index d90aa683b2..f9062ba5b9 100644 --- a/build-output.eslint.config.js +++ b/build-output.eslint.config.js @@ -2,9 +2,6 @@ // https://github.com/eslint/eslint/discussions/18806#discussioncomment-10848750 export default [ - { - ignores: ['injected/src/features/Scriptlets', 'injected/src/features/scriptlets.js'], - }, { languageOptions: { ecmaVersion: 'latest', diff --git a/eslint.config.js b/eslint.config.js index c6b6583c37..ce8aa72b26 100644 --- a/eslint.config.js +++ b/eslint.config.js @@ -23,8 +23,7 @@ export default tseslint.config( 'playwright-report', 'test-results', 'injected/src/types', - 'injected/src/features/Scriptlets', - 'injected/src/features/scriptlets.js', + 'injected/src/features/scriptlets-minimal.js', '.idea', ], }, diff --git a/injected/entry-points/integration.js b/injected/entry-points/integration.js index c7aaf755dd..ca4d79ace8 100644 --- a/injected/entry-points/integration.js +++ b/injected/entry-points/integration.js @@ -48,6 +48,7 @@ function generateConfig() { 'apiManipulation', 'duckPlayer', 'duckPlayerNative', + 'scriptlets', ], }, }; diff --git a/injected/integration-test/pages.spec.js b/injected/integration-test/pages.spec.js index e11e466177..8af8887a3b 100644 --- a/injected/integration-test/pages.spec.js +++ b/injected/integration-test/pages.spec.js @@ -97,4 +97,122 @@ test.describe('Test integration pages', () => { `./integration-test/test-pages/webcompat/config/modify-cookies.json`, ); }); + + // Scriptlet integration page tests + test('Set Cookie Scriptlet', async ({ page }, testInfo) => { + await testPage( + page, + testInfo, + 'scriptlets/pages/set-cookie.html', + './integration-test/test-pages/scriptlets/config/set-cookie.json', + ); + }); + + test('Set Local Storage Item Scriptlet', async ({ page }, testInfo) => { + await testPage( + page, + testInfo, + 'scriptlets/pages/set-local-storage-item.html', + './integration-test/test-pages/scriptlets/config/set-local-storage-item.json', + ); + }); + + test('Set Constant Scriptlet', async ({ page }, testInfo) => { + await testPage( + page, + testInfo, + 'scriptlets/pages/set-constant.html', + './integration-test/test-pages/scriptlets/config/set-constant.json', + ); + }); + + test('Trusted Set Cookie Scriptlet', async ({ page }, testInfo) => { + await testPage( + page, + testInfo, + 'scriptlets/pages/trusted-set-cookie.html', + './integration-test/test-pages/scriptlets/config/trusted-set-cookie.json', + ); + }); + + test('Remove Cookie Scriptlet', async ({ page }, testInfo) => { + await testPage( + page, + testInfo, + 'scriptlets/pages/remove-cookie.html', + './integration-test/test-pages/scriptlets/config/remove-cookie.json', + ); + }); + + test('Abort on Property Read Scriptlet', async ({ page }, testInfo) => { + await testPage( + page, + testInfo, + 'scriptlets/pages/abort-on-property-read.html', + './integration-test/test-pages/scriptlets/config/abort-on-property-read.json', + ); + }); + + test('Abort on Property Write Scriptlet', async ({ page }, testInfo) => { + await testPage( + page, + testInfo, + 'scriptlets/pages/abort-on-property-write.html', + './integration-test/test-pages/scriptlets/config/abort-on-property-write.json', + ); + }); + + test('Prevent Add Event Listener Scriptlet', async ({ page }, testInfo) => { + await testPage( + page, + testInfo, + 'scriptlets/pages/prevent-addEventListener.html', + './integration-test/test-pages/scriptlets/config/prevent-addEventListener.json', + ); + }); + + test('Prevent Set Timeout Scriptlet', async ({ page }, testInfo) => { + await testPage( + page, + testInfo, + 'scriptlets/pages/prevent-setTimeout.html', + './integration-test/test-pages/scriptlets/config/prevent-setTimeout.json', + ); + }); + + test('Prevent Window Open Scriptlet', async ({ page }, testInfo) => { + await testPage( + page, + testInfo, + 'scriptlets/pages/prevent-window-open.html', + './integration-test/test-pages/scriptlets/config/prevent-window-open.json', + ); + }); + + test('Prevent Fetch Scriptlet', async ({ page }, testInfo) => { + await testPage( + page, + testInfo, + 'scriptlets/pages/prevent-fetch.html', + './integration-test/test-pages/scriptlets/config/prevent-fetch.json', + ); + }); + + test('Remove Node Text Scriptlet', async ({ page }, testInfo) => { + await testPage( + page, + testInfo, + 'scriptlets/pages/remove-node-text.html', + './integration-test/test-pages/scriptlets/config/remove-node-text.json', + ); + }); + + test('Abort Current Inline Script Scriptlet', async ({ page }, testInfo) => { + await testPage( + page, + testInfo, + 'scriptlets/pages/abort-current-inline-script.html', + './integration-test/test-pages/scriptlets/config/abort-current-inline-script.json', + ); + }); }); diff --git a/injected/integration-test/test-pages/scriptlets/config/abort-current-inline-script.json b/injected/integration-test/test-pages/scriptlets/config/abort-current-inline-script.json new file mode 100644 index 0000000000..f5dccfc8c8 --- /dev/null +++ b/injected/integration-test/test-pages/scriptlets/config/abort-current-inline-script.json @@ -0,0 +1,39 @@ +{ + "readme": "This config tests the abortCurrentInlineScript scriptlet", + "version": 1, + "unprotectedTemporary": [], + "features": { + "scriptlets": { + "exceptions": [], + "state": "enabled", + "settings": { + "scriptlets": [], + "conditionalChanges": [ + { + "condition": [ + { + "domain": "localhost" + }, + { + "domain": "privacy-test-pages.site" + } + ], + "patchSettings": [ + { + "op": "add", + "path": "/scriptlets/-", + "value": { + "name": "abortCurrentInlineScript", + "attrs": { + "property": "document.createElement", + "search": "badScript" + } + } + } + ] + } + ] + } + } + } +} diff --git a/injected/integration-test/test-pages/scriptlets/config/abort-on-property-read.json b/injected/integration-test/test-pages/scriptlets/config/abort-on-property-read.json new file mode 100644 index 0000000000..ef685334eb --- /dev/null +++ b/injected/integration-test/test-pages/scriptlets/config/abort-on-property-read.json @@ -0,0 +1,38 @@ +{ + "readme": "This config tests the abortOnPropertyRead scriptlet", + "version": 1, + "unprotectedTemporary": [], + "features": { + "scriptlets": { + "exceptions": [], + "state": "enabled", + "settings": { + "scriptlets": [], + "conditionalChanges": [ + { + "condition": [ + { + "domain": "localhost" + }, + { + "domain": "privacy-test-pages.site" + } + ], + "patchSettings": [ + { + "op": "add", + "path": "/scriptlets/-", + "value": { + "name": "abortOnPropertyRead", + "attrs": { + "property": "testBadProperty" + } + } + } + ] + } + ] + } + } + } +} diff --git a/injected/integration-test/test-pages/scriptlets/config/abort-on-property-write.json b/injected/integration-test/test-pages/scriptlets/config/abort-on-property-write.json new file mode 100644 index 0000000000..7e56b52a45 --- /dev/null +++ b/injected/integration-test/test-pages/scriptlets/config/abort-on-property-write.json @@ -0,0 +1,38 @@ +{ + "readme": "This config tests the abortOnPropertyWrite scriptlet", + "version": 1, + "unprotectedTemporary": [], + "features": { + "scriptlets": { + "exceptions": [], + "state": "enabled", + "settings": { + "scriptlets": [], + "conditionalChanges": [ + { + "condition": [ + { + "domain": "localhost" + }, + { + "domain": "privacy-test-pages.site" + } + ], + "patchSettings": [ + { + "op": "add", + "path": "/scriptlets/-", + "value": { + "name": "abortOnPropertyWrite", + "attrs": { + "property": "testWriteProperty" + } + } + } + ] + } + ] + } + } + } +} diff --git a/injected/integration-test/test-pages/scriptlets/config/prevent-addEventListener.json b/injected/integration-test/test-pages/scriptlets/config/prevent-addEventListener.json new file mode 100644 index 0000000000..f31ec586ed --- /dev/null +++ b/injected/integration-test/test-pages/scriptlets/config/prevent-addEventListener.json @@ -0,0 +1,39 @@ +{ + "readme": "This config tests the preventAddEventListener scriptlet", + "version": 1, + "unprotectedTemporary": [], + "features": { + "scriptlets": { + "exceptions": [], + "state": "enabled", + "settings": { + "scriptlets": [], + "conditionalChanges": [ + { + "condition": [ + { + "domain": "localhost" + }, + { + "domain": "privacy-test-pages.site" + } + ], + "patchSettings": [ + { + "op": "add", + "path": "/scriptlets/-", + "value": { + "name": "preventAddEventListener", + "attrs": { + "typeSearch": "click", + "listenerSearch": "badListener" + } + } + } + ] + } + ] + } + } + } +} diff --git a/injected/integration-test/test-pages/scriptlets/config/prevent-fetch.json b/injected/integration-test/test-pages/scriptlets/config/prevent-fetch.json new file mode 100644 index 0000000000..4466645971 --- /dev/null +++ b/injected/integration-test/test-pages/scriptlets/config/prevent-fetch.json @@ -0,0 +1,38 @@ +{ + "readme": "This config tests the preventFetch scriptlet", + "version": 1, + "unprotectedTemporary": [], + "features": { + "scriptlets": { + "exceptions": [], + "state": "enabled", + "settings": { + "scriptlets": [], + "conditionalChanges": [ + { + "condition": [ + { + "domain": "localhost" + }, + { + "domain": "privacy-test-pages.site" + } + ], + "patchSettings": [ + { + "op": "add", + "path": "/scriptlets/-", + "value": { + "name": "preventFetch", + "attrs": { + "propsToMatch": "url:/blocked-url" + } + } + } + ] + } + ] + } + } + } +} diff --git a/injected/integration-test/test-pages/scriptlets/config/prevent-setTimeout.json b/injected/integration-test/test-pages/scriptlets/config/prevent-setTimeout.json new file mode 100644 index 0000000000..cc27ddba7a --- /dev/null +++ b/injected/integration-test/test-pages/scriptlets/config/prevent-setTimeout.json @@ -0,0 +1,38 @@ +{ + "readme": "This config tests the preventSetTimeout scriptlet", + "version": 1, + "unprotectedTemporary": [], + "features": { + "scriptlets": { + "exceptions": [], + "state": "enabled", + "settings": { + "scriptlets": [], + "conditionalChanges": [ + { + "condition": [ + { + "domain": "localhost" + }, + { + "domain": "privacy-test-pages.site" + } + ], + "patchSettings": [ + { + "op": "add", + "path": "/scriptlets/-", + "value": { + "name": "preventSetTimeout", + "attrs": { + "matchCallback": "badTimeout" + } + } + } + ] + } + ] + } + } + } +} diff --git a/injected/integration-test/test-pages/scriptlets/config/prevent-window-open.json b/injected/integration-test/test-pages/scriptlets/config/prevent-window-open.json new file mode 100644 index 0000000000..0ddc8b1886 --- /dev/null +++ b/injected/integration-test/test-pages/scriptlets/config/prevent-window-open.json @@ -0,0 +1,36 @@ +{ + "readme": "This config tests the preventWindowOpen scriptlet", + "version": 1, + "unprotectedTemporary": [], + "features": { + "scriptlets": { + "exceptions": [], + "state": "enabled", + "settings": { + "scriptlets": [], + "conditionalChanges": [ + { + "condition": [ + { + "domain": "localhost" + }, + { + "domain": "privacy-test-pages.site" + } + ], + "patchSettings": [ + { + "op": "add", + "path": "/scriptlets/-", + "value": { + "name": "preventWindowOpen", + "attrs": {} + } + } + ] + } + ] + } + } + } +} diff --git a/injected/integration-test/test-pages/scriptlets/config/remove-cookie.json b/injected/integration-test/test-pages/scriptlets/config/remove-cookie.json new file mode 100644 index 0000000000..febbfcd358 --- /dev/null +++ b/injected/integration-test/test-pages/scriptlets/config/remove-cookie.json @@ -0,0 +1,38 @@ +{ + "readme": "This config tests the removeCookie scriptlet", + "version": 1, + "unprotectedTemporary": [], + "features": { + "scriptlets": { + "exceptions": [], + "state": "enabled", + "settings": { + "scriptlets": [], + "conditionalChanges": [ + { + "condition": [ + { + "domain": "localhost" + }, + { + "domain": "privacy-test-pages.site" + } + ], + "patchSettings": [ + { + "op": "add", + "path": "/scriptlets/-", + "value": { + "name": "removeCookie", + "attrs": { + "match": "unwantedCookie" + } + } + } + ] + } + ] + } + } + } +} diff --git a/injected/integration-test/test-pages/scriptlets/config/remove-node-text.json b/injected/integration-test/test-pages/scriptlets/config/remove-node-text.json new file mode 100644 index 0000000000..840184e98e --- /dev/null +++ b/injected/integration-test/test-pages/scriptlets/config/remove-node-text.json @@ -0,0 +1,39 @@ +{ + "readme": "This config tests the removeNodeText scriptlet", + "version": 1, + "unprotectedTemporary": [], + "features": { + "scriptlets": { + "exceptions": [], + "state": "enabled", + "settings": { + "scriptlets": [], + "conditionalChanges": [ + { + "condition": [ + { + "domain": "localhost" + }, + { + "domain": "privacy-test-pages.site" + } + ], + "patchSettings": [ + { + "op": "add", + "path": "/scriptlets/-", + "value": { + "name": "removeNodeText", + "attrs": { + "nodeName": "script", + "textMatch": "badScriptContent" + } + } + } + ] + } + ] + } + } + } +} diff --git a/injected/integration-test/test-pages/scriptlets/config/set-constant.json b/injected/integration-test/test-pages/scriptlets/config/set-constant.json new file mode 100644 index 0000000000..cfb07786cb --- /dev/null +++ b/injected/integration-test/test-pages/scriptlets/config/set-constant.json @@ -0,0 +1,39 @@ +{ + "readme": "This config tests the setConstant scriptlet", + "version": 1, + "unprotectedTemporary": [], + "features": { + "scriptlets": { + "exceptions": [], + "state": "enabled", + "settings": { + "scriptlets": [], + "conditionalChanges": [ + { + "condition": [ + { + "domain": "localhost" + }, + { + "domain": "privacy-test-pages.site" + } + ], + "patchSettings": [ + { + "op": "add", + "path": "/scriptlets/-", + "value": { + "name": "setConstant", + "attrs": { + "property": "testConstant", + "value": "false" + } + } + } + ] + } + ] + } + } + } +} diff --git a/injected/integration-test/test-pages/scriptlets/config/set-cookie.json b/injected/integration-test/test-pages/scriptlets/config/set-cookie.json new file mode 100644 index 0000000000..9135f3f70d --- /dev/null +++ b/injected/integration-test/test-pages/scriptlets/config/set-cookie.json @@ -0,0 +1,51 @@ +{ + "readme": "This config tests the setCookie scriptlet", + "version": 1, + "unprotectedTemporary": [], + "features": { + "scriptlets": { + "exceptions": [], + "state": "enabled", + "settings": { + "scriptlets": [], + "conditionalChanges": [ + { + "condition": [ + { + "domain": "localhost" + }, + { + "domain": "privacy-test-pages.site" + } + ], + "patchSettings": [ + { + "op": "add", + "path": "/scriptlets/-", + "value": { + "name": "setCookie", + "attrs": { + "name": "testCookie", + "value": "yes" + } + } + }, + { + "op": "add", + "path": "/scriptlets/-", + "value": { + "name": "setCookie", + "attrs": { + "name": "pathCookie", + "value": "enabled", + "path": "/" + } + } + } + ] + } + ] + } + } + } +} diff --git a/injected/integration-test/test-pages/scriptlets/config/set-local-storage-item.json b/injected/integration-test/test-pages/scriptlets/config/set-local-storage-item.json new file mode 100644 index 0000000000..d2c88ac58f --- /dev/null +++ b/injected/integration-test/test-pages/scriptlets/config/set-local-storage-item.json @@ -0,0 +1,39 @@ +{ + "readme": "This config tests the setLocalStorageItem scriptlet", + "version": 1, + "unprotectedTemporary": [], + "features": { + "scriptlets": { + "exceptions": [], + "state": "enabled", + "settings": { + "scriptlets": [], + "conditionalChanges": [ + { + "condition": [ + { + "domain": "localhost" + }, + { + "domain": "privacy-test-pages.site" + } + ], + "patchSettings": [ + { + "op": "add", + "path": "/scriptlets/-", + "value": { + "name": "setLocalStorageItem", + "attrs": { + "key": "testKey", + "value": "true" + } + } + } + ] + } + ] + } + } + } +} diff --git a/injected/integration-test/test-pages/scriptlets/config/trusted-set-cookie.json b/injected/integration-test/test-pages/scriptlets/config/trusted-set-cookie.json new file mode 100644 index 0000000000..f8cae777a2 --- /dev/null +++ b/injected/integration-test/test-pages/scriptlets/config/trusted-set-cookie.json @@ -0,0 +1,50 @@ +{ + "readme": "This config tests the trustedSetCookie scriptlet", + "version": 1, + "unprotectedTemporary": [], + "features": { + "scriptlets": { + "exceptions": [], + "state": "enabled", + "settings": { + "scriptlets": [], + "conditionalChanges": [ + { + "condition": [ + { + "domain": "localhost" + }, + { + "domain": "privacy-test-pages.site" + } + ], + "patchSettings": [ + { + "op": "add", + "path": "/scriptlets/-", + "value": { + "name": "trustedSetCookie", + "attrs": { + "name": "trustedCookie", + "value": "trustedValue" + } + } + }, + { + "op": "add", + "path": "/scriptlets/-", + "value": { + "name": "trustedSetCookie", + "attrs": { + "name": "timestampCookie", + "value": "$now$" + } + } + } + ] + } + ] + } + } + } +} diff --git a/injected/integration-test/test-pages/scriptlets/index.html b/injected/integration-test/test-pages/scriptlets/index.html new file mode 100644 index 0000000000..df37760f88 --- /dev/null +++ b/injected/integration-test/test-pages/scriptlets/index.html @@ -0,0 +1,29 @@ + + + + + + Scriptlets Integration Tests + + + +

[Home]

+

Scriptlets Integration Tests

+ + + \ No newline at end of file diff --git a/injected/integration-test/test-pages/scriptlets/pages/abort-current-inline-script.html b/injected/integration-test/test-pages/scriptlets/pages/abort-current-inline-script.html new file mode 100644 index 0000000000..d523be4f0a --- /dev/null +++ b/injected/integration-test/test-pages/scriptlets/pages/abort-current-inline-script.html @@ -0,0 +1,55 @@ + + + + + + Abort Current Inline Script Scriptlet Test + + + + +

[Scriptlets]

+ +

This page verifies that the abort-current-inline-script scriptlet works properly given the config.

+ + + + \ No newline at end of file diff --git a/injected/integration-test/test-pages/scriptlets/pages/abort-on-property-read.html b/injected/integration-test/test-pages/scriptlets/pages/abort-on-property-read.html new file mode 100644 index 0000000000..96d98cc284 --- /dev/null +++ b/injected/integration-test/test-pages/scriptlets/pages/abort-on-property-read.html @@ -0,0 +1,56 @@ + + + + + + Abort on Property Read Scriptlet Test + + + + +

[Scriptlets]

+ +

This page verifies that the abort-on-property-read scriptlet works properly given the config.

+ + + + \ No newline at end of file diff --git a/injected/integration-test/test-pages/scriptlets/pages/abort-on-property-write.html b/injected/integration-test/test-pages/scriptlets/pages/abort-on-property-write.html new file mode 100644 index 0000000000..5174c58286 --- /dev/null +++ b/injected/integration-test/test-pages/scriptlets/pages/abort-on-property-write.html @@ -0,0 +1,56 @@ + + + + + + Abort on Property Write Scriptlet Test + + + + +

[Scriptlets]

+ +

This page verifies that the abort-on-property-write scriptlet works properly given the config.

+ + + + \ No newline at end of file diff --git a/injected/integration-test/test-pages/scriptlets/pages/prevent-addEventListener.html b/injected/integration-test/test-pages/scriptlets/pages/prevent-addEventListener.html new file mode 100644 index 0000000000..64867966af --- /dev/null +++ b/injected/integration-test/test-pages/scriptlets/pages/prevent-addEventListener.html @@ -0,0 +1,60 @@ + + + + + + Prevent Add Event Listener Scriptlet Test + + + + +

[Scriptlets]

+ +

This page verifies that the prevent-addEventListener scriptlet works properly given the config.

+ + + + + + diff --git a/injected/integration-test/test-pages/scriptlets/pages/prevent-fetch.html b/injected/integration-test/test-pages/scriptlets/pages/prevent-fetch.html new file mode 100644 index 0000000000..d8d4235ad2 --- /dev/null +++ b/injected/integration-test/test-pages/scriptlets/pages/prevent-fetch.html @@ -0,0 +1,57 @@ + + + + + + Prevent Fetch Scriptlet Test + + + + +

[Scriptlets]

+ +

This page verifies that the prevent-fetch scriptlet works properly given the config.

+ + + + \ No newline at end of file diff --git a/injected/integration-test/test-pages/scriptlets/pages/prevent-setTimeout.html b/injected/integration-test/test-pages/scriptlets/pages/prevent-setTimeout.html new file mode 100644 index 0000000000..656b417201 --- /dev/null +++ b/injected/integration-test/test-pages/scriptlets/pages/prevent-setTimeout.html @@ -0,0 +1,50 @@ + + + + + + Prevent Set Timeout Scriptlet Test + + + + +

[Scriptlets]

+ +

This page verifies that the prevent-setTimeout scriptlet works properly given the config.

+ + + + \ No newline at end of file diff --git a/injected/integration-test/test-pages/scriptlets/pages/prevent-window-open.html b/injected/integration-test/test-pages/scriptlets/pages/prevent-window-open.html new file mode 100644 index 0000000000..6887ff9a91 --- /dev/null +++ b/injected/integration-test/test-pages/scriptlets/pages/prevent-window-open.html @@ -0,0 +1,51 @@ + + + + + + Prevent Window Open Scriptlet Test + + + + +

[Scriptlets]

+ +

This page verifies that the prevent-window-open scriptlet works properly given the config.

+ + + + \ No newline at end of file diff --git a/injected/integration-test/test-pages/scriptlets/pages/remove-cookie.html b/injected/integration-test/test-pages/scriptlets/pages/remove-cookie.html new file mode 100644 index 0000000000..e6ff6e80c0 --- /dev/null +++ b/injected/integration-test/test-pages/scriptlets/pages/remove-cookie.html @@ -0,0 +1,46 @@ + + + + + + Remove Cookie Scriptlet Test + + + + + +

[Scriptlets]

+ +

This page verifies that the remove-cookie scriptlet works properly given the config.

+ + + + \ No newline at end of file diff --git a/injected/integration-test/test-pages/scriptlets/pages/remove-node-text.html b/injected/integration-test/test-pages/scriptlets/pages/remove-node-text.html new file mode 100644 index 0000000000..05a5ed7ccb --- /dev/null +++ b/injected/integration-test/test-pages/scriptlets/pages/remove-node-text.html @@ -0,0 +1,56 @@ + + + + + + Remove Node Text Scriptlet Test + + + + +

[Scriptlets]

+ +

This page verifies that the remove-node-text scriptlet works properly given the config.

+ + + + + + + + + + \ No newline at end of file diff --git a/injected/integration-test/test-pages/scriptlets/pages/set-constant.html b/injected/integration-test/test-pages/scriptlets/pages/set-constant.html new file mode 100644 index 0000000000..4a1b172099 --- /dev/null +++ b/injected/integration-test/test-pages/scriptlets/pages/set-constant.html @@ -0,0 +1,52 @@ + + + + + + Set Constant Scriptlet Test + + + + +

[Scriptlets]

+ +

This page verifies that the set-constant scriptlet works properly given the config.

+ + + + diff --git a/injected/integration-test/test-pages/scriptlets/pages/set-cookie.html b/injected/integration-test/test-pages/scriptlets/pages/set-cookie.html new file mode 100644 index 0000000000..7d0ffc7a11 --- /dev/null +++ b/injected/integration-test/test-pages/scriptlets/pages/set-cookie.html @@ -0,0 +1,57 @@ + + + + + + Set Cookie Scriptlet Test + + + + +

[Scriptlets]

+ +

This page verifies that the set-cookie scriptlet works properly given the config.

+ + + + diff --git a/injected/integration-test/test-pages/scriptlets/pages/set-local-storage-item.html b/injected/integration-test/test-pages/scriptlets/pages/set-local-storage-item.html new file mode 100644 index 0000000000..13df324b3a --- /dev/null +++ b/injected/integration-test/test-pages/scriptlets/pages/set-local-storage-item.html @@ -0,0 +1,34 @@ + + + + + + Set Local Storage Item Scriptlet Test + + + + +

[Scriptlets]

+ +

This page verifies that the set-local-storage-item scriptlet works properly given the config.

+ + + + diff --git a/injected/integration-test/test-pages/scriptlets/pages/trusted-set-cookie.html b/injected/integration-test/test-pages/scriptlets/pages/trusted-set-cookie.html new file mode 100644 index 0000000000..e6ad459d4e --- /dev/null +++ b/injected/integration-test/test-pages/scriptlets/pages/trusted-set-cookie.html @@ -0,0 +1,62 @@ + + + + + + Trusted Set Cookie Scriptlet Test + + + + +

[Scriptlets]

+ +

This page verifies that the trusted-set-cookie scriptlet works properly given the config.

+ + + + \ No newline at end of file diff --git a/injected/package.json b/injected/package.json index 491aa6d4d0..c9ca51755d 100644 --- a/injected/package.json +++ b/injected/package.json @@ -3,8 +3,8 @@ "scripts": { "postinstall": "npm run copy-sjcl", "copy-sjcl": "node scripts/generateSJCL.js", - "checkout-submodules": "git submodule update --init --recursive --no-fetch", - "build": "npm run checkout-submodules && npm run build-types && npm run build-locales && npm run bundle-trackers && npm run bundle-entry-points", + "build": "npm run extract-scriptlets && npm run build-types && npm run build-locales && npm run bundle-trackers && npm run bundle-entry-points", + "extract-scriptlets": "node scripts/extract-scriptlets.js", "bundle-config": "node scripts/bundleConfig.mjs", "bundle-entry-points": "node scripts/entry-points.js", "build-chrome-mv3": "node scripts/entry-points.js", diff --git a/injected/scripts/extract-scriptlets.js b/injected/scripts/extract-scriptlets.js new file mode 100644 index 0000000000..c178ac1e6f --- /dev/null +++ b/injected/scripts/extract-scriptlets.js @@ -0,0 +1,72 @@ +#!/usr/bin/env node + +/** + * Build-time script to extract only the scriptlet functions we actually use + * This creates a minimal bundle instead of including the entire @adguard/scriptlets package + */ + +import { scriptlets } from '@adguard/scriptlets'; +import { writeFileSync } from 'fs'; +import { join } from 'path'; + +// List of scriptlet functions we actually use +const NEEDED_FUNCTIONS = [ + 'set-cookie', + 'trusted-set-cookie', + 'set-cookie-reload', + 'remove-cookie', + 'set-constant', + 'set-local-storage-item', + 'abort-current-inline-script', + 'abort-on-property-read', + 'abort-on-property-write', + 'prevent-addEventListener', + 'prevent-window-open', + 'prevent-setTimeout', + 'remove-node-text', + 'prevent-fetch', +]; + +// Generate the minimal scriptlets module +function generateMinimalScriptlets() { + const functions = []; + + for (const functionName of NEEDED_FUNCTIONS) { + const func = scriptlets.getScriptletFunction(functionName); + if (!func) { + console.warn(`Warning: Function ${functionName} not found`); + continue; + } + + // Convert kebab-case to camelCase for export names + const exportName = functionName.replace(/-([a-z])/g, (_, letter) => letter.toUpperCase()); + + // Get the function source code + const functionSource = func.toString(); + + // Add the function + functions.push(`// ${functionName}`); + functions.push(`export const ${exportName} = ${functionSource};`); + functions.push(''); + } + + const moduleContent = `// @ts-nocheck +/** + * Minimal scriptlets module - AUTO-GENERATED + * Contains only the scriptlet functions actually used by this project + * Generated from @adguard/scriptlets v${process.env.npm_package_dependencies__adguard_scriptlets || 'unknown'} + * + * TypeScript checking is disabled for this auto-generated file. + */ + +${functions.join('\n')} +`; + + return moduleContent; +} + +// Write the minimal module +const outputPath = join(process.cwd(), 'src/features/scriptlets-minimal.js'); +const moduleContent = generateMinimalScriptlets(); + +writeFileSync(outputPath, moduleContent, 'utf8'); diff --git a/injected/src/features/Scriptlets b/injected/src/features/Scriptlets deleted file mode 160000 index 70ec3c0f38..0000000000 --- a/injected/src/features/Scriptlets +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 70ec3c0f38ad1ac5e867429c6685be9c5ed788ea diff --git a/injected/src/features/scriptlets.js b/injected/src/features/scriptlets.js index 115793b363..29dbaf59b0 100644 --- a/injected/src/features/scriptlets.js +++ b/injected/src/features/scriptlets.js @@ -1,26 +1,30 @@ import ContentFeature from '../content-feature.js'; import { isBeingFramed } from '../utils.js'; -import { setCookie } from './Scriptlets/src/scriptlets/set-cookie.js'; -import { trustedSetCookie } from './Scriptlets/src/scriptlets/trusted-set-cookie.js'; -import { setCookieReload } from './Scriptlets/src/scriptlets/set-cookie-reload.js'; -import { removeCookie } from './Scriptlets/src/scriptlets/remove-cookie.js'; -import { setConstant } from './Scriptlets/src/scriptlets/set-constant.js'; -import { setLocalStorageItem } from './Scriptlets/src/scriptlets/set-local-storage-item.js'; -import { abortCurrentInlineScript } from './Scriptlets/src/scriptlets/abort-current-inline-script.js'; -import { abortOnPropertyRead } from './Scriptlets/src/scriptlets/abort-on-property-read.js'; -import { abortOnPropertyWrite } from './Scriptlets/src/scriptlets/abort-on-property-write.js'; -import { preventAddEventListener } from './Scriptlets/src/scriptlets/prevent-addEventListener.js'; -import { preventWindowOpen } from './Scriptlets/src/scriptlets/prevent-window-open.js'; -import { preventSetTimeout } from './Scriptlets/src/scriptlets/prevent-setTimeout.js'; -import { removeNodeText } from './Scriptlets/src/scriptlets/remove-node-text.js'; -import { preventFetch } from './Scriptlets/src/scriptlets/prevent-fetch.js'; + +// Import from our minimal scriptlets module (contains only functions we actually use) +import { + setCookie, + trustedSetCookie, + setCookieReload, + removeCookie, + setConstant, + setLocalStorageItem, + abortCurrentInlineScript, + abortOnPropertyRead, + abortOnPropertyWrite, + preventAddEventListener, + preventWindowOpen, + preventSetTimeout, + removeNodeText, + preventFetch, +} from './scriptlets-minimal.js'; export class Scriptlets extends ContentFeature { init() { if (isBeingFramed()) { return; } - /* @type {import('./Scriptlets/src/scriptlets/scriptlets.ts').Source} */ + /* @type {import('@adguard/scriptlets').Source} */ const source = { verbose: false, }; @@ -39,47 +43,48 @@ export class Scriptlets extends ContentFeature { // add debug flag to site breakage reports this.addDebugFlag(); + // The extracted scriptlets expect (source, args) where args is an array if (scriptlet.name === 'setCookie') { - setCookie(source, attrs.name, attrs.value, attrs.path, attrs.domain); + setCookie(source, [attrs.name, attrs.value, attrs.path, attrs.domain]); } if (scriptlet.name === 'trustedSetCookie') { - trustedSetCookie(source, attrs.name, attrs.value, attrs.path, attrs.domain); + trustedSetCookie(source, [attrs.name, attrs.value, attrs.path, attrs.domain]); } if (scriptlet.name === 'setCookieReload') { - setCookieReload(source, attrs.name, attrs.value, attrs.path, attrs.domain); + setCookieReload(source, [attrs.name, attrs.value, attrs.path, attrs.domain]); } if (scriptlet.name === 'removeCookie') { - removeCookie(source, attrs.match); + removeCookie(source, [attrs.match]); } if (scriptlet.name === 'setConstant') { - setConstant(source, attrs.property, attrs.value, attrs.stack, attrs.valueWrapper, attrs.setProxyTrap); + setConstant(source, [attrs.property, attrs.value, attrs.stack, attrs.valueWrapper, attrs.setProxyTrap]); } if (scriptlet.name === 'setLocalStorageItem') { - setLocalStorageItem(source, attrs.key, attrs.value); + setLocalStorageItem(source, [attrs.key, attrs.value]); } if (scriptlet.name === 'abortCurrentInlineScript') { - abortCurrentInlineScript(source, attrs.property, attrs.search); + abortCurrentInlineScript(source, [attrs.property, attrs.search]); } if (scriptlet.name === 'abortOnPropertyRead') { - abortOnPropertyRead(source, attrs.property); + abortOnPropertyRead(source, [attrs.property]); } if (scriptlet.name === 'abortOnPropertyWrite') { - abortOnPropertyWrite(source, attrs.property); + abortOnPropertyWrite(source, [attrs.property]); } if (scriptlet.name === 'preventAddEventListener') { - preventAddEventListener(source, attrs.typeSearch, attrs.listenerSearch, attrs.additionalArgName, attrs.additionalArgValue); + preventAddEventListener(source, [attrs.typeSearch, attrs.listenerSearch, attrs.additionalArgName, attrs.additionalArgValue]); } if (scriptlet.name === 'preventWindowOpen') { - preventWindowOpen(source, attrs.match, attrs.delay, attrs.replacement); + preventWindowOpen(source, [attrs.match, attrs.delay, attrs.replacement]); } if (scriptlet.name === 'preventSetTimeout') { - preventSetTimeout(source, attrs.matchCallback, attrs.matchDelay); + preventSetTimeout(source, [attrs.matchCallback, attrs.matchDelay]); } if (scriptlet.name === 'removeNodeText') { - removeNodeText(source, attrs.nodeName, attrs.textMatch, attrs.parentSelector); + removeNodeText(source, [attrs.nodeName, attrs.textMatch, attrs.parentSelector]); } if (scriptlet.name === 'preventFetch') { - preventFetch(source, attrs.propsToMatch, attrs.responseBody, attrs.responseType); + preventFetch(source, [attrs.propsToMatch, attrs.responseBody, attrs.responseType]); } } } diff --git a/package-lock.json b/package-lock.json index 4fd10871c0..7c2dd97a8b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -13,6 +13,7 @@ "types-generator" ], "dependencies": { + "@adguard/scriptlets": "^2.1.6", "immutable-json-patch": "^6.0.1", "urlpattern-polyfill": "^10.1.0" }, @@ -60,6 +61,110 @@ "version": "1.0.0", "license": "ISC" }, + "node_modules/@adguard/agtree": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/@adguard/agtree/-/agtree-3.2.1.tgz", + "integrity": "sha512-MeelXInvMLSO8xNLQesmBv3mrmjLO13uzFipgXkdTYWzQmhRMn6vkcx2XCNcU9oqzuhOufSc0Wsz5Mc23zdlTw==", + "license": "MIT", + "dependencies": { + "@adguard/css-tokenizer": "^1.2.0", + "camelcase-keys": "^7.0.2", + "clone-deep": "^4.0.1", + "is-ip": "3.1.0", + "json5": "^2.2.3", + "sprintf-js": "^1.1.3", + "tldts": "^5.7.112", + "xregexp": "^5.1.1", + "zod": "3.24.4" + }, + "engines": { + "node": ">=22" + } + }, + "node_modules/@adguard/agtree/node_modules/json5": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "license": "MIT", + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@adguard/agtree/node_modules/tldts": { + "version": "5.7.112", + "resolved": "https://registry.npmjs.org/tldts/-/tldts-5.7.112.tgz", + "integrity": "sha512-6VSJ/C0uBtc2PQlLsp4IT8MIk2UUh6qVeXB1HZtK+0HiXlAPzNcfF3p2WM9RqCO/2X1PIa4danlBLPoC2/Tc7A==", + "license": "MIT", + "dependencies": { + "tldts-core": "^5.7.112" + }, + "bin": { + "tldts": "bin/cli.js" + } + }, + "node_modules/@adguard/agtree/node_modules/tldts-core": { + "version": "5.7.112", + "resolved": "https://registry.npmjs.org/tldts-core/-/tldts-core-5.7.112.tgz", + "integrity": "sha512-mutrEUgG2sp0e/MIAnv9TbSLR0IPbvmAImpzqul5O/HJ2XM1/I1sajchQ/fbj0fPdA31IiuWde8EUhfwyldY1Q==", + "license": "MIT" + }, + "node_modules/@adguard/agtree/node_modules/xregexp": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/xregexp/-/xregexp-5.1.2.tgz", + "integrity": "sha512-6hGgEMCGhqCTFEJbqmWrNIPqfpdirdGWkqshu7fFZddmTSfgv5Sn9D2SaKloR79s5VUiUlpwzg3CM3G6D3VIlw==", + "license": "MIT", + "dependencies": { + "@babel/runtime-corejs3": "^7.26.9" + } + }, + "node_modules/@adguard/css-tokenizer": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@adguard/css-tokenizer/-/css-tokenizer-1.2.0.tgz", + "integrity": "sha512-cUj5j/AU5z/T4//5M6KnIJBpykAY4QbDsoiQ2DaWX/r2XkepMkTb8DhIbUHJD/QLGEyLeQLpi+nlxAgf4NTRRQ==", + "license": "MIT" + }, + "node_modules/@adguard/scriptlets": { + "version": "2.2.7", + "resolved": "https://registry.npmjs.org/@adguard/scriptlets/-/scriptlets-2.2.7.tgz", + "integrity": "sha512-UK7aNkbGOACPaJEDGKj5g9Zyl+zNTM0DZf2/6+RaMavnGDQuObtkBvzZO0/0G4BVqRDdstULlrgzazmaLeHukw==", + "license": "GPL-3.0", + "dependencies": { + "@adguard/agtree": "^3.2.1", + "@types/trusted-types": "^2.0.7", + "js-yaml": "^3.14.1" + } + }, + "node_modules/@adguard/scriptlets/node_modules/argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "license": "MIT", + "dependencies": { + "sprintf-js": "~1.0.2" + } + }, + "node_modules/@adguard/scriptlets/node_modules/js-yaml": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "license": "MIT", + "dependencies": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/@adguard/scriptlets/node_modules/sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", + "license": "BSD-3-Clause" + }, "node_modules/@apidevtools/json-schema-ref-parser": { "version": "11.7.2", "resolved": "https://registry.npmjs.org/@apidevtools/json-schema-ref-parser/-/json-schema-ref-parser-11.7.2.tgz", @@ -379,6 +484,18 @@ "node": ">=6.9.0" } }, + "node_modules/@babel/runtime-corejs3": { + "version": "7.27.6", + "resolved": "https://registry.npmjs.org/@babel/runtime-corejs3/-/runtime-corejs3-7.27.6.tgz", + "integrity": "sha512-vDVrlmRAY8z9Ul/HxT+8ceAru95LQgkSKiXkSYZvqtbkPSfhZJgpRp45Cldbh1GJ1kxzQkI70AqyrTI58KpaWQ==", + "license": "MIT", + "dependencies": { + "core-js-pure": "^3.30.2" + }, + "engines": { + "node": ">=6.9.0" + } + }, "node_modules/@babel/template": { "version": "7.27.2", "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.27.2.tgz", @@ -1772,6 +1889,12 @@ "integrity": "sha512-dISoDXWWQwUquiKsyZ4Ng+HX2KsPL7LyHKHQwgGFEA3IaKac4Obd+h2a/a6waisAoepJlBcx9paWqjA8/HVjCw==", "license": "MIT" }, + "node_modules/@types/trusted-types": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.7.tgz", + "integrity": "sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==", + "license": "MIT" + }, "node_modules/@types/unist": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.3.tgz", @@ -2789,7 +2912,6 @@ "version": "6.3.0", "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", - "dev": true, "license": "MIT", "engines": { "node": ">=10" @@ -2802,7 +2924,6 @@ "version": "7.0.2", "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-7.0.2.tgz", "integrity": "sha512-Rjs1H+A9R+Ig+4E/9oyB66UC5Mj9Xq3N//vcLf2WzgdTi/3gUu3Z9KoqmlrEG4VuuLK8wJHofxzdQXz/knhiYg==", - "dev": true, "license": "MIT", "dependencies": { "camelcase": "^6.3.0", @@ -2855,6 +2976,32 @@ "integrity": "sha512-saHYOzhIQs6wy2sVxTM6bUDsQO4F50V9RQ22qBpEdCW+I+/Wmke2HOl6lS6dTpdxVhb88/I6+Hs+438c3lfUow==", "license": "MIT" }, + "node_modules/clone-deep": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz", + "integrity": "sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==", + "license": "MIT", + "dependencies": { + "is-plain-object": "^2.0.4", + "kind-of": "^6.0.2", + "shallow-clone": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/clone-deep/node_modules/is-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "license": "MIT", + "dependencies": { + "isobject": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/color-convert": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", @@ -2905,6 +3052,17 @@ "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==", "license": "MIT" }, + "node_modules/core-js-pure": { + "version": "3.43.0", + "resolved": "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.43.0.tgz", + "integrity": "sha512-i/AgxU2+A+BbJdMxh3v7/vxi2SbFqxiFmg6VsDwYB4jkucrd1BZNA9a9gphC0fYMG5IBSgQcbQnk865VCLe7xA==", + "hasInstallScript": true, + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/core-js" + } + }, "node_modules/corser": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/corser/-/corser-2.0.1.tgz", @@ -3952,6 +4110,19 @@ "url": "https://opencollective.com/eslint" } }, + "node_modules/esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "license": "BSD-2-Clause", + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=4" + } + }, "node_modules/esquery": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz", @@ -4909,6 +5080,15 @@ "node": ">= 0.4" } }, + "node_modules/ip-regex": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ip-regex/-/ip-regex-4.3.0.tgz", + "integrity": "sha512-B9ZWJxHHOHUhUjCPrMpLD4xEq35bUTClHM1S6CBU5ixQnkZmwipwgc96vAd7AAGM9TGHvJR+Uss+/Ak6UphK+Q==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, "node_modules/is-array-buffer": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.4.tgz", @@ -5053,6 +5233,18 @@ "node": ">=0.10.0" } }, + "node_modules/is-ip": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-ip/-/is-ip-3.1.0.tgz", + "integrity": "sha512-35vd5necO7IitFPjd/YBeqwWnyDWbuLH9ZXQdMfDA8TEo7pv5X8yfrvVO3xbJbLUlERCMvf6X0hTUamQxCYJ9Q==", + "license": "MIT", + "dependencies": { + "ip-regex": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/is-negative-zero": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.3.tgz", @@ -5220,6 +5412,15 @@ "dev": true, "license": "ISC" }, + "node_modules/isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/jackspeak": { "version": "3.4.3", "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz", @@ -5370,7 +5571,6 @@ "version": "6.0.3", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", - "dev": true, "license": "MIT", "engines": { "node": ">=0.10.0" @@ -5491,7 +5691,6 @@ "version": "4.3.0", "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-4.3.0.tgz", "integrity": "sha512-hdN1wVrZbb29eBGiGjJbeP8JbKjq1urkHJ/LIP/NY48MZ1QVXUsQBV1G1zvYFHn1XE06cwjBsOI2K3Ulnj1YXQ==", - "dev": true, "license": "MIT", "engines": { "node": ">=8" @@ -6357,7 +6556,6 @@ "version": "5.1.1", "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-5.1.1.tgz", "integrity": "sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==", - "dev": true, "license": "MIT", "engines": { "node": ">=10" @@ -6773,6 +6971,18 @@ "node": ">= 0.4" } }, + "node_modules/shallow-clone": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-3.0.1.tgz", + "integrity": "sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==", + "license": "MIT", + "dependencies": { + "kind-of": "^6.0.2" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/shebang-command": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", @@ -6924,6 +7134,12 @@ "resolved": "special-pages", "link": true }, + "node_modules/sprintf-js": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.3.tgz", + "integrity": "sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==", + "license": "BSD-3-Clause" + }, "node_modules/string-width": { "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", @@ -7573,7 +7789,6 @@ "version": "1.4.0", "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-1.4.0.tgz", "integrity": "sha512-yGSza74xk0UG8k+pLh5oeoYirvIiWo5t0/o3zHHAO2tRDiZcxWP7fywNlXhqb6/r6sWvwi+RsyQMWhVLe4BVuA==", - "dev": true, "license": "(MIT OR CC0-1.0)", "engines": { "node": ">=10" @@ -8282,6 +8497,15 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/zod": { + "version": "3.24.4", + "resolved": "https://registry.npmjs.org/zod/-/zod-3.24.4.tgz", + "integrity": "sha512-OdqJE9UDRPwWsrHjLN2F8bPxvwJBK22EHLWtanu0LSYr5YqzsaaW3RMgmjwr8Rypg5k+meEJdSPXJZXE/yqOMg==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/colinhacks" + } + }, "special-pages": { "version": "1.0.0", "license": "ISC", diff --git a/package.json b/package.json index 072aa08a80..477c055f8f 100644 --- a/package.json +++ b/package.json @@ -19,7 +19,7 @@ "test-clean-tree": "npm run build && sh scripts/check-for-changes.sh", "docs": "typedoc", "docs-watch": "typedoc --watch", - "tsc": "tsc", + "tsc": "npm run --workspace=injected extract-scriptlets && tsc", "tsc-watch": "tsc --watch", "lint": "eslint . && npm run tsc && npm run lint-no-output-globals && npx prettier . --check", "lint-no-output-globals": "eslint --no-inline-config --config build-output.eslint.config.js Sources/ContentScopeScripts/dist/contentScope.js", @@ -54,6 +54,7 @@ "typescript-eslint": "^8.33.0" }, "dependencies": { + "@adguard/scriptlets": "^2.1.6", "immutable-json-patch": "^6.0.1", "urlpattern-polyfill": "^10.1.0" } diff --git a/tsconfig.json b/tsconfig.json index 6a96819b17..ffc1414e5d 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -37,8 +37,6 @@ "injected/integration-test/test-pages", "injected/playwright-report", "injected/integration-test/extension", - "injected/src/features/scriptlets.js", - "injected/src/features/Scriptlets/**/*", "special-pages/pages/**/public", "special-pages/playwright-report", "special-pages/test-results",