@@ -26,6 +26,7 @@ export function querySelectorDeep(selector, root = document) {
26
26
}
27
27
28
28
function _querySelectorDeep ( selector , findMany , root ) {
29
+ selector = normalizeSelector ( selector )
29
30
let lightElement = root . querySelector ( selector ) ;
30
31
31
32
if ( document . head . createShadowRoot || document . head . attachShadow ) {
@@ -150,4 +151,162 @@ function collectAllElementsDeep(selector = null, root) {
150
151
findAllElements ( root . querySelectorAll ( '*' ) ) ;
151
152
152
153
return selector ? allElements . filter ( el => el . matches ( selector ) ) : allElements ;
153
- }
154
+ }
155
+
156
+
157
+ // normalize-selector-rev-02.js
158
+ /*
159
+ author: kyle simpson (@getify)
160
+ original source: https://gist.github.com/getify/9679380
161
+
162
+ modified for tests by david kaye (@dfkaye)
163
+ 21 march 2014
164
+
165
+ rev-02 incorporate kyle's changes 3/2/42014
166
+ */
167
+ /* istanbul ignore next */
168
+ function normalizeSelector ( sel ) {
169
+
170
+ // save unmatched text, if any
171
+ function saveUnmatched ( ) {
172
+ if ( unmatched ) {
173
+ // whitespace needed after combinator?
174
+ if ( tokens . length > 0 &&
175
+ / ^ [ ~ + > ] $ / . test ( tokens [ tokens . length - 1 ] )
176
+ ) {
177
+ tokens . push ( " " ) ;
178
+ }
179
+
180
+ // save unmatched text
181
+ tokens . push ( unmatched ) ;
182
+ }
183
+ }
184
+
185
+ var tokens = [ ] , match , unmatched , regex , state = [ 0 ] ,
186
+ next_match_idx = 0 , prev_match_idx ,
187
+ not_escaped_pattern = / (?: [ ^ \\ ] | (?: ^ | [ ^ \\ ] ) (?: \\ \\ ) + ) $ / ,
188
+ whitespace_pattern = / ^ \s + $ / ,
189
+ state_patterns = [
190
+ / \s + | \/ \* | [ " ' > ~ + \[ \( ] / g, // general
191
+ / \s + | \/ \* | [ " ' \[ \] \( \) ] / g, // [..] set
192
+ / \s + | \/ \* | [ " ' \[ \] \( \) ] / g, // (..) set
193
+ null , // string literal (placeholder)
194
+ / \* \/ / g // comment
195
+ ]
196
+ ;
197
+
198
+ sel = sel . trim ( ) ;
199
+
200
+ while ( true ) {
201
+ unmatched = "" ;
202
+
203
+ regex = state_patterns [ state [ state . length - 1 ] ] ;
204
+
205
+ regex . lastIndex = next_match_idx ;
206
+ match = regex . exec ( sel ) ;
207
+
208
+ // matched text to process?
209
+ if ( match ) {
210
+ prev_match_idx = next_match_idx ;
211
+ next_match_idx = regex . lastIndex ;
212
+
213
+ // collect the previous string chunk not matched before this token
214
+ if ( prev_match_idx < next_match_idx - match [ 0 ] . length ) {
215
+ unmatched = sel . substring ( prev_match_idx , next_match_idx - match [ 0 ] . length ) ;
216
+ }
217
+
218
+ // general, [ ] pair, ( ) pair?
219
+ if ( state [ state . length - 1 ] < 3 ) {
220
+ saveUnmatched ( ) ;
221
+
222
+ // starting a [ ] pair?
223
+ if ( match [ 0 ] === "[" ) {
224
+ state . push ( 1 ) ;
225
+ }
226
+ // starting a ( ) pair?
227
+ else if ( match [ 0 ] === "(" ) {
228
+ state . push ( 2 ) ;
229
+ }
230
+ // starting a string literal?
231
+ else if ( / ^ [ " ' ] $ / . test ( match [ 0 ] ) ) {
232
+ state . push ( 3 ) ;
233
+ state_patterns [ 3 ] = new RegExp ( match [ 0 ] , "g" ) ;
234
+ }
235
+ // starting a comment?
236
+ else if ( match [ 0 ] === "/*" ) {
237
+ state . push ( 4 ) ;
238
+ }
239
+ // ending a [ ] or ( ) pair?
240
+ else if ( / ^ [ \] \) ] $ / . test ( match [ 0 ] ) && state . length > 0 ) {
241
+ state . pop ( ) ;
242
+ }
243
+ // handling whitespace or a combinator?
244
+ else if ( / ^ (?: \s + | [ ~ + > ] ) $ / . test ( match [ 0 ] ) ) {
245
+
246
+ // need to insert whitespace before?
247
+ if ( tokens . length > 0 &&
248
+ ! whitespace_pattern . test ( tokens [ tokens . length - 1 ] ) &&
249
+ state [ state . length - 1 ] === 0
250
+ ) {
251
+ // add normalized whitespace
252
+ tokens . push ( " " ) ;
253
+ }
254
+
255
+ // case-insensitive attribute selector CSS L4
256
+ if ( state [ state . length - 1 ] === 1 &&
257
+ tokens . length === 5 &&
258
+ tokens [ 2 ] . charAt ( tokens [ 2 ] . length - 1 ) === '=' ) {
259
+ tokens [ 4 ] = " " + tokens [ 4 ] ;
260
+ }
261
+
262
+ // whitespace token we can skip?
263
+ if ( whitespace_pattern . test ( match [ 0 ] ) ) {
264
+ continue ;
265
+ }
266
+ }
267
+
268
+ // save matched text
269
+ tokens . push ( match [ 0 ] ) ;
270
+ }
271
+ // otherwise, string literal or comment
272
+ else {
273
+ // save unmatched text
274
+ tokens [ tokens . length - 1 ] += unmatched ;
275
+
276
+ // unescaped terminator to string literal or comment?
277
+ if ( not_escaped_pattern . test ( tokens [ tokens . length - 1 ] ) ) {
278
+ // comment terminator?
279
+ if ( state [ state . length - 1 ] === 4 ) {
280
+ // ok to drop comment?
281
+ if ( tokens . length < 2 ||
282
+ whitespace_pattern . test ( tokens [ tokens . length - 2 ] )
283
+ ) {
284
+ tokens . pop ( ) ;
285
+ }
286
+ // otherwise, turn comment into whitespace
287
+ else {
288
+ tokens [ tokens . length - 1 ] = " " ;
289
+ }
290
+
291
+ // handled already
292
+ match [ 0 ] = "" ;
293
+ }
294
+
295
+ state . pop ( ) ;
296
+ }
297
+
298
+ // append matched text to existing token
299
+ tokens [ tokens . length - 1 ] += match [ 0 ] ;
300
+ }
301
+ }
302
+ // otherwise, end of processing (no more matches)
303
+ else {
304
+ unmatched = sel . substr ( next_match_idx ) ;
305
+ saveUnmatched ( ) ;
306
+
307
+ break ;
308
+ }
309
+ }
310
+
311
+ return tokens . join ( "" ) . trim ( ) ;
312
+ }
0 commit comments