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's 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])
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.
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:
yarn install
Build for CoreLibs:
yarn corelibs
Build dev (rebuild js files on every change):
yarn watch
Build for Extension
In scriptlets directory install dependencies, build scriptlets bundle, and create scriptlets link.
yarn
yarn build
yarn link
In tsurlfilter directory install and link dependencies, link scriptlets,
move into package and build, and create tsurlfilter link.
lerna bootstrap
yarn link "@adguard/scriptlets"
cd ./packages/tsurlfilter
yarn build
yarn link
In extension directory install dependencies, link packages and build
yarn
yarn link @adguard/scriptlets
yarn link @adguard/tsurlfilter
yarn dev
How to test
Some tests are run in QUnit, some in Jest.
Run all tests:
yarn test
-
QUnit is used for testing of scriptlets, redirects, and helpers:
yarn test:qunit [scriptlets | redirects | helpers]
For scriptlets and redirects test run can be more specific:
// node test run
yarn test:qunit scriptlets --name set-cookie
yarn test:qunit redirects --name ati-smarttag
// gui test run
yarn test:qunit scriptlets --name set-cookie --gui
yarn 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:
yarn test:qunit scriptlets --name set-cookie --build
-
Run all jest tests:
yarn test:jest
or limit the testing — testRegex
may be specified in jest.config.js
or specify test name in command line, e.g.:
yarn test:jest -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:
yarn 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
yarn test
and open needed HTML file from tests/dist
in your browser with devtools
How to update wiki
There are two scripts to update wiki:
yarn wiki:build-table
— checks compatibility data updates and updates the compatibility table.
Should be run manually while the release preparation.yarn 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
yarn add @adguard/scriptlets
npm install @adguard/scriptlets
API description
Scriptlets library
Scriptlets API
You are welcome to use scriptlets and redirect resources as a CJS module.
They can be imported from dist/cjs/scriptlets.cjs.js
:
const scriptlets = require('scriptlets');
const { redirects } = require('scriptlets');
And also there is a module at dist/scriptlets.js
which has been exported to a global variable scriptlets
with such methods:
Methods
invoke()
scriptlets.invoke(source);
where:
getScriptletFunction()
scriptlets.getScriptletFunction(name);
isValidScriptletName()
scriptlets.isValidScriptletName(name);
isValidScriptletRule()
scriptlets.isValidScriptletRule(ruleText);
isAdgScriptletRule()
, isUboScriptletRule()
, isAbpSnippetRule()
scriptlets.isAdgScriptletRule(rule);
scriptlets.isUboScriptletRule(rule);
scriptlets.isAbpSnippetRule(rule);
convertUboToAdg()
scriptlets.convertUboToAdg(rule);
Note that parameters in UBO rule should be separated by comma + space. Otherwise, the rule is not valid.
convertAbpToAdg()
scriptlets.convertAbpToAdg(rule);
convertScriptletToAdg()
scriptlets.convertScriptletToAdg(rule);
convertAdgToUbo()
scriptlets.convertAdgToUbo(rule);
Properties
SCRIPTLETS_VERSION
type: string
Current version of scriptlets library.
Redirects API methods
import { redirects } from '@adguard/scriptlets';
getCode()
redirects.getCode(source);
isAdgRedirectRule()
redirects.isAdgRedirectRule(rule)
isValidAdgRedirectRule()
redirects.isValidAdgRedirectRule(rule);
isRedirectResourceCompatibleWithAdg()
redirects.isRedirectResourceCompatibleWithAdg(redirectName);
isAdgRedirectCompatibleWithUbo()
redirects.isAdgRedirectCompatibleWithUbo(rule);
isUboRedirectCompatibleWithAdg()
redirects.isUboRedirectCompatibleWithAdg(rule);
isAbpRedirectCompatibleWithAdg()
redirects.isAbpRedirectCompatibleWithAdg(rule);
convertUboRedirectToAdg()
redirects.convertUboRedirectToAdg(rule);
convertAbpRedirectToAdg()
redirects.convertAbpRedirectToAdg(rule);
convertRedirectToAdg()
redirects.convertRedirectToAdg(rule);
convertRedirectNameToAdg()
redirects.convertRedirectNameToAdg(rule);
convertAdgRedirectToUbo()
redirects.convertAdgRedirectToUbo(rule);
getRedirectFilename()
redirects.getRedirectFilename(name);
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');
Browser | Version |
---|
Chrome | ✅ 55 |
Firefox | ✅ 52 |
Edge | ✅ 15 |
Opera | ✅ 42 |
Safari | ✅ 11 |
Internet Explorer | ❌ |