@adguard/tsurlfilter
TypeScript icon, indicating that this package has built-in type declarations

2.2.19 • Public • Published

TSUrlFilter

NPM

This is a TypeScript library that implements AdGuard's content blocking rules.

Idea

The idea is to have a single library that we can reuse for the following tasks:

Usage

Install the tsurlfilter:

npm install @adguard/tsurlfilter

API description

Public properties

TSURLFILTER_VERSION

type: string

Version of the library.

Public classes

Engine

Engine is a main class of this library. It represents the filtering functionality for loaded rules

Constructor
    /**
     * Creates an instance of Engine
     * Parses filtering rules and creates a filtering engine of them
     *
     * @param ruleStorage storage
     * @param configuration optional configuration
     *
     * @throws
     */
    constructor(ruleStorage: RuleStorage, configuration?: IConfiguration | undefined)
matchRequest


    /**
     * Matches the specified request against the filtering engine and returns the matching result.
     * In case frameRules parameter is not specified, frame rules will be selected matching request.sourceUrl.
     *
     * @param request - request to check
     * @param frameRules - source rules or undefined
     * @return matching result
     */
    matchRequest(request: Request, frameRule: NetworkRule | null = null): MatchingResult
matchFrame
    /**
     * Matches current frame and returns document-level allowlist rule if found.
     *
     * @param frameUrl
     */
    matchFrame(frameUrl: string): NetworkRule | null
Starting engine
    const list = new StringRuleList(listId, rulesText, false, false);
    const ruleStorage = new RuleStorage([list]);

    const config = {
        engine: 'extension',
        version: '1.0.0',
        verbose: true,
    };

    setConfiguration(config)

    const engine = new Engine(ruleStorage);
Matching requests
    const request = new Request(url, sourceUrl, RequestType.Document);
    const result = engine.matchRequest(request);
Retrieving cosmetic data
    const cosmeticResult = engine.getCosmeticResult(request, CosmeticOption.CosmeticOptionAll);

MatchingResult

MatchingResult contains all the rules matching a web request, and provides methods that define how a web request should be processed

getBasicResult
    /**
     * GetBasicResult returns a rule that should be applied to the web request.
     * Possible outcomes are:
     * returns null -- bypass the request.
     * returns a allowlist rule -- bypass the request.
     * returns a blocking rule -- block the request.
     *
     * @return basic result rule
     */
    getBasicResult(): NetworkRule | null
getCosmeticOption

This flag should be used for getCosmeticResult(request: Request, option: CosmeticOption)

    /**
     * Returns a bit-flag with the list of cosmetic options
     *
     * @return {CosmeticOption} mask
     */
    getCosmeticOption(): CosmeticOption
Other rules
    /**
     * Return an array of replace rules
     */
    getReplaceRules(): NetworkRule[]

    /**
     * Returns an array of csp rules
     */
    getCspRules(): NetworkRule[]

    /**
     * Returns an array of cookie rules
     */
    getCookieRules(): NetworkRule[]

CosmeticResult

Cosmetic result is the representation of matching cosmetic rules. It contains the following properties:

    /**
     * Storage of element hiding rules
     */
    public elementHiding: CosmeticStylesResult;

    /**
     * Storage of CSS rules
     */
    public CSS: CosmeticStylesResult;

    /**
     * Storage of JS rules
     */
    public JS: CosmeticScriptsResult;

    /**
     * Storage of Html filtering rules
     */
    public Html: CosmeticHtmlResult;

    /**
     * Script rules
     */
    public getScriptRules(): CosmeticRule[];
Applying cosmetic result - css
   const css = [...cosmeticResult.elementHiding.generic, ...cosmeticResult.elementHiding.specific]
           .map((rule) => `${rule.getContent()} { display: none!important; }`);

    const styleText = css.join('\n');
    const injectDetails = {
        code: styleText,
        runAt: 'document_start',
    };

    chrome.tabs.insertCSS(tabId, injectDetails);
