![Create React App Officially Deprecated Amid React 19 Compatibility Issues](https://cdn.sanity.io/images/cgdhsj6q/production/04fa08cf844d798abc0e1a6391c129363cc7e2ab-1024x1024.webp?w=400&fit=max&auto=format)
Security News
Create React App Officially Deprecated Amid React 19 Compatibility Issues
Create React App is officially deprecated due to React 19 issues and lack of maintenance—developers should switch to Vite or other modern alternatives.
@adguard/ecss-tree
Advanced tools
Adblock Extended CSS supplement for CSSTree. Our primary goal is to change the internal behavior of the CSSTree parser to support Extended CSS (ECSS) language elements, but we don't change the API or the AST structure. Therefore ECSSTree fully backwards compatible with CSSTree, so you can pass our AST to CSSTree functions and vice versa without any problems.
:warning: Note: If you are looking for a library that can parse CSS, but you don't know what is Adblock or Extended CSS, you should probably use CSSTree instead of this library :)
You can install the library using one of the following methods:
npm install @adguard/ecss-tree
yarn add @adguard/ecss-tree
Links:
Currently, the following Extended CSS pseudo classes are supported:
:-abp-contains(text / regexp)
: [ABP reference]:-abp-has(selector list)
: [ABP reference]:contains(text / regexp)
: [ADG reference]:has-text(text / regexp)
: [uBO reference]:if-not(selector)
: [ADG reference]:matches-media(media query list)
: [uBO reference]:min-text-length(number)
: [uBO reference]:nth-ancestor(number)
: [ADG reference]:style(style declaration list)
: [uBO reference]:upward(selector / number)
: [ADG reference], [uBO reference]:xpath(xpath expression)
: [ADG reference], [uBO reference]In addition, CSSTree supports the following pseudo classes by default:
:has(selector list)
: [W3C reference], [ADG reference], [uBO reference]:not(selector list)
: [W3C reference], [ADG reference], [uBO reference]:is(selector list)
: [W3C reference], [ADG reference]Also, CSSTree supports legacy Extended CSS elements by default (attribute selectors): [-ext-name="value"]
, where name
is the name of the Extended CSS element and value
is its value. For example, the following selector can be parsed by CSSTree:
[-ext-has="selector list"]
If a pseudo class is unknown to CSSTree, it tries to parse it as a Raw
element (if possible - see problematic cases).
The CSSTree library itself is quite flexible and error-tolerant, so it basically manages well the Extended CSS elements that are not (yet) included here.
For example, the following selector
div:-abp-has(> section)
will be parsed by the default CSSTree as follows
{
"type": "Selector",
"loc": null,
"children": [
{
"type": "PseudoClassSelector",
"loc": null,
"name": "-abp-has",
"children": [
{
"type": "Raw",
"loc": null,
"value": "> section"
}
]
}
]
}
The problem with this is that the -abp-has
parameter is parsed as Raw
, not as a Selector
, since -abp-has
is an unknown pseudo class in CSS / CSSTree.
This is where the ECSSTree library comes into play. It detects that -abp-has
expects a selector as a parameter, i.e. it parses the passed parameter as a Selector
. This means that the selector above will be parsed as follows:
{
"type": "Selector",
"loc": null,
"children": [
{
"type": "PseudoClassSelector",
"loc": null,
"name": "-abp-has",
"children": [
{
"type": "Selector",
"loc": null,
"children": [
{
"type": "Combinator",
"loc": null,
"name": ">"
},
{
"type": "TypeSelector",
"loc": null,
"name": "section"
}
]
}
]
}
]
}
Combinator
and similar Nodes are part of CSSTree, this fork simply specifies that the -abp-has
parameter should be parsed as a selector. The nodes themselves are part of the CSSTree.
In addition, this approach enables a more advanced validation. For example, the default CSSTree does not throw an error when parsing the following selector:
div:-abp-has(42)
since it doesn't know what -abp-has
is, it simply parses 42 as Raw
. ECSSTree parses the parameter as a selector, which will throw an error, since 42 is simply an invalid selector.
The library also handles problematic selectors, such as the following:
div:contains(aaa'bbb)
This selector doesn't fully meet with CSS standards, so even if CSSTree is flexible, it will not be able to parse it properly, because it will tokenize it as follows:
Token type | Start index | End index | Source part |
---|---|---|---|
ident-token | 0 | 3 | div |
colon-token | 3 | 4 | : |
function-token | 4 | 13 | contains( |
ident-token | 13 | 16 | aaa |
string-token | 16 | 21 | 'bbb) |
At quote mark ('
) tokenizer will think that a string is starting, and it tokenizes the rest of the input as a string. This is the normal behavior for the tokenizer, but it is wrong for us, since the parser will fail with an ")" is expected
error, as it doesn't found the closing parenthesis, since it thinks that the string is still open.
ECSSTree will handle this case by a special re-tokenization algorithm during the parsing process, when parser reaches this problematic point. This way, ECSSTree's parser will be able to parse this selector properly. It is also true for xpath
.
Note: ECSSTree parses :contains
and :xpath
parameters as Raw
. The main goal of this library is changing the internal behavior of the CSSTree's parser to make it able to parse the Extended CSS selectors properly, not to change the AST itself. The AST should be the same as in CSSTree, so that the library can be used as a drop-in replacement for CSSTree. Parsing :xpath
expressions or regular expressions in detail would be a huge task, and requires new AST nodes, which would be a breaking change. But it always parses the correct raw expression for you, so you can parse/validate these expressions yourself if you want. There are many libraries for this, such as xpath or regexpp. See example codes for more details.
Here are a very simple example to show how to use ECSSTree:
const { parse, generate, toPlainObject, fromPlainObject } = require("@adguard/ecss-tree");
const { inspect } = require("util");
// Some inputs to test
const inputs = [
// Valid selectors
`div:-abp-has(> .some-class > a[href^="https://example.com"])`,
`body:style(padding-top: 0 !important;):matches-media((min-width: 500px) and (max-width: 1000px))`,
`section:upward(2):contains(aaa'bbb):xpath(//*[contains(text(),"()(cc")])`,
// Missing closing bracket at the end
`div:-abp-has(> .some-class > a[href^="https://example.com"]`,
];
// Iterate over inputs
for (const input of inputs) {
try {
// Parse raw input to AST. This will throw an error if the input is not valid.
// Don't forget to set context to 'selector', because CSSTree will try to parse
// 'stylesheet' by default.
const ast = parse(input, { context: "selector" });
// By default, AST uses a doubly linked list. To convert it to plain object, you can
// use toPlainObject() function.
// If you want to convert AST back to doubly linked list version, you can use
// fromPlainObject() function.
const astPlain = toPlainObject(ast);
const astAgain = fromPlainObject(astPlain);
// Print AST to console
console.log(inspect(astPlain, { colors: true, depth: null }));
// You can also generate string from AST (don't use plain object here)
console.log(generate(astAgain));
} catch (e) {
// Mark invalid selector
console.log(`Invalid selector: ${input}`);
// Show CSSTree's formatted error message
console.log(e.formattedMessage);
}
}
The API is the same as in CSSTree, so you can use the CSSTree documentation as a reference.
You can find more examples in the examples folder.
Our build process generates a browser-friendly version of the library, which can be used in the browser. You can insert it into your HTML page like this:
<script src="https://cdn.jsdelivr.net/npm/@adguard/ecss-tree/dist/ecsstree.iife.min.js"></script>
or
<script src="https://unpkg.com/@adguard/ecss-tree@latest/dist/ecsstree.iife.min.js"></script>
Example usage:
<script>
// Selector to parse
const selector = `div[title="Hello world!"]`;
// Double linked list version of AST
const ast = ECSSTree.parse(selector, { context: "selector" });
// Plain object version of AST
const plain = ECSSTree.toPlainObject(ast);
// Print AST object to console
console.log(plain);
</script>
If you find a bug or want to request a new feature, please open an issue or a discussion on GitHub. Please provide a detailed description of the problem or the feature you want to request, and if possible, a code example that demonstrates the problem or the feature.
You can contribute to the project by opening a pull request. People who contribute to AdGuard projects can receive various rewards, see this page for details.
Here is a short guide on how to set up the development environment and how to submit your changes:
git clone
yarn
(this will also initialize the Git hooks via Husky)git checkout -b <branch-name>
(e.g. git checkout -b feature/add-some-feature
, please add /feature
or /fix
prefix to your branch name)src
folder and make suitable tests for them in the test
folderyarn test
(or run only a specific test with yarn test <test-name>
)We would be happy to review your pull request and merge it if it is suitable for the project.
Note: you can find CSSTree API map here: https://github.com/csstree/csstree#top-level-api
During development, you can use the following commands (listed in package.json
):
yarn lint
- lint the code with ESLintyarn test
- run tests with Jest (you can also run a specific test with yarn test <test-name>
)yarn build
- build the library to the dist
folder by using RollupThis library is licensed under the MIT license. See the LICENSE file for more info.
In this section, we would like to thank the following people for their work:
Here are some useful links to learn more about Extended CSS selectors:
[1.0.6] - 2022-02-21
@types/css-tree
.AdguardTeam
organization.FAQs
Adblock Extended CSS fork for CSSTree
The npm package @adguard/ecss-tree receives a total of 767 weekly downloads. As such, @adguard/ecss-tree popularity was classified as not popular.
We found that @adguard/ecss-tree demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 0 open source maintainers collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
Create React App is officially deprecated due to React 19 issues and lack of maintenance—developers should switch to Vite or other modern alternatives.
Security News
Oracle seeks to dismiss fraud claims in the JavaScript trademark dispute, delaying the case and avoiding questions about its right to the name.
Security News
The Linux Foundation is warning open source developers that compliance with global sanctions is mandatory, highlighting legal risks and restrictions on contributions.