diff --git a/lib/any.js b/lib/any.js index 2ceb1ff..eb45886 100644 --- a/lib/any.js +++ b/lib/any.js @@ -1,12 +1,8 @@ /** - * @typedef {import('./types.js').Selector} Selector * @typedef {import('./types.js').Selectors} Selectors * @typedef {import('./types.js').Rule} Rule * @typedef {import('./types.js').RuleSet} RuleSet - * @typedef {import('./types.js').RulePseudo} RulePseudo - * @typedef {import('./types.js').Query} Query * @typedef {import('./types.js').Node} Node - * @typedef {import('./types.js').Parent} Parent * @typedef {import('./types.js').SelectIterator} SelectIterator * @typedef {import('./types.js').SelectState} SelectState */ @@ -79,12 +75,17 @@ function rule(query, tree, state) { 0, null, configure(query, { - scopeNodes: root(tree) ? tree.children : [tree], - index: false, + any: state.any, iterator, + scopeNodes: root(tree) ? tree.children : [tree], one: state.one, shallow: state.shallow, - any: state.any + index: false, + found: false, + typeIndex: state.typeIndex, + nodeIndex: state.nodeIndex, + typeCount: state.typeCount, + nodeCount: state.nodeCount }) ) diff --git a/lib/nest.js b/lib/nest.js index fb3c905..5ddf556 100644 --- a/lib/nest.js +++ b/lib/nest.js @@ -1,6 +1,5 @@ /** * @typedef {import('./types.js').Rule} Rule - * @typedef {import('./types.js').Query} Query * @typedef {import('./types.js').Node} Node * @typedef {import('./types.js').Parent} Parent * @typedef {import('./types.js').SelectState} SelectState diff --git a/lib/pseudo.js b/lib/pseudo.js index 134ab91..16f2992 100644 --- a/lib/pseudo.js +++ b/lib/pseudo.js @@ -61,10 +61,13 @@ const handle = zwitch('name', { }) pseudo.needsIndex = [ + 'any', 'first-child', 'first-of-type', 'last-child', 'last-of-type', + 'matches', + 'not', 'nth-child', 'nth-last-child', 'nth-of-type', @@ -104,8 +107,8 @@ function matches(query, node, _1, _2, state) { const shallow = state.shallow const one = state.one + state.shallow = false state.one = true - state.shallow = true const result = state.any(query.value, node, state)[0] === node diff --git a/lib/types.js b/lib/types.js index 0f92669..4a72247 100644 --- a/lib/types.js +++ b/lib/types.js @@ -31,16 +31,20 @@ * * @typedef {Object} SelectState * @property {(query: Selectors|RuleSet|Rule, node: Node|undefined, state: SelectState) => Node[]} any - * @property {Array.} [scopeNodes] * @property {SelectIterator|null|undefined} [iterator] + * @property {Array} [scopeNodes] * @property {boolean} [one=false] * @property {boolean} [shallow=false] * @property {boolean} [index=false] * @property {boolean} [found=false] - * @property {number} [typeIndex] Track siblings - * @property {number} [nodeIndex] Track siblings - * @property {number} [typeCount] Track siblings - * @property {number} [nodeCount] Track siblings + * @property {number} [typeIndex] + * Track siblings: this current node has `n` nodes with its type before it. + * @property {number} [nodeIndex] + * Track siblings: this current node has `n` nodes before it. + * @property {number} [typeCount] + * Track siblings: there are `n` siblings with this node’s type. + * @property {number} [nodeCount] + * Track siblings: there are `n` siblings. */ /** diff --git a/lib/util.js b/lib/util.js index 4986750..95f68ea 100644 --- a/lib/util.js +++ b/lib/util.js @@ -1,14 +1,6 @@ /** - * @typedef {import('./types.js').Selector} Selector - * @typedef {import('./types.js').Selectors} Selectors - * @typedef {import('./types.js').Rule} Rule - * @typedef {import('./types.js').RuleSet} RuleSet - * @typedef {import('./types.js').RulePseudo} RulePseudo - * @typedef {import('./types.js').Query} Query * @typedef {import('./types.js').Node} Node * @typedef {import('./types.js').Parent} Parent - * @typedef {import('./types.js').SelectIterator} SelectIterator - * @typedef {import('./types.js').SelectState} SelectState */ /** diff --git a/test/select-all.js b/test/select-all.js index 04d58a9..25d75aa 100644 --- a/test/select-all.js +++ b/test/select-all.js @@ -740,5 +740,35 @@ test('select.selectAll()', (t) => { st.end() }) + t.test(':any', (t) => { + t.deepEqual( + selectAll('y:any(:first-child)', u('x', [u('y', 'a'), u('y', 'b')])), + [u('y', 'a')], + 'should support parent-sensitive `:any`' + ) + + t.end() + }) + + t.test(':matches', (t) => { + t.deepEqual( + selectAll('y:matches(:first-child)', u('x', [u('y', 'a'), u('y', 'b')])), + [u('y', 'a')], + 'should support parent-sensitive `:matches`' + ) + + t.end() + }) + + t.test(':not', (t) => { + t.deepEqual( + selectAll('y:not(:first-child)', u('x', [u('y', 'a'), u('y', 'b')])), + [u('y', 'b')], + 'should support parent-sensitive `:not`' + ) + + t.end() + }) + t.end() }) diff --git a/test/select.js b/test/select.js index 306bb69..e9f5a02 100644 --- a/test/select.js +++ b/test/select.js @@ -706,5 +706,35 @@ test('select.select()', (t) => { st.end() }) + t.test(':any', (t) => { + t.deepEqual( + select('y:any(:first-child)', u('x', [u('y', 'a'), u('y', 'b')])), + u('y', 'a'), + 'should support parent-sensitive `:any`' + ) + + t.end() + }) + + t.test(':matches', (t) => { + t.deepEqual( + select('y:matches(:first-child)', u('x', [u('y', 'a'), u('y', 'b')])), + u('y', 'a'), + 'should support parent-sensitive `:matches`' + ) + + t.end() + }) + + t.test(':not', (t) => { + t.deepEqual( + select('y:not(:first-child)', u('x', [u('y', 'a'), u('y', 'b')])), + u('y', 'b'), + 'should support parent-sensitive `:not`' + ) + + t.end() + }) + t.end() })