Skip to content

Commit

Permalink
Fix support for parent-sensitive pseudos
Browse files Browse the repository at this point in the history
Previously, `:any`, `:matches`, and `:not` did not support
selectors sensitive to their parent.
This is now fixed.

Related-to syntax-tree/hast-util-select#5.
  • Loading branch information
wooorm committed Dec 31, 2022
1 parent 96ea63a commit beca7d5
Show file tree
Hide file tree
Showing 7 changed files with 81 additions and 22 deletions.
15 changes: 8 additions & 7 deletions lib/any.js
Original file line number Diff line number Diff line change
@@ -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
*/
Expand Down Expand Up @@ -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
})
)

Expand Down
1 change: 0 additions & 1 deletion lib/nest.js
Original file line number Diff line number Diff line change
@@ -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
Expand Down
5 changes: 4 additions & 1 deletion lib/pseudo.js
Original file line number Diff line number Diff line change
Expand Up @@ -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',
Expand Down Expand Up @@ -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

Expand Down
14 changes: 9 additions & 5 deletions lib/types.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,16 +31,20 @@
*
* @typedef {Object} SelectState
* @property {(query: Selectors|RuleSet|Rule, node: Node|undefined, state: SelectState) => Node[]} any
* @property {Array.<Node>} [scopeNodes]
* @property {SelectIterator|null|undefined} [iterator]
* @property {Array<Node>} [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.
*/

/**
Expand Down
8 changes: 0 additions & 8 deletions lib/util.js
Original file line number Diff line number Diff line change
@@ -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
*/

/**
Expand Down
30 changes: 30 additions & 0 deletions test/select-all.js
Original file line number Diff line number Diff line change
Expand Up @@ -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()
})
30 changes: 30 additions & 0 deletions test/select.js
Original file line number Diff line number Diff line change
Expand Up @@ -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()
})

0 comments on commit beca7d5

Please sign in to comment.