@@ -51,27 +51,40 @@ selectors_group -> _ selector (_ "," _ selector):* _
51
51
} %}
52
52
53
53
selector -> simple_selector_sequence ( combinator simple_selector_sequence ):*
54
- {% (d ) => { return {type: ' selector' , nodes: collectObjects (d)} } %}
54
+ {% (d ) => {
55
+ var nodes = collectObjects (d)
56
+ , specificity = {a: 0 , b: 0 , c: 0 , d: 0 }
57
+ ;
58
+
59
+ // calculate the specificity @see: https://www.w3.org/TR/2009/CR-CSS2-20090908/cascade.html#specificity
60
+ for (var i = 0 ; i < nodes .length ; i++ ) {
61
+ if (nodes[i].specificityType ) {
62
+ specificity[nodes[i].specificityType ]++ ;
63
+ }
64
+ }
65
+
66
+ return {type: ' selector' , nodes, specificity};
67
+ } %}
55
68
56
69
combinator -> ( _ [+>~] _ | __ )
57
- {% (d , location ) => { return {type: combinatorTypes[d[0 ][1 ] || ' ' ], location, raw: collapseRaw (d)} } %}
70
+ {% (d , location ) => { return {type: combinatorTypes[d[0 ][1 ] || ' ' ], location, raw: collapseRaw (d), specificityType : null } } %}
58
71
59
72
simple_selector_sequence -> ( type_selector | universal ) simple_selector :* | simple_selector :+
60
73
61
74
simple_selector -> hash | class | attrib | pseudo | negation
62
75
63
76
# selectors
64
77
universal -> namespace_prefix :? "*"
65
- {% (d , location ) => { return {type: ' universalSelector' , namespace: d[0 ] ? d[0 ].name : d[0 ], location, raw: collapseRaw (d)} } %}
78
+ {% (d , location ) => { return {type: ' universalSelector' , namespace: d[0 ] ? d[0 ].name : d[0 ], location, raw: collapseRaw (d), specificityType : null } } %}
66
79
type_selector -> namespace_prefix :? ident
67
- {% (d , location ) => { return {type: ' typeSelector' , namespace: d[0 ] ? d[0 ].name : d[0 ], name: collapse (d[1 ]), location, raw: collapseRaw (d)} } %}
80
+ {% (d , location ) => { return {type: ' typeSelector' , namespace: d[0 ] ? d[0 ].name : d[0 ], name: collapse (d[1 ]), location, raw: collapseRaw (d), specificityType : ' d ' } } %}
68
81
hash -> "#" name
69
- {% (d , location ) => { return {type: ' idSelector' , name: collapse (d[1 ]), location, raw: collapseRaw (d)} } %}
82
+ {% (d , location ) => { return {type: ' idSelector' , name: collapse (d[1 ]), location, raw: collapseRaw (d), specificityType : ' b ' } } %}
70
83
class -> "." ident
71
- {% (d , location ) => { return {type: ' classSelector' , name: collapse (d[1 ]), location, raw: collapseRaw (d)} } %}
84
+ {% (d , location ) => { return {type: ' classSelector' , name: collapse (d[1 ]), location, raw: collapseRaw (d), specificityType : ' c ' } } %}
72
85
attrib -> "[" _ namespace_prefix :? ident _ ( [~|^$*] :? "=" _ ( ident | string ) ):? "]"
73
86
{% (d , location ) => {
74
- var obj = {namespace: d[2 ] ? d[2 ].name : d[2 ], name: collapse (d[3 ]), location, raw: collapseRaw (d)};
87
+ var obj = {namespace: d[2 ] ? d[2 ].name : d[2 ], name: collapse (d[3 ]), location, raw: collapseRaw (d), specificityType : ' c ' };
75
88
if (d[5 ] && d[5 ].length ) {
76
89
obj .type = ' attributeValueSelector' ;
77
90
obj .operator = (d[5 ][0 ] || ' ' ) + ' =' ;
@@ -95,15 +108,17 @@ pseudo -> ":" ":":? ( ident | functional_pseudo )
95
108
return reject;
96
109
}
97
110
obj .type = ' pseudoElementSelector' ;
111
+ obj .specificityType = ' d' ;
98
112
} else {
99
113
obj .type = ' pseudoClassSelector' ;
114
+ obj .specificityType = ' c' ;
100
115
obj .expression = d[2 ][0 ].expression || null ;
101
116
obj .expressionRaw = d[2 ][0 ].expressionRaw || null ;
102
117
}
103
118
return obj;
104
119
} %}
105
120
negation -> ":" [nN] [oO] [tT] "(" _ negation_arg _ ")"
106
- {% (d , location ) => { return {type: ' negationSelector' , selectors: d[6 ], location, raw: collapseRaw (d)} } %}
121
+ {% (d , location ) => { return {type: ' negationSelector' , selectors: d[6 ], location, raw: collapseRaw (d), specificityType : null } } %}
107
122
108
123
# selector helpers
109
124
namespace_prefix -> ( ident | "*" ):? "|"
0 commit comments