@@ -4,6 +4,24 @@ import Selector from './Selector';
4
4
import PropertyTest from './PropertyTest' ;
5
5
import CSS from './escape' ;
6
6
7
+ /**
8
+ * Using the location and additional offset of unicode escape tokens,
9
+ * fix the location values for parsed selector tokens.
10
+ *
11
+ * @param {Array } tokens
12
+ * @param {Array } unicodeLocations location and offset of each unicode escape
13
+ */
14
+ function fixLocation ( tokens , unicodeLocations ) {
15
+ for ( var i = 0 ; i < tokens . length ; i ++ ) {
16
+ if ( tokens [ i ] . location ) {
17
+ tokens [ i ] . location += unicodeLocations . filter ( ( l ) => l . index < tokens [ i ] . location ) . reduce ( ( offset , l ) => offset + l . offset , 0 ) ;
18
+ }
19
+ if ( Array . isArray ( tokens [ i ] . tokens ) ) {
20
+ fixLocation ( tokens [ i ] . tokens , unicodeLocations ) ;
21
+ }
22
+ }
23
+ }
24
+
7
25
export default {
8
26
9
27
// classes
@@ -17,8 +35,26 @@ export default {
17
35
* @return {array } Selector object(s)
18
36
*/
19
37
parse ( selector ) {
38
+ // tokenize the input string
39
+ // (the only special tokens are unicode escapes, which need to be matched greedily to avoid ambiguous results)
40
+ var tokens = [ ]
41
+ , unicodeReg = / \\ [ 0 - 9 a - z A - Z ] { 1 , 6 } (?: \r \n | [ \n \r \t \f ] ) ? / g
42
+ , lastIndex = 0
43
+ , result
44
+ , unicodeLocations = [ ] // keep track of where unicode tokens are to fix the "location" values of selector tokens
45
+ ;
46
+
47
+ // find all the unicode escapes, split everything else into individual chars
48
+ while ( ( result = unicodeReg . exec ( selector ) ) !== null ) {
49
+ Array . prototype . push . apply ( tokens , selector . substr ( lastIndex , result . index ) . split ( '' ) ) ;
50
+ unicodeLocations . push ( { index : tokens . length , offset : result [ 0 ] . length - 1 } ) ;
51
+ tokens . push ( result [ 0 ] ) ;
52
+ lastIndex = unicodeReg . lastIndex ;
53
+ }
54
+ Array . prototype . push . apply ( tokens , selector . substr ( lastIndex ) . split ( '' ) ) ;
55
+
20
56
var parser = new Parser ( grammar . ParserRules , grammar . ParserStart )
21
- , results = parser . feed ( selector ) . results
57
+ , results = parser . feed ( tokens ) . results
22
58
;
23
59
24
60
// usually a parse error is thrown by nearley, unless there are no results due to
@@ -39,7 +75,12 @@ export default {
39
75
}
40
76
}
41
77
42
- return results [ 0 ] . selectors . map ( ( selector ) => new Selector ( selector . tokens ) ) ;
78
+ return results [ 0 ] . selectors . map ( ( selector ) => {
79
+ if ( unicodeLocations . length ) {
80
+ fixLocation ( selector . tokens , unicodeLocations ) ;
81
+ }
82
+ return new Selector ( selector . tokens ) ;
83
+ } ) ;
43
84
} ,
44
85
45
86
/**
0 commit comments