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+
111import { html , svg } from 'property-information'
212import { zwitch } from 'zwitch'
313import { enterState } from './enter-state.js'
@@ -11,27 +21,52 @@ var type = zwitch('type', {
1121 handlers : { selectors, ruleSet, rule}
1222} )
1323
24+ /**
25+ * @param {Selectors|RuleSet|Rule } query
26+ * @param {HastNode } node
27+ * @param {SelectState } state
28+ * @returns {Array.<Element> }
29+ */
1430export function any ( query , node , state ) {
31+ // @ts -ignore zwitch types are off.
1532 return query && node ? type ( query , node , state ) : [ ]
1633}
1734
35+ /**
36+ * @param {Selectors } query
37+ * @param {HastNode } node
38+ * @param {SelectState } state
39+ * @returns {Array.<Element> }
40+ */
1841function selectors ( query , node , state ) {
19- var collect = collector ( state . one )
42+ var collector = new Collector ( state . one )
2043 var index = - 1
2144
2245 while ( ++ index < query . selectors . length ) {
23- collect ( ruleSet ( query . selectors [ index ] , node , state ) )
46+ collector . collectAll ( ruleSet ( query . selectors [ index ] , node , state ) )
2447 }
2548
26- return collect . result
49+ return collector . result
2750}
2851
52+ /**
53+ * @param {RuleSet } query
54+ * @param {HastNode } node
55+ * @param {SelectState } state
56+ * @returns {Array.<Element> }
57+ */
2958function ruleSet ( query , node , state ) {
3059 return rule ( query . rule , node , state )
3160}
3261
62+ /**
63+ * @param {Rule } query
64+ * @param {HastNode } tree
65+ * @param {SelectState } state
66+ * @returns {Array.<Element> }
67+ */
3368function rule ( query , tree , state ) {
34- var collect = collector ( state . one )
69+ var collector = new Collector ( state . one )
3570
3671 if ( state . shallow && query . rule ) {
3772 throw new Error ( 'Expected selector without nesting' )
@@ -47,30 +82,39 @@ function rule(query, tree, state) {
4782 language : null ,
4883 direction : 'ltr' ,
4984 editableOrEditingHost : false ,
85+ // @ts -ignore assume elements.
5086 scopeElements : tree . type === 'root' ? tree . children : [ tree ] ,
5187 iterator,
5288 one : state . one ,
5389 shallow : state . shallow
5490 } )
5591 )
5692
57- return collect . result
93+ return collector . result
5894
95+ /** @type {SelectIterator } */
5996 function iterator ( query , node , index , parent , state ) {
6097 var exit = enterState ( state , node )
6198
6299 if ( test ( query , node , index , parent , state ) ) {
63100 if ( query . rule ) {
64101 nest ( query . rule , node , index , parent , configure ( query . rule , state ) )
65102 } else {
66- collect ( node )
103+ // @ts -ignore `test` also asserts `node is Element`
104+ collector . collect ( node )
67105 state . found = true
68106 }
69107 }
70108
71109 exit ( )
72110 }
73111
112+ /**
113+ * @template {SelectState} S
114+ * @param {Rule } query
115+ * @param {S } state
116+ * @returns {S }
117+ */
74118 function configure ( query , state ) {
75119 var pseudos = query . pseudos || [ ]
76120 var index = - 1
@@ -87,7 +131,10 @@ function rule(query, tree, state) {
87131}
88132
89133// 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+ */
91138function unknownType ( query ) {
92139 throw new Error ( 'Unknown type `' + query . type + '`' )
93140}
@@ -98,35 +145,45 @@ function invalidType() {
98145 throw new Error ( 'Invalid type' )
99146}
100147
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+ }
108160
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 ) {
111167 var index = - 1
112168
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 ] )
119171 }
172+ }
120173
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
130185 }
186+
187+ if ( ! this . result . includes ( element ) ) this . result . push ( element )
131188 }
132189}
0 commit comments