88 * @typedef {import('./types.js').SelectState } SelectState
99 */
1010
11- import { html , svg } from 'property-information'
1211import { zwitch } from 'zwitch'
1312import { enterState } from './enter-state.js'
1413import { nest } from './nest.js'
1514import { pseudo } from './pseudo.js'
1615import { test } from './test.js'
1716
18- /** @type {(query: Selectors| RuleSet| Rule, element: Node, state: SelectState) => Array<Element> } */
17+ /** @type {(query: Selectors | RuleSet | Rule, element: Node, state: SelectState) => Array<Element> } */
1918const type = zwitch ( 'type' , {
2019 unknown : unknownType ,
2120 invalid : invalidType ,
2221 handlers : { selectors, ruleSet, rule}
2322} )
2423
2524/**
26- * @param {Selectors|RuleSet|Rule } query
27- * @param {Node|undefined } node
25+ * Handle an optional query and node.
26+ *
27+ * @param {Selectors | RuleSet | Rule | undefined } query
28+ * Thing to find.
29+ * @param {Node | undefined } node
30+ * Tree.
2831 * @param {SelectState } state
32+ * State.
2933 * @returns {Array<Element> }
34+ * Results.
3035 */
3136export function any ( query , node , state ) {
3237 return query && node ? type ( query , node , state ) : [ ]
3338}
3439
3540/**
41+ * Handle selectors.
42+ *
3643 * @param {Selectors } query
44+ * Multiple selectors.
3745 * @param {Node } node
46+ * Tree.
3847 * @param {SelectState } state
48+ * State.
3949 * @returns {Array<Element> }
50+ * Results.
4051 */
4152function selectors ( query , node , state ) {
4253 const collector = new Collector ( state . one )
4354 let index = - 1
4455
4556 while ( ++ index < query . selectors . length ) {
46- collector . collectAll ( ruleSet ( query . selectors [ index ] , node , state ) )
57+ const set = query . selectors [ index ]
58+ collector . collectAll ( rule ( set . rule , node , state ) )
4759 }
4860
4961 return collector . result
5062}
5163
5264/**
65+ * Handle a selector.
66+ *
5367 * @param {RuleSet } query
68+ * One selector.
5469 * @param {Node } node
70+ * Tree.
5571 * @param {SelectState } state
72+ * State.
5673 * @returns {Array<Element> }
74+ * Results.
5775 */
5876function ruleSet ( query , node , state ) {
5977 return rule ( query . rule , node , state )
6078}
6179
6280/**
81+ * Handle a rule.
82+ *
6383 * @param {Rule } query
84+ * One rule.
6485 * @param {Node } tree
86+ * Tree.
6587 * @param {SelectState } state
88+ * State.
6689 * @returns {Array<Element> }
90+ * Results.
6791 */
6892function rule ( query , tree , state ) {
6993 const collector = new Collector ( state . one )
@@ -72,30 +96,11 @@ function rule(query, tree, state) {
7296 throw new Error ( 'Expected selector without nesting' )
7397 }
7498
75- nest (
76- query ,
77- tree ,
78- 0 ,
79- undefined ,
80- configure ( query , {
81- // @ts -expect-error assume elements.
82- scopeElements : tree . type === 'root' ? tree . children : [ tree ] ,
83- iterator,
84- one : state . one ,
85- shallow : state . shallow ,
86- index : false ,
87- found : false ,
88- space : state . space ,
89- schema : state . space === 'svg' ? svg : html ,
90- language : undefined ,
91- direction : 'ltr' ,
92- editableOrEditingHost : false ,
93- typeIndex : state . typeIndex ,
94- elementIndex : state . elementIndex ,
95- typeCount : state . typeCount ,
96- elementCount : state . elementCount
97- } )
98- )
99+ nest ( query , tree , 0 , undefined , {
100+ ...state ,
101+ iterator,
102+ index : needsIndex ( query )
103+ } )
99104
100105 return collector . result
101106
@@ -105,7 +110,11 @@ function rule(query, tree, state) {
105110
106111 if ( test ( query , node , index , parent , state ) ) {
107112 if ( query . rule ) {
108- nest ( query . rule , node , index , parent , configure ( query . rule , state ) )
113+ nest ( query . rule , node , index , parent , {
114+ ...state ,
115+ iterator,
116+ index : needsIndex ( query . rule )
117+ } )
109118 } else {
110119 // @ts -expect-error `test` also asserts `node is Element`
111120 collector . collect ( node )
@@ -115,26 +124,25 @@ function rule(query, tree, state) {
115124
116125 exit ( )
117126 }
127+ }
118128
119- /**
120- * @template {SelectState} S
121- * @param { Rule } query
122- * @param {S } state
123- * @returns {S }
124- */
125- function configure ( query , state ) {
126- const pseudos = query . pseudos || [ ]
127- let index = - 1
129+ /**
130+ * Check if indexing is needed.
131+ *
132+ * @param {Rule } query
133+ * @returns {boolean }
134+ */
135+ function needsIndex ( query ) {
136+ const pseudos = query . pseudos || [ ]
137+ let index = - 1
128138
129- while ( ++ index < pseudos . length ) {
130- if ( pseudo . needsIndex . includes ( pseudos [ index ] . name ) ) {
131- state . index = true
132- break
133- }
139+ while ( ++ index < pseudos . length ) {
140+ if ( pseudo . needsIndex . includes ( pseudos [ index ] . name ) ) {
141+ return true
134142 }
135-
136- return state
137143 }
144+
145+ return false
138146}
139147
140148// Shouldn’t be called, all data is handled.
@@ -154,21 +162,38 @@ function invalidType() {
154162 throw new Error ( 'Invalid type' )
155163}
156164
165+ /**
166+ * Collect elements.
167+ */
157168class Collector {
158169 /**
159- * @param {boolean| undefined } [ one]
170+ * @param {boolean | undefined } one
160171 */
161172 constructor ( one ) {
162- /** @type {Array<Element> } */
173+ /**
174+ * Found elements.
175+ *
176+ * @type {Array<Element> }
177+ */
163178 this . result = [ ]
164- /** @type {boolean|undefined } */
165- this . one = one
166- /** @type {boolean } */
179+
180+ /**
181+ * Whether we’re looking for one result.
182+ *
183+ * @type {boolean }
184+ */
185+ this . one = one || false
186+
187+ /**
188+ * Whether we’ve found something.
189+ *
190+ * @type {boolean }
191+ */
167192 this . found = false
168193 }
169194
170195 /**
171- * Append nodes to array, filtering out duplicates .
196+ * Add multiple elements .
172197 *
173198 * @param {Array<Element> } elements
174199 */
@@ -181,7 +206,7 @@ class Collector {
181206 }
182207
183208 /**
184- * Append one node .
209+ * Add one element .
185210 *
186211 * @param {Element } element
187212 */
0 commit comments