Skip to content

Commit d61ed0d

Browse files
authored
Update csstree to v2.1.0 (#219)
1 parent 1b7ced6 commit d61ed0d

File tree

4 files changed

+73
-94
lines changed

4 files changed

+73
-94
lines changed

package-lock.json

Lines changed: 15 additions & 9 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@
4444
"metrics"
4545
],
4646
"dependencies": {
47-
"css-tree": "^2.0.1"
47+
"css-tree": "^2.1.0"
4848
},
4949
"devDependencies": {
5050
"benchmark": "^2.1.4",

src/index.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import parse from 'css-tree/parser'
22
import walk from 'css-tree/walker'
3-
import { property as getProperty } from '../node_modules/css-tree/lib/utils/names.js'
3+
import { property as getProperty } from 'css-tree/utils'
44
import { compareSpecificity } from './selectors/specificity.js'
55
import { analyzeRules } from './rules/rules.js'
66
import { colorFunctions, colorNames } from './values/colors.js'

src/selectors/specificity.js

Lines changed: 56 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
import parse from 'css-tree/parser'
21
import walk from 'css-tree/walker'
32

43
/**
@@ -69,9 +68,11 @@ const analyzeSpecificity = (ast) => {
6968
B++
7069
complexity++
7170

71+
// Add 1 for [attr=value] (or any variation using *= $= ^= |= )
7272
if (Boolean(selector.value)) {
7373
complexity++
7474
}
75+
7576
isA11y = selector.name.name === 'role' || selector.name.name.startsWith('aria-')
7677
break
7778
}
@@ -84,94 +85,66 @@ const analyzeSpecificity = (ast) => {
8485
break
8586
}
8687
case 'PseudoClassSelector': {
87-
if (['before', 'after', 'first-letter', 'first-line'].includes(selector.name)) {
88-
C++
89-
complexity++
90-
return this.skip
91-
}
92-
// The specificity of an :is(), :not(), or :has() pseudo-class is
93-
// replaced by the specificity of the most specific complex
94-
// selector in its selector list argument.
95-
96-
// CSSTree doesn't parse the arguments of :is, :has and :matches,
97-
// so we need to create an AST out of them ourselves
98-
if (['is', 'has', 'matches', '-webkit-any', '-moz-any'].includes(selector.name)) {
99-
const childAst = parse(selector.children.first.value, { context: 'selectorList' })
100-
const selectorList = selectorListSpecificities(childAst)
101-
const [topA, topB, topC] = selectorList[0].specificity
102-
A += topA
103-
B += topB
104-
C += topC
105-
106-
for (let i = 0; i < selectorList.length; i++) {
107-
complexity += selectorList[i].complexity
88+
switch (selector.name) {
89+
case 'before':
90+
case 'after':
91+
case 'first-letter':
92+
case 'first-line': {
93+
C++
94+
complexity++
95+
return this.skip
10896
}
109-
complexity++
110-
return
111-
}
11297

113-
// CSSTree *does* parse the arguments of the :not() pseudo-class,
114-
// so we have direct access to the AST, instead of having to parse
115-
// the arguments ourselves.
116-
if (selector.name === 'not') {
117-
const selectorList = selectorListSpecificities(selector)
118-
const [topA, topB, topC] = selectorList[0].specificity
119-
A += topA
120-
B += topB
121-
C += topC
122-
123-
for (let i = 0; i < selectorList.length; i++) {
124-
complexity += selectorList[i].complexity
98+
// The specificity of an :is(), :not(), or :has() pseudo-class is
99+
// replaced by the specificity of the most specific complex
100+
// selector in its selector list argument.
101+
case 'where':
102+
case 'is':
103+
case 'has':
104+
case 'matches':
105+
case '-webkit-any':
106+
case '-moz-any':
107+
case 'not':
108+
case 'nth-child':
109+
case 'nth-last-child': {
110+
// The specificity of an :nth-child() or :nth-last-child() selector
111+
// is the specificity of the pseudo class itself (counting as one
112+
// pseudo-class selector) plus the specificity of the most
113+
// specific complex selector in its selector list argument (if any).
114+
if (['nth-child', 'nth-last-child'].includes(selector.name)) {
115+
// +1 for the pseudo class itself
116+
B++
117+
}
118+
119+
const selectorList = selectorListSpecificities(selector)
120+
121+
// Bail out for empty/non-existent :nth-child() params
122+
if (selectorList.length === 0) return
123+
124+
// The specificity of a :where() pseudo-class is replaced by zero,
125+
// but it does count towards complexity.
126+
if (selector.name !== 'where') {
127+
const [topA, topB, topC] = selectorList[0].specificity
128+
A += topA
129+
B += topB
130+
C += topC
131+
}
132+
133+
for (let i = 0; i < selectorList.length; i++) {
134+
complexity += selectorList[i].complexity
135+
}
136+
137+
complexity++
138+
return this.skip
125139
}
126-
complexity++
127-
return this.skip
128-
}
129-
130-
// The specificity of an :nth-child() or :nth-last-child() selector
131-
// is the specificity of the pseudo class itself (counting as one
132-
// pseudo-class selector) plus the specificity of the most
133-
// specific complex selector in its selector list argument (if any).
134-
if (['nth-child', 'nth-last-child'].includes(selector.name)) {
135-
// +1 for the pseudo class itself
136-
B++
137-
138-
const childSelectors = selectorListSpecificities(selector)
139-
140-
if (childSelectors.length === 0) {
141-
return
142-
}
143-
144-
const [topA, topB, topC] = childSelectors[0].specificity
145-
A += topA
146-
B += topB
147-
C += topC
148140

149-
for (let i = 0; i < childSelectors.length; i++) {
150-
complexity += childSelectors[i].complexity;
141+
default: {
142+
// Regular pseudo classes have specificity [0,1,0]
143+
complexity++
144+
B++
145+
return this.skip
151146
}
152-
153-
complexity++
154-
return
155-
}
156-
157-
// The specificity of a :where() pseudo-class is replaced by zero,
158-
// but it does count towards complexity.
159-
if (selector.name === 'where') {
160-
const childAst = parse(selector.children.first.value, { context: 'selectorList' })
161-
const childSelectors = selectorListSpecificities(childAst)
162-
163-
for (let i = 0; i < childSelectors.length; i++) {
164-
complexity += childSelectors[i].complexity;
165-
}
166-
167-
complexity++
168-
return
169147
}
170-
171-
// Regular pseudo classes have specificity [0,1,0]
172-
complexity++
173-
B++
174-
break
175148
}
176149
case 'Combinator': {
177150
complexity++

0 commit comments

Comments
 (0)