@adguard/scriptlets

AdGuard's JavaScript library of Scriptlets and Redirect resources

Usage no npm install needed!

<script type="module">
  import adguardScriptlets from 'https://cdn.skypack.dev/@adguard/scriptlets';
</script>

README

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

rule = [domains]  "#%#//scriptlet(" scriptletName arguments ")"
  • scriptletName (mandatory) is 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 meanining of the arguments depends on the scriptlet.
  • You can use either single or double quotes for the scriptlet name and arguments.
  • Special characters must be escaped properly:
    • 'prop["nested"]' - valid
    • "prop['nested']" - valid
    • "prop[\"nested\"]" - also valid
    • "prop["nested"]" - not valid
    • 'prop['nested']' - not valid

Example

example.org#%#//scriptlet('abort-on-property-read', 'alert')
example.org#%#//scriptlet('remove-class', 'branding', 'div[class^="inner"]')

This rule applies the abort-on-property-read scriptlet on all pages of example.org and its subdomains, and passes one orgument to it (alert).

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 resources below.

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.

$redirect rules priority is higher than the regular basic blocking rules' priority. This means that if there's a basic blocking rule (even with $important modifier), $redirect rule will prevail over it. If there's a whitelist (@@) rule matching the same URL, it will disable redirecting as well (unless the $redirect rule is also marked as $important).

uBlock Origin specifies additional resource name none that can disable other redirect rules. AdGuard does not support it, use $badfilter to disable specific rules.


How to build

Install dependencies

yarn install

Build for CoreLibs

yarn corelibs

Build for Extension

yarn build

Build dev (rebuild js files on every change)

yarn watch

Run node testing

yarn test

Run tests gui

yarn gui-test

To run browserstack tests create .env file or rename .env-example.

Fill in and with data from your Browserstack profile. Run next command

yarn browserstack

Build output

Scriptlets library

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:

/**
* Returns scriptlet code
* @param {Source} source
* @returns {string}
*/
scriptlets.invoke(source);
/**
* Checks if the scriptlet name is valid
* @param {string} name - scriptlet name
* @returns {boolean}
*/
scriptlets.isValidScriptletName(name);
/**
* Checks whether the ADG scriptlet exists or UBO/ABP scriptlet is compatible to ADG
*
* ADG or UBO rule is single-scriptlet, but ABP rule may contain more than one snippet
* so if at least one of them is not valid - whole 'input' rule is not valid too.
* @param {string} input - can be Adguard or Ubo or Abp scriptlet rule
* @returns {boolean}
*/
scriptlets.isValidScriptletRule(input);
/**
* Checks if the `rule` is AdGuard / Ubo / Abp scriptlet rule
* @param {string} rule - rule text
* @returns {boolean}
*/
scriptlets.isAdgScriptletRule(rule);
scriptlets.isUboScriptletRule(rule);
scriptlets.isAbpSnippetRule(rule);
/**
* Converts Ubo scriptlet rule to AdGuard
* @param {string} rule - rule text
* @returns {Array} - array with one item - AdGuard scriptlet rule
*/
scriptlets.convertUboToAdg(rule);

Note that parameters in UBO rule should be separated by comma + space. Otherwise, the rule is not valid.

/**
* Converts Abp snippet rule to AdGuard
* @param {string} rule - rule text
* @returns {Array} - array with AdGuard scriptlet rule or rules if Abp-rule has few snippets in one line
*/
scriptlets.convertAbpToAdg(rule);
/**
* Checks if the `rule` is any scriptlet rule and converts it to AdGuard
* @param {string} rule - rule text
* @returns {Array} - array of AdGuard scriptlet rules - one item for Adg and Ubo or few items for Abp
*/
scriptlets.convertScriptletToAdg(rule);
/**
 * Converts AdGuard scriptlet rule to UBO one
 * @param {string} rule - AdGuard scriptlet rule
 * @returns {string} - UBO scriptlet rule
 */
scriptlets.convertAdgToUbo(rule);
Imported redirects has such methods:
/**
* Returns redirects code
* @param {Source} source
* @returns {string}
*/
redirects.getCode(source);
/**
 * Checks if the `rule` is AdGuard redirect rule.
 * Discards comments and JS rules and checks if the `rule` has 'redirect' modifier.
 * @param {string} rule - rule text
 */
redirects.isAdgRedirectRule(rule)
/**
* Checks if the `rule` is **valid** AdGuard redirect rule
* @param {string} rule - redirect rule text
* @returns {boolean}
*/
redirects.isValidAdgRedirectRule(rule);
/**
* Checks if the AdGuard redirect `rule` has Ubo analog. Needed for Adg->Ubo conversion
* @param {string} rule - AdGuard rule text
* @returns {boolean} - true if the rule can be converted to Ubo
*/
redirects.isAdgRedirectCompatibleWithUbo(rule);
/**
* Checks if the Ubo redirect `rule` has AdGuard analog. Needed for Ubo->Adg conversion
* @param {string} rule - Ubo rule text
* @returns {boolean} - true if the rule can be converted to AdGuard
*/
redirects.isUboRedirectCompatibleWithAdg(rule);
/**
* Checks if the Abp redirect `rule` has AdGuard analog. Needed for Abp->Adg conversion
* @param {string} rule - Abp rule text
* @returns {boolean} - true if the rule can be converted to AdGuard
*/
redirects.isAbpRedirectCompatibleWithAdg(rule);
/**
* Converts Ubo redirect rule to AdGuard
* @param {string} rule - rule text
* @returns {string}
*/
redirects.convertUboRedirectToAdg(rule);
/**
* Converts Abp redirect rule to AdGuard
* @param {string} rule - rule text
* @returns {string}
*/
redirects.convertAbpRedirectToAdg(rule);
/**
* Checks if the `rule` is any redirect rule and converts it to AdGuard
* @param {string} rule - rule text
* @returns {string} - converted to Adguard redirect rule OR `rule` if it is valid Adguard rule
*/
redirects.convertRedirectToAdg(rule);
/**
 * Converts Adg redirect rule to Ubo one
 * @param {string} rule
 * @returns {string}
 */
redirects.convertAdgRedirectToUbo(rule);

Corelibs library

dist/scriptlets.corelibs.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"
                    }
                },
            }
        }
    }
}

Redirects library

dist/redirects.js
dist/redirects.yml

Creates a global variable Redirects.

// Usage

/**
 * Converts rawYaml into JS object with sources titles used as keys
 */
const redirects = new Redirects(rawYaml)

/**
 * Returns redirect source object by title
 */
const redirect = redirect.getRedirect('noopjs');

/**
 * Redirect - object with following props
 * {
 *      title: 1x1-transparent.gif
 *      comment: http://probablyprogramming.com/2009/03/15/the-tiniest-gif-ever
 *      contentType: image/gif;base64
 *      content: R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==
 * }
 */

Browser Compatibility

| Chrome | Edge | Firefox | IE | Opera | Safari | |--|--|--|--|--|--| | 55 | 15 | 52 | 11 | 42 | 10 |