Skip to content

Commit 8126a30

Browse files
nwronskiQard
authored andcommitted
Added :has() pseudo-selector to grammar.
1 parent c029e89 commit 8126a30

File tree

4 files changed

+119
-6
lines changed

4 files changed

+119
-6
lines changed

esquery.js

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,22 @@
8383
}
8484
return true;
8585

86+
case 'has':
87+
var a, collector = [];
88+
for (i = 0, l = selector.selectors.length; i < l; ++i) {
89+
a = [];
90+
estraverse.traverse(node, {
91+
enter: function (node, parent) {
92+
if (parent != null) { a.unshift(parent); }
93+
if (matches(node, selector.selectors[i], a)) {
94+
collector.push(node);
95+
}
96+
},
97+
leave: function () { a.shift(); }
98+
});
99+
}
100+
return collector.length !== 0;
101+
86102
case 'child':
87103
if (matches(node, selector.right, ancestry)) {
88104
return matches(ancestry[0], selector.left, ancestry.slice(1));

grammar.pegjs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ sequence
4949

5050
atom
5151
= wildcard / identifier / attr / field / negation / matches
52-
/ firstChild / lastChild / nthChild / nthLastChild / class
52+
/ has / firstChild / lastChild / nthChild / nthLastChild / class
5353

5454
wildcard = a:"*" { return { type: 'wildcard', value: a }; }
5555
identifier = "#"? i:identifierName { return { type: 'identifier', value: i }; }
@@ -88,12 +88,14 @@ field = "." i:identifierName is:("." identifierName)* {
8888

8989
negation = ":not(" _ ss:selectors _ ")" { return { type: 'not', selectors: ss }; }
9090
matches = ":matches(" _ ss:selectors _ ")" { return { type: 'matches', selectors: ss }; }
91+
has = ":has(" _ ss:selectors _ ")" { return { type: 'has', selectors: ss }; }
9192

9293
firstChild = ":first-child" { return nth(1); }
9394
lastChild = ":last-child" { return nthLast(1); }
9495
nthChild = ":nth-child(" _ n:[0-9]+ _ ")" { return nth(parseInt(n.join(''), 10)); }
9596
nthLastChild = ":nth-last-child(" _ n:[0-9]+ _ ")" { return nthLast(parseInt(n.join(''), 10)); }
9697

98+
9799
class = ":" c:("statement"i / "expression"i / "declaration"i / "function"i / "pattern"i) {
98100
return { type: 'class', name: c };
99101
}

parser.js

Lines changed: 83 additions & 5 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

tests/queryHas.js

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
2+
define([
3+
"esquery",
4+
"jstestr/assert",
5+
"jstestr/test",
6+
"./fixtures/conditional"
7+
], function (esquery, assert, test, conditional) {
8+
9+
test.defineSuite("Parent selector query", {
10+
11+
"conditional": function () {
12+
var matches = esquery(conditional, 'ExpressionStatement:has([name="foo"][type="Identifier"])');
13+
assert.isEqual(1, matches.length);
14+
}
15+
16+
});
17+
});

0 commit comments

Comments
 (0)