AdGuard Scriptlets and Redirect Resources
AdGuard's Scriptlets and Redirect resources library which provides extended capabilities for content blocking.
Scriptlets
Scriptlet is a JavaScript function which can be used in a declarative manner in AdGuard filtering rules.
AdGuard supports a lot of different scriptlets.
Please note, that in order to achieve cross-blocker compatibility, we also support syntax of uBO and ABP.
Syntax
Blocking rules
[domains]#%#//scriptlet(name[, arguments])
domains — optional, a list of domains where the rule should be applied;
name — required, a name of the scriptlet from AdGuard Scriptlets library;
arguments — optional, a list of string arguments (no other types of arguments are supported).
Remarks
-
The meaning of the arguments depends on the scriptlet.
-
Special characters in scriptlet argument must be escaped properly:
- valid:
'prop["nested"]'
"prop['nested']"
'prop[\'nested\']'
"prop[\"nested\"]"
- not valid:
'prop['nested']'
"prop["nested"]"
-
Scriptlet name and each of the arguments should be wrapped in quotes.
You can use either single or double quotes for the scriptlet name and arguments.
Single quote is recommended but not for cases when its usage makes readability worse,
e.g. ".css('display','block');" is more preferred then '.css(\'display\',\'block\');'.
Exception rules
[domains]#@%#//scriptlet([name[, arguments]])
domains — optional, a list of domains where the rule should be applied;
name — optional, a name of the scriptlet to except from the applying;
if not set, all scriptlets will not be applied;
arguments — optional, a list of string arguments to match the same blocking rule and disable it.
Examples
-
Apply the abort-on-property-read scriptlet on all pages of example.org and its subdomains,
and passes one argument to it (alert):
example.org#%#//scriptlet('abort-on-property-read', 'alert')
-
Remove the branding class from all div[class^="inner"] elements
on all pages of example.org and its subdomains:
example.org#%#//scriptlet('remove-class', 'branding', 'div[class^="inner"]')
-
Apply set-constant and set-cookie on any webpage,
but because of specific scriptlet exception rule
only set-constant scriptlet will be applied on example.org and its subdomains:
#%#//scriptlet('set-constant', 'adList', 'emptyArr')
#%#//scriptlet('set-cookie', 'accepted', 'true')
example.org#@%#//scriptlet('set-cookie')
-
Apply adjust-setInterval on any webpage,
and set-local-storage-item on all pages of example.com and its subdomains,
but there is also multiple scriptlet exception rule,
so no scriptlet rules will be applied on example.com and its subdomains:
#%#//scriptlet('adjust-setInterval', 'count', '*', '0.001')
example.com#%#//scriptlet('set-local-storage-item', 'ALLOW_COOKIES', 'false')
example.com#@%#//scriptlet()
Trusted scriptlets
Trusted scriptlets are scriptlets with extended functionality.
Their names are prefixed with trusted-, e.g trusted-click-element,
to be easily distinguished from common scriptlets.
Restriction
Trusted scriptlets application must be restricted due to dangerous nature of their capabilities.
Allowed sources of trusted scriptlets are:
- filters created by AdGuard Team,
- custom filters which were installed as
trusted,
- user rules.
Trusted scriptlets has no compatibility table as they are not compatible with any other blocker.
Trusted scriptlets list
Redirect resources
AdGuard is able to redirect web requests to a local "resource".
Syntax
AdGuard uses the same filtering rule syntax as uBlock Origin.
Also, it is compatible with ABP $rewrite=abp-resource modifier.
$redirect is a modifier for the basic filtering rules
so rules with this modifier support all other basic modifiers like $domain, $third-party, $script, etc.
The value of the $redirect modifier must be the name of the resource that will be used for redirection.
See the list of available redirect resources.
Priority of $redirect rules is described in the Knowledge Base.
Examples
||example.org/script.js$script,redirect=noopjs — redirects all requests to script.js
to the resource named noopjs.
||example.org/test.mp4$media,redirect=noopmp4-1s — requests to example.org/test.mp4 will be redirected
to the resource named noopmp4-1s.
uBlock Origin specifies additional resource name none that can disable other redirect rules.
AdGuard does not support it, use $badfilter to disable specific rules.
Development
How to build
Install dependencies:
pnpm install
Build dist:
pnpm build
In tsurlfilter directory install and link dependencies, link scriptlets,
move into package and build, and create tsurlfilter link.
lerna bootstrap
pnpm link --global "@adguard/scriptlets"
cd ./packages/tsurlfilter
pnpm build
pnpm link --global
In extension directory install dependencies, link packages and build
pnpm install
pnpm link --global "@adguard/scriptlets"
How to test
Some tests are run in QUnit, some in Vitest.
Run all tests:
pnpm test
-
QUnit is used for testing of scriptlets, redirects, and helpers:
pnpm test:qunit [scriptlets | redirects | helpers]
For scriptlets and redirects test run can be more specific:
// node test run
pnpm test:qunit scriptlets --name set-cookie
pnpm test:qunit redirects --name ati-smarttag
// gui test run
pnpm test:qunit scriptlets --name set-cookie --gui
pnpm test:qunit redirects --name ati-smarttag --gui
For debugging purposes after some test is running in gui mode,
you may change your scriptlet/redirect code, and without stopping the server
run in new terminal:
pnpm test:qunit scriptlets --name set-cookie --build
-
Run all jest tests:
pnpm test:vitest
or limit the testing — include may be specified in vitest.config.ts
or specify test name in command line, e.g.:
pnpm test:vitest -t isValidScriptletRule
To run browserstack tests create .env file or copy and rename .env-example.
Fill in <username> and <key> with data from your Browserstack profile.
Run next command:
pnpm browserstack
Tests run by jest should be named .spec.js, so they will be not included in the QUnit tests.
Debugging
Use debugger; statement where you need it, run
pnpm test
and open needed HTML file from tests/dist in your browser with devtools
How to link packages
Scriptlets library relies on external packages, such as @adguard/agtree.
During development, you might need to link these packages using pnpm link.
How to update wiki
There are two scripts to update wiki:
pnpm wiki:build-table — checks compatibility data updates and updates the compatibility table.
Should be run manually while the release preparation.
pnpm wiki:build-docs — updates wiki pages about-scriptlets.md and about-redirects.md.
They are being generated from JSDoc-type comments of corresponding scriptlets and redirects source files
due to @scriptlet/@redirect and @description tags. Runs automatically while the release build.
Usage
CoreLibs
For CoreLibs usage you should use dist/scriptlets.corelibs.json and dist/redirects.json.
File example:
{
"version": "1.0.0",
"scriptlets": [
{
"names": [
"abort-on-property-read",
"ubo-abort-on-property-read.js",
"abp-abort-on-property-read"
],
"scriptlet": "function() { ...code... }"
}
]
}
Schema:
{
"type": "object",
"properties": {
"version": {
"type": "string"
},
"scriptlets": {
"type": "array",
"items": {
"type": "object",
"properties": {
"names": {
"type": "array",
"items": {
"type": "string"
}
},
"scriptlet": {
"type": "string"
}
}
}
}
}
}
NPM module
Installation
You can install the library using
- Yarn:
yarn add @adguard/scriptlets
- NPM:
npm install @adguard/scriptlets
- PNPM:
pnpm add @adguard/scriptlets
API description
Scriptlets API
You are welcome to use scriptlets as a CJS modules or ESM modules:
const { scriptlets } = require('@adguard/scriptlets');
import { scriptlets } from '@adguard/scriptlets';
invoke()
declare function getScriptletCode(source: Source): string;
declare const scriptlets: {
invoke: typeof getScriptletCode;
};
where Source is:
interface Source {
name: string;
args: string[];
engine: string;
version: string;
verbose: boolean;
ruleText?: string;
domainName?: string;
uniqueId?: string;
api?: ContentScriptApi;
}
see also ContentScriptApi for more details.
getScriptletFunction()
declare function getScriptletFunction(name: any): string;
declare const scriptlets: {
getScriptletFunction: typeof getScriptletFunction;
};
Properties
SCRIPTLETS_VERSION
type: string
Current version of scriptlets library.
ContentScriptApi
API provided by CoreLibs content script.
This API is used to provide a set of utilities and shared state for scriptlets
running in the context of a web page. Particularly, it includes:
export interface ContentScriptApi {
readonly policy: PolicyApi;
readonly shared: Record<string, unknown>;
}
PolicyApi
Trusted Types Policy API utility.
This interface extends the native TrustedTypePolicy and TrustedTypePolicyFactory
to provide a more user-friendly API for working with Trusted Types. In case if
environment doesn't support Trusted Types API, it provides polyfilled methods
and properties to ensure compatibility.
export interface PolicyApi extends TrustedTypePolicy, TrustedTypePolicyFactory {
isSupported: boolean;
TrustedType: typeof TrustedType;
create(type: TrustedType, input: string): string;
convertAttributeToTrusted(
tagName: string,
attribute: string,
value: string,
elementNS?: string,
attrNS?: string,
): string;
convertPropertyToTrusted(
tagName: string,
property: string,
value: string,
elementNS?: string,
): string;
}
Redirects API
You are welcome to use redirects as a CJS modules or ESM modules:
const { Redirects } = require('@adguard/scriptlets/redirects');
import { Redirects, getRedirectFilename } from '@adguard/scriptlets/redirects';
Redirects class
import { Redirects } from '@adguard/scriptlets';
const redirects = new Redirects(rawYaml)
where rawYaml is a string with YAML content located in dist/redirects.yml.
getRedirect()
const redirect = redirects.getRedirect('noopjs');
isBlocking()
const isBlocking = redirect.isBlocking('click2load.html');
getRedirectFilename()
import { getRedirectFilename } from '@adguard/scriptlets/redirects';
declare function getRedirectFilename(name: string): string;
Validators API
isValidScriptletName()
import { isValidScriptletName } from '@adguard/scriptlets/validators';
declare function isValidScriptletName(name: string | null): boolean;
isValidScriptletRule()
declare function isValidScriptletRule(rule: string | ScriptletInjectionRule): boolean;
isAdgScriptletRule(), isUboScriptletRule(), isAbpSnippetRule()
declare function isAdgScriptletRule(rule: string): boolean;
declare function isUboScriptletRule(rule: string): boolean;
declare function isAbpSnippetRule(rule: string): boolean;
isValidAdgRedirectRule()
declare function isValidAdgRedirectRule(rule: string): boolean
isRedirectResourceCompatibleWithAdg()
declare function isRedirectResourceCompatibleWithAdg(redirectName: string): boolean;
Converters API
import {
convertUboToAdg,
convertAbpToAdg,
convertScriptletToAdg,
convertAdgToUbo
} from '@adguard/scriptlets/converters';
convertUboToAdg()
declare function convertUboToAdg(rule: string | ScriptletInjectionRule): string[];
Note that parameters in UBO rule should be separated by comma + space. Otherwise, the rule is not valid.
convertAbpToAdg()
declare function convertAbpToAdg(rule: string | ScriptletInjectionRule): string[];
convertScriptletToAdg()
declare function convertScriptletToAdg(rule: string | ScriptletInjectionRule): string[];
convertAdgToUbo()
declare function convertAdgToUbo(rule: string | ScriptletInjectionRule): string | undefined;
convertAdgRedirectToUbo()
declare function convertAdgRedirectToUbo(rule: string): string;
| Chrome | ✅ 55 |
| Firefox | ✅ 52 |
| Edge | ✅ 15 |
| Opera | ✅ 42 |
| Safari | ✅ 13 |
| Internet Explorer | ❌ |