2
2
3
3
module . exports = parse ;
4
4
5
- var re_ws = / ^ \s / ,
6
- re_name = / ^ (?: \\ .| [ \w \- \u00c0 - \uFFFF ] ) + / ,
5
+ var re_name = / ^ (?: \\ .| [ \w \- \u00c0 - \uFFFF ] ) + / ,
7
6
re_escape = / \\ ( [ \d a - f ] { 1 , 6 } \s ? | ( \s ) | .) / ig,
8
7
//modified version of https://github.com/jquery/sizzle/blob/master/src/sizzle.js#L87
9
8
re_attr = / ^ \s * ( (?: \\ .| [ \w \u00c0 - \uFFFF \- ] ) + ) \s * (?: ( \S ? ) = \s * (?: ( [ ' " ] ) ( .* ?) \3| ( # ? (?: \\ .| [ \w \u00c0 - \uFFFF \- ] ) * ) | ) | ) \s * ( i ) ? \] / ;
@@ -72,6 +71,10 @@ function unescapeCSS(str){
72
71
return str . replace ( re_escape , funescape ) ;
73
72
}
74
73
74
+ function isWhitespace ( c ) {
75
+ return c === " " || c === "\n" || c === "\t" || c === "\f" || c === "\r" ;
76
+ }
77
+
75
78
function parse ( selector , options ) {
76
79
var subselects = [ ] ;
77
80
@@ -89,58 +92,51 @@ function parseSelector(subselects, selector, options){
89
92
sawWS = false ,
90
93
data , firstChar , name , quot ;
91
94
92
- selector = selector . trimLeft ( ) ;
93
-
94
95
function getName ( ) {
95
96
var sub = selector . match ( re_name ) [ 0 ] ;
96
97
selector = selector . substr ( sub . length ) ;
97
98
return unescapeCSS ( sub ) ;
98
99
}
99
100
100
- while ( selector !== "" ) {
101
- if ( re_name . test ( selector ) ) {
102
- if ( sawWS ) {
103
- tokens . push ( { type : "descendant" } ) ;
104
- sawWS = false ;
105
- }
101
+ function stripWhitespace ( start ) {
102
+ while ( isWhitespace ( selector . charAt ( start ) ) ) start ++ ;
103
+ selector = selector . substr ( start ) ;
104
+ }
106
105
107
- name = getName ( ) ;
106
+ stripWhitespace ( 0 ) ;
108
107
109
- if ( ! options || ( "lowerCaseTags" in options ? options . lowerCaseTags : ! options . xmlMode ) ) {
110
- name = name . toLowerCase ( ) ;
111
- }
108
+ while ( selector !== "" ) {
109
+ firstChar = selector . charAt ( 0 ) ;
112
110
113
- tokens . push ( { type : "tag" , name : name } ) ;
114
- } else if ( re_ws . test ( selector ) ) {
111
+ if ( isWhitespace ( firstChar ) ) {
115
112
sawWS = true ;
116
- selector = selector . trimLeft ( ) ;
117
- } else {
118
- firstChar = selector . charAt ( 0 ) ;
119
- selector = selector . substr ( 1 ) ;
120
-
121
- if ( firstChar in simpleSelectors ) {
122
- tokens . push ( { type : simpleSelectors [ firstChar ] } ) ;
123
- selector = selector . trimLeft ( ) ;
124
- sawWS = false ;
125
- continue ;
126
- } else if ( firstChar === "," ) {
127
- if ( tokens . length === 0 ) {
128
- throw new SyntaxError ( "empty sub-selector" ) ;
129
- }
130
- subselects . push ( tokens ) ;
131
- tokens = [ ] ;
132
-
133
- selector = selector . trimLeft ( ) ;
134
- sawWS = false ;
135
- continue ;
136
- } else if ( sawWS ) {
137
- tokens . push ( { type : "descendant" } ) ;
113
+ stripWhitespace ( 1 ) ;
114
+ } else if ( firstChar in simpleSelectors ) {
115
+ tokens . push ( { type : simpleSelectors [ firstChar ] } ) ;
116
+ sawWS = false ;
117
+
118
+ stripWhitespace ( 1 ) ;
119
+ } else if ( firstChar === "," ) {
120
+ if ( tokens . length === 0 ) {
121
+ throw new SyntaxError ( "empty sub-selector" ) ;
122
+ }
123
+ subselects . push ( tokens ) ;
124
+ tokens = [ ] ;
125
+ sawWS = false ;
126
+ stripWhitespace ( 1 ) ;
127
+ } else {
128
+ if ( sawWS ) {
129
+ if ( tokens . length > 0 ) {
130
+ tokens . push ( { type : "descendant" } ) ;
131
+ }
138
132
sawWS = false ;
139
133
}
140
134
141
- if ( firstChar === "*" ) {
135
+ if ( firstChar === "*" ) {
136
+ selector = selector . substr ( 1 ) ;
142
137
tokens . push ( { type : "universal" } ) ;
143
138
} else if ( firstChar in attribSelectors ) {
139
+ selector = selector . substr ( 1 ) ;
144
140
tokens . push ( {
145
141
type : "attribute" ,
146
142
name : attribSelectors [ firstChar ] [ 0 ] ,
@@ -149,6 +145,7 @@ function parseSelector(subselects, selector, options){
149
145
ignoreCase : false
150
146
} ) ;
151
147
} else if ( firstChar === "[" ) {
148
+ selector = selector . substr ( 1 ) ;
152
149
data = selector . match ( re_attr ) ;
153
150
if ( ! data ) {
154
151
throw new SyntaxError ( "Malformed attribute selector: " + selector ) ;
@@ -175,7 +172,10 @@ function parseSelector(subselects, selector, options){
175
172
} ) ;
176
173
177
174
} else if ( firstChar === ":" ) {
178
- //if(selector.charAt(0) === ":"){} //TODO pseudo-element
175
+ //if(selector.charAt(1) === ":"){} //TODO pseudo-element
176
+
177
+ selector = selector . substr ( 1 ) ;
178
+
179
179
name = getName ( ) . toLowerCase ( ) ;
180
180
data = null ;
181
181
@@ -232,12 +232,20 @@ function parseSelector(subselects, selector, options){
232
232
}
233
233
234
234
tokens . push ( { type : "pseudo" , name : name , data : data } ) ;
235
- } else {
235
+ } else if ( re_name . test ( selector ) ) {
236
+ name = getName ( ) ;
237
+
238
+ if ( ! options || ( "lowerCaseTags" in options ? options . lowerCaseTags : ! options . xmlMode ) ) {
239
+ name = name . toLowerCase ( ) ;
240
+ }
241
+
242
+ tokens . push ( { type : "tag" , name : name } ) ;
243
+ } else {
236
244
if ( tokens . length && tokens [ tokens . length - 1 ] . type === "descendant" ) {
237
245
tokens . pop ( ) ;
238
246
}
239
247
addToken ( subselects , tokens ) ;
240
- return firstChar + selector ;
248
+ return selector ;
241
249
}
242
250
}
243
251
}
0 commit comments