Adblocker
A fast and memory efficient, pure-JavaScript content-blocking library made by Cliqz.
This library is the building block technology used to power Ghostery and
Cliqz' Adblocking. Being a pure JavaScript library it is trivial to include in
any new project and can also be used as a building block for tooling. For
example this library can be used for:
- Building a content-blocking extension (see this example for a minimal content-blocking webextension)
- Building tooling around popular block-lists such as EasyList
- validating filters
- normalizing filters
- detecting redundant filters
- Detecting dead domains
- etc.
The library provides abstractions to manipulate filters at a low-level.
Getting Started
This package can be installed directly from npm
:
$ npm install @cliqz/adblocker
Or you can install it from sources directly:
$ npm ci
$ npm pack
$ npm run test
Multiple bundles are provided in the dist
folder.
Usage
Network Filters
Here is how one can parse and match individual network filters:
const { NetworkFilter, Request } = require('@cliqz/adblocker');
const filter = NetworkFilter.parse('||domain.com/ads.js$script');
filter.match(new Request({
type: 'script',
domain: 'domain.com',
hostname: 'domain.com',
url: 'https://domain.com/ads.js?param=42',
sourceUrl: 'https://domain.com/',
sourceHostname: 'domain.com',
sourceDomain: 'domain.com',
}));
Matching requires you to provide an instance of Request
which knows
about the type of the request (e.g.: main_frame
, script,
etc.) as
well as the URL, hostname and domain of the request and source URL.
To make things a bit easier, the library exposes a makeRequest
helper
which can be used alongside a library like tldts
(or another library
providing parsing of hostnames and domains) to provide the parsing:
const tldts = require('tldts');
const { NetworkFilter, makeRequest } = require('@cliqz/adblocker');
const filter = NetworkFilter.parse('||domain.com/ads.js$script');
filter.match(makeRequest({
type: 'script',
url: 'https://domain.com/ads.js',
}, tldts));
Cosmetic Filters
Here is how one can parse and match individual cosmetic filters:
const { CosmeticFilter } = require('@cliqz/adblocker');
const filter = CosmeticFilter.parse('domain.*,domain2.com###selector');
filter.match('sub.domain.com', 'domain.com');
Filters Engine
Manipulating filters at a low level is useful to build tooling or debugging, but
to perform efficient matching we need to use FiltersEngine
which can be seen
as a "container" for both network and cosmetic filters. The filters are
organized in a very compact way and allow fast matching against requests.
const { FiltersEngine } = require('@cliqz/adblocker');
const engine = FiltersEngine.parse(`
! This is a custom list
||domain.com/ads.js$script
###selector
domain.com,entity.*##+js(script,args1)
`);
const serialized = engine.serialize();
const deserialized = FiltersEngine.deserialize(serialized);
const {
match,
redirect,
exception,
filter,
} = engine.match(new Request(...));
const directives = engine.getCSPDirectives(new Request(...));
const {
styles,
scripts,
} = engine.getCosmeticFilters('sub.domain.com', 'domain.com');
Release Checklist
To publish a new version:
- Bump
ENGINE_VERSION
in engine.ts
(to invalidate serialized versions) - Create a new branch (e.g.:
release-x.y.z
) - Update
version
in package.json - Update CHANGELOG.md
- Create a release commit (e.g.: "Release vx.y.z")
- Create a PR for the release
- Merge and create a new Release on GitHub
- Travis takes care of the rest!
License
Mozilla Public License 2.0