@@ -4,7 +4,6 @@ module.exports = parse;
4
4
5
5
var re_ws = / ^ \s / ,
6
6
re_name = / ^ (?: \\ .| [ \w \- \u00c0 - \uFFFF ] ) + / ,
7
- re_cleanSelector = / ( [ ^ \\ ] ) \s * ( [ > < ~ + , ] | $ ) \s * / g,
8
7
re_combinators = / ^ \s * [ ^ \\ ] \s * [ > ~ + , ] | $ \s * / g,
9
8
re_escape = / \\ ( [ \d a - f ] { 1 , 6 } \s ? | ( \s ) | .) / ig,
10
9
re_comma = / ^ \s * , \s * / ,
@@ -69,10 +68,11 @@ function getClosingPos(selector){
69
68
}
70
69
71
70
function parse ( selector , options ) {
72
- selector = ( selector + "" ) . trimLeft ( ) . replace ( re_cleanSelector , "$1$2" ) ;
71
+ selector = ( selector + "" ) . trimLeft ( ) ;
73
72
74
73
var subselects = [ ] ,
75
74
tokens = [ ] ,
75
+ sawWS = false ,
76
76
data , firstChar , name ;
77
77
78
78
function getName ( ) {
@@ -93,17 +93,40 @@ function parse(selector, options){
93
93
94
94
while ( selector !== "" ) {
95
95
if ( re_name . test ( selector ) ) {
96
+ if ( sawWS ) {
97
+ tokens . push ( { type : "descendant" } ) ;
98
+ sawWS = false ;
99
+ }
100
+
96
101
tokens . push ( { type : "tag" , name : getLCName ( ) } ) ;
97
102
} else if ( re_ws . test ( selector ) ) {
98
- tokens . push ( { type : "descendant" } ) ;
103
+ sawWS = true ;
99
104
selector = selector . trimLeft ( ) ;
100
105
} else {
101
106
firstChar = selector . charAt ( 0 ) ;
102
107
selector = selector . substr ( 1 ) ;
103
108
104
109
if ( firstChar in simpleSelectors ) {
105
110
tokens . push ( { type : simpleSelectors [ firstChar ] } ) ;
106
- } else if ( firstChar in attribSelectors ) {
111
+ selector = selector . trimLeft ( ) ;
112
+ sawWS = false ;
113
+ continue ;
114
+ } else if ( firstChar === "," ) {
115
+ if ( tokens . length === 0 ) {
116
+ throw new SyntaxError ( "empty sub-selector" ) ;
117
+ }
118
+ subselects . push ( tokens ) ;
119
+ tokens = [ ] ;
120
+
121
+ selector = selector . trimLeft ( ) ;
122
+ sawWS = false ;
123
+ continue ;
124
+ } else if ( sawWS ) {
125
+ tokens . push ( { type : "descendant" } ) ;
126
+ sawWS = false ;
127
+ }
128
+
129
+ if ( firstChar in attribSelectors ) {
107
130
tokens . push ( {
108
131
type : "attribute" ,
109
132
name : attribSelectors [ firstChar ] [ 0 ] ,
@@ -143,12 +166,6 @@ function parse(selector, options){
143
166
}
144
167
145
168
tokens . push ( { type : "pseudo" , name : name , data : data } ) ;
146
- } else if ( firstChar === "," ) {
147
- if ( tokens . length === 0 ) {
148
- throw new SyntaxError ( "empty sub-selector" ) ;
149
- }
150
- subselects . push ( tokens ) ;
151
- tokens = [ ] ;
152
169
} else {
153
170
//otherwise, the parser needs to throw or it would enter an infinite loop
154
171
throw new SyntaxError ( "Unmatched selector: " + firstChar + selector ) ;
0 commit comments