1
+ /**
2
+ * @typedef {import('hast').Element } Element
3
+ * @typedef {import('./types.js').Selectors } Selectors
4
+ * @typedef {import('./types.js').Rule } Rule
5
+ * @typedef {import('./types.js').RuleSet } RuleSet
6
+ * @typedef {import('./types.js').HastNode } HastNode
7
+ * @typedef {import('./types.js').SelectIterator } SelectIterator
8
+ * @typedef {import('./types.js').SelectState } SelectState
9
+ */
10
+
1
11
import { html , svg } from 'property-information'
2
12
import { zwitch } from 'zwitch'
3
13
import { enterState } from './enter-state.js'
@@ -11,27 +21,52 @@ var type = zwitch('type', {
11
21
handlers : { selectors, ruleSet, rule}
12
22
} )
13
23
24
+ /**
25
+ * @param {Selectors|RuleSet|Rule } query
26
+ * @param {HastNode } node
27
+ * @param {SelectState } state
28
+ * @returns {Array.<Element> }
29
+ */
14
30
export function any ( query , node , state ) {
31
+ // @ts -ignore zwitch types are off.
15
32
return query && node ? type ( query , node , state ) : [ ]
16
33
}
17
34
35
+ /**
36
+ * @param {Selectors } query
37
+ * @param {HastNode } node
38
+ * @param {SelectState } state
39
+ * @returns {Array.<Element> }
40
+ */
18
41
function selectors ( query , node , state ) {
19
- var collect = collector ( state . one )
42
+ var collector = new Collector ( state . one )
20
43
var index = - 1
21
44
22
45
while ( ++ index < query . selectors . length ) {
23
- collect ( ruleSet ( query . selectors [ index ] , node , state ) )
46
+ collector . collectAll ( ruleSet ( query . selectors [ index ] , node , state ) )
24
47
}
25
48
26
- return collect . result
49
+ return collector . result
27
50
}
28
51
52
+ /**
53
+ * @param {RuleSet } query
54
+ * @param {HastNode } node
55
+ * @param {SelectState } state
56
+ * @returns {Array.<Element> }
57
+ */
29
58
function ruleSet ( query , node , state ) {
30
59
return rule ( query . rule , node , state )
31
60
}
32
61
62
+ /**
63
+ * @param {Rule } query
64
+ * @param {HastNode } tree
65
+ * @param {SelectState } state
66
+ * @returns {Array.<Element> }
67
+ */
33
68
function rule ( query , tree , state ) {
34
- var collect = collector ( state . one )
69
+ var collector = new Collector ( state . one )
35
70
36
71
if ( state . shallow && query . rule ) {
37
72
throw new Error ( 'Expected selector without nesting' )
@@ -47,30 +82,39 @@ function rule(query, tree, state) {
47
82
language : null ,
48
83
direction : 'ltr' ,
49
84
editableOrEditingHost : false ,
85
+ // @ts -ignore assume elements.
50
86
scopeElements : tree . type === 'root' ? tree . children : [ tree ] ,
51
87
iterator,
52
88
one : state . one ,
53
89
shallow : state . shallow
54
90
} )
55
91
)
56
92
57
- return collect . result
93
+ return collector . result
58
94
95
+ /** @type {SelectIterator } */
59
96
function iterator ( query , node , index , parent , state ) {
60
97
var exit = enterState ( state , node )
61
98
62
99
if ( test ( query , node , index , parent , state ) ) {
63
100
if ( query . rule ) {
64
101
nest ( query . rule , node , index , parent , configure ( query . rule , state ) )
65
102
} else {
66
- collect ( node )
103
+ // @ts -ignore `test` also asserts `node is Element`
104
+ collector . collect ( node )
67
105
state . found = true
68
106
}
69
107
}
70
108
71
109
exit ( )
72
110
}
73
111
112
+ /**
113
+ * @template {SelectState} S
114
+ * @param {Rule } query
115
+ * @param {S } state
116
+ * @returns {S }
117
+ */
74
118
function configure ( query , state ) {
75
119
var pseudos = query . pseudos || [ ]
76
120
var index = - 1
@@ -87,7 +131,10 @@ function rule(query, tree, state) {
87
131
}
88
132
89
133
// Shouldn’t be called, all data is handled.
90
- /* c8 ignore next 3 */
134
+ /* c8 ignore next 6 */
135
+ /**
136
+ * @param {{[x: string]: unknown, type: string} } query
137
+ */
91
138
function unknownType ( query ) {
92
139
throw new Error ( 'Unknown type `' + query . type + '`' )
93
140
}
@@ -98,35 +145,45 @@ function invalidType() {
98
145
throw new Error ( 'Invalid type' )
99
146
}
100
147
101
- function collector ( one ) {
102
- var result = [ ]
103
- var found
104
-
105
- collect . result = result
106
-
107
- return collect
148
+ class Collector {
149
+ /**
150
+ * @param {boolean } one
151
+ */
152
+ constructor ( one ) {
153
+ /** @type {Array.<Element> } */
154
+ this . result = [ ]
155
+ /** @type {boolean } */
156
+ this . one = one
157
+ /** @type {boolean } */
158
+ this . found = false
159
+ }
108
160
109
- // Append elements to array, filtering out duplicates.
110
- function collect ( source ) {
161
+ /**
162
+ * Append nodes to array, filtering out duplicates.
163
+ *
164
+ * @param {Array.<Element> } elements
165
+ */
166
+ collectAll ( elements ) {
111
167
var index = - 1
112
168
113
- if ( 'length' in source ) {
114
- while ( ++ index < source . length ) {
115
- collectOne ( source [ index ] )
116
- }
117
- } else {
118
- collectOne ( source )
169
+ while ( ++ index < elements . length ) {
170
+ this . collect ( elements [ index ] )
119
171
}
172
+ }
120
173
121
- function collectOne ( element ) {
122
- if ( one ) {
123
- // Shouldn’t happen, safeguards performance problems.
124
- /* c8 ignore next */
125
- if ( found ) throw new Error ( 'Cannot collect multiple nodes' )
126
- found = true
127
- }
128
-
129
- if ( ! result . includes ( element ) ) result . push ( element )
174
+ /**
175
+ * Append one node.
176
+ *
177
+ * @param {Element } element
178
+ */
179
+ collect ( element ) {
180
+ if ( this . one ) {
181
+ // Shouldn’t happen, safeguards performance problems.
182
+ /* c8 ignore next */
183
+ if ( this . found ) throw new Error ( 'Cannot collect multiple nodes' )
184
+ this . found = true
130
185
}
186
+
187
+ if ( ! this . result . includes ( element ) ) this . result . push ( element )
131
188
}
132
189
}
0 commit comments