Skip to content

Commit

Permalink
allow naked binaryOp at the start of a selector within :has() (#145)
Browse files Browse the repository at this point in the history
Co-authored-by: Richard Silverton <[email protected]>
Co-authored-by: Michael Ficarra <[email protected]>
  • Loading branch information
3 people authored Jul 8, 2024
1 parent 909bea6 commit 00448e0
Show file tree
Hide file tree
Showing 5 changed files with 448 additions and 277 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ The following selectors are supported:
* [following sibling](http://dev.w3.org/csswg/selectors4/#general-sibling-combinators): `node ~ sibling`
* [adjacent sibling](http://dev.w3.org/csswg/selectors4/#adjacent-sibling-combinators): `node + adjacent`
* [negation](http://dev.w3.org/csswg/selectors4/#negation-pseudo): `:not(ForStatement)`
* [has](https://drafts.csswg.org/selectors-4/#has-pseudo): `:has(ForStatement)`
* [has](https://drafts.csswg.org/selectors-4/#has-pseudo): `:has(ForStatement)`, `:has(> ForStatement)`
* [matches-any](http://dev.w3.org/csswg/selectors4/#matches): `:matches([attr] > :first-child, :last-child)`
* [subject indicator](http://dev.w3.org/csswg/selectors4/#subject): `!IfStatement > [name="foo"]`
* class of AST node: `:statement`, `:expression`, `:declaration`, `:function`, or `:pattern`
Expand Down
11 changes: 10 additions & 1 deletion esquery.js
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,11 @@ function inPath(node, ancestor, path, fromPathIndex) {

/**
* A generated matcher function for a selector.
* @typedef {function} SelectorMatcher
* @callback SelectorMatcher
* @param {?SelectorAST} selector
* @param {external:AST[]} [ancestry=[]]
* @param {ESQueryOptions} [options]
* @returns {void}
*/

/**
Expand Down Expand Up @@ -123,6 +127,11 @@ function generateMatcher(selector) {
};
}

case 'exactNode':
return (node, ancestry) => {
return ancestry.length === 0;
};

case 'field': {
const path = selector.name.split('.');
return (node, ancestry) => {
Expand Down
13 changes: 12 additions & 1 deletion grammar.pegjs
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,21 @@ binaryOp
/ _ "+" _ { return 'adjacent'; }
/ " " _ { return 'descendant'; }

hasSelectors = s:hasSelector ss:(_ "," _ hasSelector)* {
return [s].concat(ss.map(function (s) { return s[3]; }));
}

selectors = s:selector ss:(_ "," _ selector)* {
return [s].concat(ss.map(function (s) { return s[3]; }));
}


hasSelector
= op:binaryOp? s:selector {
if (!op) return s;
return { type: op, left: { type: 'exactNode' }, right: s };
}

selector
= a:sequence ops:(binaryOp sequence)* {
return ops.reduce(function (memo, rhs) {
Expand Down Expand Up @@ -96,7 +107,7 @@ field = "." i:identifierName is:("." identifierName)* {

negation = ":not(" _ ss:selectors _ ")" { return { type: 'not', selectors: ss }; }
matches = ":matches(" _ ss:selectors _ ")" { return { type: 'matches', selectors: ss }; }
has = ":has(" _ ss:selectors _ ")" { return { type: 'has', selectors: ss }; }
has = ":has(" _ ss:hasSelectors _ ")" { return { type: 'has', selectors: ss }; }

firstChild = ":first-child" { return nth(1); }
lastChild = ":last-child" { return nthLast(1); }
Expand Down
Loading

0 comments on commit 00448e0

Please sign in to comment.