Research
Security News
Quasar RAT Disguised as an npm Package for Detecting Vulnerabilities in Ethereum Smart Contracts
Socket researchers uncover a malicious npm package posing as a tool for detecting vulnerabilities in Etherium smart contracts.
@tokey/css-selector-parser
Advanced tools
A flexible CSS selector parser with support for the latest syntax and features.
Features
start/end
on every AST nodebefore/after
and never affects selector meaningcomments
- comments parsed wherever they are placed 🤪escaping
- support escaped dots, slashes, quotation marks, etc.An+B of
- Nth selector AST with inner parts and validation flags for each partcombinators
- correctly identify and mark spaces/combinators with validation flagsnesting
- support future &
selectornamespace
- universal
and type
selectors namespace with validation flags on the ASTUsing NPM:
npm install @tokey/css-selector-parser
Using Yarn:
yarn add @tokey/css-selector-parser
parseCssSelector
- accepts a selector list string and returns an AST representation of that.
import { parseCssSelector } from '@tokey/css-selector-parser';
const selectorList = parseCssSelector(`.card, .box`);
/*
[
{
type: "selector",
start: 0,
end: 5,
before: "",
after: "",
nodes: [
{
type: "class",
value: "card",
start: 0,
end: 5,
dotComments: [],
},
],
},
{
type: "selector",
start: 6,
end: 11,
before: " ",
after: "",
nodes: [
{
type: "class",
value: "box",
start: 7,
end: 11,
dotComments: [],
},
],
}
]
*/
offset
- start AST offset from a given point, defaults to 0:
parseCssSelector(`ul`, { offset: 105 });
stringifySelectorAst
- converts an AST node back into its string representation.
import { stringifySelectorAst } from '@tokey/css-selector-parser';
stringifySelectorAst(
parseCssSelector(`.class`);
); // ".class"
walk
- traverse each node of the selector AST from start to end.
The visit call is given:
import { walk } from '@tokey/css-selector-parser';
walk(
parseCssSelector(`.one + three(#four, [five]), /*six*/ ::seven:eight`),
(node: SelectorNode, index: number, nodes: SelectorNode[], parents: SelectorNode[]) => {
// calling order:
// selector: .one + three(#four, [five])
// .one
// +
// three
// selector: #four
// #four
// selector: [five]
// [five]
// selector: /*six*/ ::seven:eight
// /*six*/
// ::seven
// :eight
}
);
Note: comments within class, pseudo-class and pseudo-element are not traversed at the moment
For example:
./*what?!*/a
.
The transversal can be controlled with the return value of each visit:
import { walk } from '@tokey/css-selector-parser';
walk(
parseCssSelector(`selector`),
(node) => {
// return walk.skipNested;
// return walk.skipCurrentSelector;
// return walk.stopAll;
}
);
visitList/ignoreList
- limits the types of AST calls to the visit function, but does not prevent traversal of nested nodes.
walk(
parseCssSelector(`.one:is(:not(/*comment*/.two))`),
(node) => {
// .one
// :is()
// :not()
// .two
},
{
// visit will not be called on selector or comment nodes
ignoreList: [`selector`, `comment`]
}
);
groupCompoundSelectors
and splitCompoundSelectors
- take a Selector | SelectorList
and shallow group or split compound selectors accordingly.
import {
parseCssSelector,
groupCompoundSelectors,
splitCompoundSelectors
} from '@tokey/css-selector-parser';
const selectorList = parseCssSelector(`.a.b .c.d`);
const compoundSelectorList = groupCompoundSelectors(selectorList);
/*
[
{
type: `selector,
nodes: [
{
type: `compound_selector`,
nodes: [
{ type: `class`, value: `a` },
{ type: `class`, value: `b` },
]
}
{ type: `combinator`, value: ` ` },
{
type: `compound_selector`,
nodes: [
{ type: `class`, value: `c` },
{ type: `class`, value: `d` },
]
}
]
}
]
*/
const flatSelectorList = splitCompoundSelectors(compoundSelectorList);
/*
[
{
type: `selector,
nodes: [
{ type: `class`, value: `a` },
{ type: `class`, value: `b` },
{ type: `combinator`, value: ` ` },
{ type: `class`, value: `c` },
{ type: `class`, value: `d` },
]
}
]
*/
Note: compound selector contain
invalid
flag to indicate selector has auniversal
ortype
selector that is not located in the first part of the selector.
Note: comments with no spacing are included within the compound selector
splitPseudoElements
- by default pseudo-elements are split into separated compound selectors, use splitPseudoElements: false
to combine them into the previous compound selector:
const selectorList = parseCssSelector(`.a::before`);
const compoundSelectorList = groupCompoundSelectors(selectorList);
/*
[
{
type: `selector,
nodes: [
{
type: `compound_selector`,
nodes: [
{ type: `class`, value: `a` },
]
}
{
type: `compound_selector`,
nodes: [
{ type: `pseudo_element`, value: `before` },
]
}
]
}
]
*/
const compoundSelectorList = groupCompoundSelectors(selectorList, {splitPseudoElements: false});
/*
[
{
type: `selector,
nodes: [
{
type: `compound_selector`,
nodes: [
{ type: `class`, value: `a` },
{ type: `pseudo_element`, value: `before` },
]
}
]
}
]
calcSpecificity
take a Selector
and returns it's specificity value
import {
parseCssSelector,
calcSpecificity,
} from '@tokey/css-selector-parser';
const specificity = calcSpecificity(parseCssSelector(`span.x.y#z`));
// [0, 1, 2, 1]
compareSpecificity
takes 2 specificity values and return 0 if they are equal, 1 if the first is higher and -1 if the second is higher:
import {
compareSpecificity,
} from '@tokey/css-selector-parser';
compareSpecificity(
[0, 2, 0, 0],
[0, 1, 0, 0]
) // 1
compareSpecificity(
[0, 0, 2, 0],
[0, 1, 0, 0]
) // -1
The parser supports character escaping, but will not escape anything by itself. Make sure to escape any value before setting it manually into an AST node.
The parser supports native pseudo-classes/pseudo-elements
functional selectors, but also parses other selectors in the same way. So type
/id
/class
/attribute
/nesting
selectors are all parsed with nodes
in case they are followed by a pair of parentheses (e.g. element(nodeA, nodeB)
). This syntax is not valid CSS and should be handled before served to a CSS consumer.
:nth-child
, :nth-last-child
, :nth-of-type
and :nth-last-of-type
are a set of special cases where An+B of
syntax is expected.
FAQs
selector parser for css
We found that @tokey/css-selector-parser demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 3 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.
Research
Security News
Socket researchers uncover a malicious npm package posing as a tool for detecting vulnerabilities in Etherium smart contracts.
Security News
Research
A supply chain attack on Rspack's npm packages injected cryptomining malware, potentially impacting thousands of developers.
Research
Security News
Socket researchers discovered a malware campaign on npm delivering the Skuld infostealer via typosquatted packages, exposing sensitive data.