@@ -26,6 +26,7 @@ export function querySelectorDeep(selector, root = document) {
2626}
2727
2828function _querySelectorDeep ( selector , findMany , root ) {
29+ selector = normalizeSelector ( selector )
2930 let lightElement = root . querySelector ( selector ) ;
3031
3132 if ( document . head . createShadowRoot || document . head . attachShadow ) {
@@ -150,4 +151,167 @@ function collectAllElementsDeep(selector = null, root) {
150151 findAllElements ( root . querySelectorAll ( '*' ) ) ;
151152
152153 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+ if ( typeof require == 'function' && typeof module != 'undefined' ) {
168+ // enable to re-use in a browser without require.js
169+ module . exports = normalizeSelector ;
170+ }
171+
172+
173+ function normalizeSelector ( sel ) {
174+
175+ // save unmatched text, if any
176+ function saveUnmatched ( ) {
177+ if ( unmatched ) {
178+ // whitespace needed after combinator?
179+ if ( tokens . length > 0 &&
180+ / ^ [ ~ + > ] $ / . test ( tokens [ tokens . length - 1 ] )
181+ ) {
182+ tokens . push ( " " ) ;
183+ }
184+
185+ // save unmatched text
186+ tokens . push ( unmatched ) ;
187+ }
188+ }
189+
190+ var tokens = [ ] , match , unmatched , regex , state = [ 0 ] ,
191+ next_match_idx = 0 , prev_match_idx ,
192+ not_escaped_pattern = / (?: [ ^ \\ ] | (?: ^ | [ ^ \\ ] ) (?: \\ \\ ) + ) $ / ,
193+ whitespace_pattern = / ^ \s + $ / ,
194+ state_patterns = [
195+ / \s + | \/ \* | [ " ' > ~ + \[ \( ] / g, // general
196+ / \s + | \/ \* | [ " ' \[ \] \( \) ] / g, // [..] set
197+ / \s + | \/ \* | [ " ' \[ \] \( \) ] / g, // (..) set
198+ null , // string literal (placeholder)
199+ / \* \/ / g // comment
200+ ]
201+ ;
202+
203+ sel = sel . trim ( ) ;
204+
205+ while ( true ) {
206+ unmatched = "" ;
207+
208+ regex = state_patterns [ state [ state . length - 1 ] ] ;
209+
210+ regex . lastIndex = next_match_idx ;
211+ match = regex . exec ( sel ) ;
212+
213+ // matched text to process?
214+ if ( match ) {
215+ prev_match_idx = next_match_idx ;
216+ next_match_idx = regex . lastIndex ;
217+
218+ // collect the previous string chunk not matched before this token
219+ if ( prev_match_idx < next_match_idx - match [ 0 ] . length ) {
220+ unmatched = sel . substring ( prev_match_idx , next_match_idx - match [ 0 ] . length ) ;
221+ }
222+
223+ // general, [ ] pair, ( ) pair?
224+ if ( state [ state . length - 1 ] < 3 ) {
225+ saveUnmatched ( ) ;
226+
227+ // starting a [ ] pair?
228+ if ( match [ 0 ] === "[" ) {
229+ state . push ( 1 ) ;
230+ }
231+ // starting a ( ) pair?
232+ else if ( match [ 0 ] === "(" ) {
233+ state . push ( 2 ) ;
234+ }
235+ // starting a string literal?
236+ else if ( / ^ [ " ' ] $ / . test ( match [ 0 ] ) ) {
237+ state . push ( 3 ) ;
238+ state_patterns [ 3 ] = new RegExp ( match [ 0 ] , "g" ) ;
239+ }
240+ // starting a comment?
241+ else if ( match [ 0 ] === "/*" ) {
242+ state . push ( 4 ) ;
243+ }
244+ // ending a [ ] or ( ) pair?
245+ else if ( / ^ [ \] \) ] $ / . test ( match [ 0 ] ) && state . length > 0 ) {
246+ state . pop ( ) ;
247+ }
248+ // handling whitespace or a combinator?
249+ else if ( / ^ (?: \s + | [ ~ + > ] ) $ / . test ( match [ 0 ] ) ) {
250+
251+ // need to insert whitespace before?
252+ if ( tokens . length > 0 &&
253+ ! whitespace_pattern . test ( tokens [ tokens . length - 1 ] ) &&
254+ state [ state . length - 1 ] === 0
255+ ) {
256+ // add normalized whitespace
257+ tokens . push ( " " ) ;
258+ }
259+
260+ // case-insensitive attribute selector CSS L4
261+ if ( state [ state . length - 1 ] === 1 &&
262+ tokens . length === 5 &&
263+ tokens [ 2 ] . charAt ( tokens [ 2 ] . length - 1 ) === '=' ) {
264+ tokens [ 4 ] = " " + tokens [ 4 ] ;
265+ }
266+
267+ // whitespace token we can skip?
268+ if ( whitespace_pattern . test ( match [ 0 ] ) ) {
269+ continue ;
270+ }
271+ }
272+
273+ // save matched text
274+ tokens . push ( match [ 0 ] ) ;
275+ }
276+ // otherwise, string literal or comment
277+ else {
278+ // save unmatched text
279+ tokens [ tokens . length - 1 ] += unmatched ;
280+
281+ // unescaped terminator to string literal or comment?
282+ if ( not_escaped_pattern . test ( tokens [ tokens . length - 1 ] ) ) {
283+ // comment terminator?
284+ if ( state [ state . length - 1 ] === 4 ) {
285+ // ok to drop comment?
286+ if ( tokens . length < 2 ||
287+ whitespace_pattern . test ( tokens [ tokens . length - 2 ] )
288+ ) {
289+ tokens . pop ( ) ;
290+ }
291+ // otherwise, turn comment into whitespace
292+ else {
293+ tokens [ tokens . length - 1 ] = " " ;
294+ }
295+
296+ // handled already
297+ match [ 0 ] = "" ;
298+ }
299+
300+ state . pop ( ) ;
301+ }
302+
303+ // append matched text to existing token
304+ tokens [ tokens . length - 1 ] += match [ 0 ] ;
305+ }
306+ }
307+ // otherwise, end of processing (no more matches)
308+ else {
309+ unmatched = sel . substr ( next_match_idx ) ;
310+ saveUnmatched ( ) ;
311+
312+ break ;
313+ }
314+ }
315+
316+ return tokens . join ( "" ) . trim ( ) ;
317+ }
0 commit comments