44// We could almost use `/\b\s(?![><+~][\s]+?)/` to split the selector but this doesn't work with attribute selectors
55var RE_SELECTOR_DESCENDANT_SPLIT = ( / ( .* ?(?: (?: \( [ ^ \) ] + \) | \[ [ ^ \] ] + \] | (? ! [ > < + ~ \s ] ) .) + ) (?: (?: (?: \s (? ! > > ) ) | (?: \t (? ! > > ) ) | (?: \s ? > > \s ? ) ) (? ! \s + ) ) (? ! [ > < + ~ ] [ \s ] + ?) ) / ) ;
66
7+ // Separate selector to classes and ids
8+ var RE_SELECTOR_SEPARATOR = / ( ( [ \. # ] ? ) [ ^ \. # ] + ) / g;
9+
10+ // Helper function to get all combination of a text array
11+ var getCombinations = function ( strings ) {
12+ var result = [ ] ;
13+ var f = function ( prefix , strings ) {
14+ for ( var i = 0 ; i < strings . length ; i ++ ) {
15+ result . push ( prefix + strings [ i ] ) ;
16+ f ( prefix + strings [ i ] , strings . slice ( i + 1 ) ) ;
17+ }
18+ }
19+ f ( '' , strings ) ;
20+ return result ;
21+ }
722
823var generateDescendantPiecesFromSelector = function ( selector ) {
924 return selector . split ( RE_SELECTOR_DESCENDANT_SPLIT )
@@ -17,7 +32,19 @@ var generateDescendantPiecesFromSelector = function(selector) {
1732 // Trim whitespace which would be a normal descendant selector
1833 // and trim off the CSS4 descendant `>>` into a normal descendant selector
1934 return piece . trim ( ) . replace ( / \s * ?> > \s * ?/ g, '' ) ;
20- } ) ;
35+ } )
36+ . reduce ( function ( result , piece ) {
37+ if ( piece . indexOf ( ' ' ) !== - 1 ) {
38+ result . push ( piece ) ;
39+ return result ;
40+ }
41+ // a.b#c => [a, .b, #c]
42+ var pieces = piece . match ( RE_SELECTOR_SEPARATOR ) ;
43+ // [a, .b, #c] => [a, a.b, a.b#c, a#c, .b, .b#c, #c]
44+ var combinations = getCombinations ( pieces ) ;
45+ result = result . concat ( combinations ) ;
46+ return result ;
47+ } , [ ] ) ;
2148} ;
2249
2350module . exports = generateDescendantPiecesFromSelector ;
0 commit comments