8
8
* @typedef {import('./types.js').SelectState } SelectState
9
9
*/
10
10
11
- import { html , svg } from 'property-information'
12
11
import { zwitch } from 'zwitch'
13
12
import { enterState } from './enter-state.js'
14
13
import { nest } from './nest.js'
15
14
import { pseudo } from './pseudo.js'
16
15
import { test } from './test.js'
17
16
18
- /** @type {(query: Selectors| RuleSet| Rule, element: Node, state: SelectState) => Array<Element> } */
17
+ /** @type {(query: Selectors | RuleSet | Rule, element: Node, state: SelectState) => Array<Element> } */
19
18
const type = zwitch ( 'type' , {
20
19
unknown : unknownType ,
21
20
invalid : invalidType ,
22
21
handlers : { selectors, ruleSet, rule}
23
22
} )
24
23
25
24
/**
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.
28
31
* @param {SelectState } state
32
+ * State.
29
33
* @returns {Array<Element> }
34
+ * Results.
30
35
*/
31
36
export function any ( query , node , state ) {
32
37
return query && node ? type ( query , node , state ) : [ ]
33
38
}
34
39
35
40
/**
41
+ * Handle selectors.
42
+ *
36
43
* @param {Selectors } query
44
+ * Multiple selectors.
37
45
* @param {Node } node
46
+ * Tree.
38
47
* @param {SelectState } state
48
+ * State.
39
49
* @returns {Array<Element> }
50
+ * Results.
40
51
*/
41
52
function selectors ( query , node , state ) {
42
53
const collector = new Collector ( state . one )
43
54
let index = - 1
44
55
45
56
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 ) )
47
59
}
48
60
49
61
return collector . result
50
62
}
51
63
52
64
/**
65
+ * Handle a selector.
66
+ *
53
67
* @param {RuleSet } query
68
+ * One selector.
54
69
* @param {Node } node
70
+ * Tree.
55
71
* @param {SelectState } state
72
+ * State.
56
73
* @returns {Array<Element> }
74
+ * Results.
57
75
*/
58
76
function ruleSet ( query , node , state ) {
59
77
return rule ( query . rule , node , state )
60
78
}
61
79
62
80
/**
81
+ * Handle a rule.
82
+ *
63
83
* @param {Rule } query
84
+ * One rule.
64
85
* @param {Node } tree
86
+ * Tree.
65
87
* @param {SelectState } state
88
+ * State.
66
89
* @returns {Array<Element> }
90
+ * Results.
67
91
*/
68
92
function rule ( query , tree , state ) {
69
93
const collector = new Collector ( state . one )
@@ -72,30 +96,11 @@ function rule(query, tree, state) {
72
96
throw new Error ( 'Expected selector without nesting' )
73
97
}
74
98
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
+ } )
99
104
100
105
return collector . result
101
106
@@ -105,7 +110,11 @@ function rule(query, tree, state) {
105
110
106
111
if ( test ( query , node , index , parent , state ) ) {
107
112
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
+ } )
109
118
} else {
110
119
// @ts -expect-error `test` also asserts `node is Element`
111
120
collector . collect ( node )
@@ -115,26 +124,25 @@ function rule(query, tree, state) {
115
124
116
125
exit ( )
117
126
}
127
+ }
118
128
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
128
138
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
134
142
}
135
-
136
- return state
137
143
}
144
+
145
+ return false
138
146
}
139
147
140
148
// Shouldn’t be called, all data is handled.
@@ -154,21 +162,38 @@ function invalidType() {
154
162
throw new Error ( 'Invalid type' )
155
163
}
156
164
165
+ /**
166
+ * Collect elements.
167
+ */
157
168
class Collector {
158
169
/**
159
- * @param {boolean| undefined } [ one]
170
+ * @param {boolean | undefined } one
160
171
*/
161
172
constructor ( one ) {
162
- /** @type {Array<Element> } */
173
+ /**
174
+ * Found elements.
175
+ *
176
+ * @type {Array<Element> }
177
+ */
163
178
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
+ */
167
192
this . found = false
168
193
}
169
194
170
195
/**
171
- * Append nodes to array, filtering out duplicates .
196
+ * Add multiple elements .
172
197
*
173
198
* @param {Array<Element> } elements
174
199
*/
@@ -181,7 +206,7 @@ class Collector {
181
206
}
182
207
183
208
/**
184
- * Append one node .
209
+ * Add one element .
185
210
*
186
211
* @param {Element } element
187
212
*/
0 commit comments