Applying cosmetic result - scripts
    const cosmeticRules = cosmeticResult.getScriptRules();
    const scriptsCode = cosmeticRules.map((x) => x.getScript()).join('\r\n');
    const toExecute = buildScriptText(scriptsCode);

    chrome.tabs.executeScript(tabId, {
        code: toExecute,
    });

DnsEngine

DNSEngine combines host rules and network rules and is supposed to quickly find matching rules for hostnames.

Constructor
    /**
     * Builds an instance of dns engine
     *
     * @param storage
     */
    constructor(storage: RuleStorage)
match
    /**
     * Match searches over all filtering and host rules loaded to the engine
     *
     * @param hostname to check
     * @return dns result object
     */
    public match(hostname: string): DnsResult
Matching hostname
    const dnsResult = dnsEngine.match(hostname);
    if (dnsResult.basicRule && !dnsResult.basicRule.isAllowlist()) {
        // blocking rule found
        ..
    }

    if (dnsResult.hostRules.length > 0) {
        // hosts rules found
        ..
    }

RuleConverter

Before saving downloaded text with rules it could be useful to run converter on it. The text will be processed line by line, converting each line from known external format to Adguard syntax.

convertRules
    /**
     * Converts rules text
     *
     * @param rulesText
     */
    public static convertRules(rulesText: string): string {

RuleValidator

This module is not used in the engine directly, but it can be used to validate filter rules in other libraries or tools

Public methods
    /**
     * Validates raw rule string
     * @param rawRule
     */
    public static validate(rawRule: string): ValidationResult
    /**
    * Valid true - means that the rule is valid, otherwise rule is not valid
    * If rule is not valid, reason is returned in the error field
    */
    interface ValidationResult {
        valid: boolean;
        error: string | null;
    }

RuleSyntaxUtils

This module is not used in the engine directly, but it can be used in other libraries

Public methods
    /**
     * Checks if rule can be matched by domain
     * @param ruleText
     * @param domain
     */
    public static isRuleForDomain(ruleText: string, domain: string): boolean {
    /**
     * Checks if rule can be matched by url
     * @param ruleText
     * @param url
     */
    public static isRuleForUrl(ruleText: string, url: string): boolean {

DeclarativeConverter

Provides a functionality of conversion AG rules to manifest v3 declarative syntax. See examples/manifest-v3/ for an example usage.

Public methods
    /**
     * Converts a set of rules to declarative rules array
     *
     * @param ruleList
     */
    public convert(ruleList: IRuleList): DeclarativeRule[] {
Problems

QueryTransform

  • Regexp is not supported in remove params
  • We cannot implement inversion in remove params
  • We cannot filter by request methods
  • Only one rule applies for a redirect. For this reason, different rules with the same url may not work. Example below:
Works   ||testcases.adguard.com$removeparam=p1case6|p2case6

Failed  ||testcases.adguard.com$removeparam=p1case6
Works   ||testcases.adguard.com$removeparam=p2case6

Development

This project is part of the @adguard/extensions monorepo. It is highly recommended to use lerna for commands as it will execute scripts in the correct order and can cache dependencies.

npx lerna run --scope=@adguard/tsurlfilter:<script>

NPM scripts

  • start: Run build in watch mode
  • test:watch: Run test suite in interactive watch mode
  • test:prod: Run linting and generate coverage
  • build: Generate bundles and typings, create docs
  • lint: Lints code

Excluding peerDependencies

On library development, one might want to set some peer dependencies, and thus remove those from the final bundle. You can see in Rollup docs how to do that.

Good news: the setup is here for you, you must only include the dependency name in external property within rollup.config.js. For example, if you want to exclude lodash, just write there external: ['lodash'].

Git Hooks

There is already set a precommit hook for formatting your code with Eslint 💅

Readme

Keywords

none

Package Sidebar

Install

npm i @adguard/tsurlfilter

Weekly Downloads

182

Version

2.2.19

License

GPL-3.0-only

Unpacked Size

5.26 MB

Total Files

247

Last publish

Collaborators

  • ameshkov
  • maximtop
  • blakhard