Skip to content

Commit 0b10632

Browse files
committed
replaced stupid selector cleaning with a serious solution
1 parent a38effd commit 0b10632

File tree

2 files changed

+43
-10
lines changed

2 files changed

+43
-10
lines changed

index.js

Lines changed: 27 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ module.exports = parse;
44

55
var re_ws = /^\s/,
66
re_name = /^(?:\\.|[\w\-\u00c0-\uFFFF])+/,
7-
re_cleanSelector = /([^\\])\s*([><~+,]|$)\s*/g,
87
re_combinators = /^\s*[^\\]\s*[>~+,]|$\s*/g,
98
re_escape = /\\([\da-f]{1,6}\s?|(\s)|.)/ig,
109
re_comma = /^\s*,\s*/,
@@ -69,10 +68,11 @@ function getClosingPos(selector){
6968
}
7069

7170
function parse(selector, options){
72-
selector = (selector + "").trimLeft().replace(re_cleanSelector, "$1$2");
71+
selector = (selector + "").trimLeft();
7372

7473
var subselects = [],
7574
tokens = [],
75+
sawWS = false,
7676
data, firstChar, name;
7777

7878
function getName(){
@@ -93,17 +93,40 @@ function parse(selector, options){
9393

9494
while(selector !== ""){
9595
if(re_name.test(selector)){
96+
if(sawWS){
97+
tokens.push({type: "descendant"});
98+
sawWS = false;
99+
}
100+
96101
tokens.push({type: "tag", name: getLCName()});
97102
} else if(re_ws.test(selector)){
98-
tokens.push({type: "descendant"});
103+
sawWS = true;
99104
selector = selector.trimLeft();
100105
} else {
101106
firstChar = selector.charAt(0);
102107
selector = selector.substr(1);
103108

104109
if(firstChar in simpleSelectors){
105110
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){
107130
tokens.push({
108131
type: "attribute",
109132
name: attribSelectors[firstChar][0],
@@ -143,12 +166,6 @@ function parse(selector, options){
143166
}
144167

145168
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 = [];
152169
} else {
153170
//otherwise, the parser needs to throw or it would enter an infinite loop
154171
throw new SyntaxError("Unmatched selector: " + firstChar + selector);

tests/test.js

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -295,6 +295,22 @@ var tests = [
295295
],
296296
'escaped attribute'
297297
],
298+
[
299+
'[name="foo ~ < > , bar" i]',
300+
[
301+
[
302+
{
303+
'type': 'attribute',
304+
'name': 'name',
305+
'action': 'equals',
306+
'value': 'foo ~ < > , bar',
307+
'ignoreCase': true
308+
}
309+
]
310+
],
311+
'attribute with previously normalized characters'
312+
],
313+
298314

299315

300316
//pseudo selectors

0 commit comments

Comments
 (0)