Skip to content

Commit f00f4fc

Browse files
authored
Upgrade CSSTree to v3 (#460)
alternative to #350 closes #426
1 parent a638e56 commit f00f4fc

File tree

5 files changed

+87
-75
lines changed

5 files changed

+87
-75
lines changed

package-lock.json

Lines changed: 17 additions & 50 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 & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -46,16 +46,13 @@
4646
],
4747
"dependencies": {
4848
"@bramus/specificity": "^2.4.1",
49-
"css-tree": "^2.3.1"
49+
"css-tree": "^3.1.0"
5050
},
5151
"devDependencies": {
5252
"@codecov/vite-plugin": "^1.9.0",
5353
"c8": "^10.1.3",
5454
"uvu": "^0.5.6",
5555
"vite": "^6.3.4",
5656
"vite-plugin-dts": "^4.5.0"
57-
},
58-
"mangle": {
59-
"regex": "^_[^_]"
6057
}
6158
}

src/atrules/atrules.js

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ import walk from 'css-tree/walker'
33
import {
44
Identifier,
55
MediaQuery,
6-
MediaFeature,
76
Declaration,
87
} from '../css-tree-node-types.js'
98

@@ -54,21 +53,16 @@ export function isMediaBrowserhack(prelude) {
5453
let returnValue = false
5554

5655
walk(prelude, function (node) {
57-
let children = node.children
5856
let name = node.name
5957
let value = node.value
6058

61-
if (node.type === MediaQuery
62-
&& children.size === 1
63-
&& children.first.type === Identifier
64-
) {
65-
let n = children.first.name
59+
if (node.type === MediaQuery && node.mediaType !== null) {
6660
// Note: CSSTree adds a trailing space to \\9
67-
if (startsWith('\\0', n) || endsWith('\\9 ', n)) {
61+
if (startsWith('\\0', node.mediaType) || endsWith('\\9 ', node.mediaType)) {
6862
returnValue = true
6963
return this.break
7064
}
71-
} else if (node.type === MediaFeature) {
65+
} else if (node.type === 'Feature' && node.kind === 'media') {
7266
if (value && value.unit && value.unit === '\\0') {
7367
returnValue = true
7468
return this.break

src/atrules/atrules.test.js

Lines changed: 52 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,11 @@ AtRules('finds @layer', () => {
6767
// Fixture is pretty much a straight copy from all code examples from
6868
// https://css-tricks.com/css-cascade-layers/
6969
const fixture = `
70+
@import url('test.css') layer;
71+
@import url('test.css') layer();
72+
@import url('test.css') layer(test);
73+
@import url('test.css') layer(test.abc);
74+
7075
/* establish a layer order up-front, from lowest to highest priority */
7176
@layer reset, defaults, patterns, components, utilities, overrides;
7277
@@ -143,9 +148,11 @@ AtRules('finds @layer', () => {
143148
`
144149
const actual = analyze(fixture).atrules.layer
145150
const expected = {
146-
total: 48,
147-
totalUnique: 26,
151+
total: 50,
152+
totalUnique: 28,
148153
unique: {
154+
"test": 1,
155+
"test.abc": 1,
149156
"defaults": 5,
150157
"layer-1": 1,
151158
"layer-2": 1,
@@ -173,7 +180,7 @@ AtRules('finds @layer', () => {
173180
"overrides": 1,
174181
"<anonymous>": 2,
175182
},
176-
uniquenessRatio: 26 / 48
183+
uniquenessRatio: 28 / 50
177184
}
178185

179186
assert.equal(actual, expected)
@@ -389,26 +396,63 @@ AtRules('finds @imports', () => {
389396
390397
@import url('remedy.css') layer(reset.remedy);
391398
399+
@import 'test.css' supports((display: grid));
400+
@import 'test.css' supports(not (display: grid));
401+
@import 'test.css' supports(selector(a:has(b)));
402+
/*@import "test.css" supports((selector(h2 > p) and (font-tech(color-COLRv1))));*/
403+
392404
/* @import without prelude */
393405
@import;
394406
`
395-
const actual = analyze(fixture).atrules.import
407+
const actual = analyze(fixture).atrules
396408
const expected = {
397-
total: 7,
398-
totalUnique: 7,
409+
total: 10,
410+
totalUnique: 10,
399411
unique: {
400412
'"https://example.com/without-url"': 1,
401413
'url("https://example.com/with-url")': 1,
402414
'url("https://example.com/with-media-query") screen and (min-width: 33em)': 1,
403415
'url("https://example.com/with-multiple-media-queries") screen, projection': 1,
404416
'url(\'example.css\') layer(named-layer)': 1,
405417
'url(\'../example.css\') layer': 1,
406-
'url(\'remedy.css\') layer(reset.remedy)': 1,
418+
"url('remedy.css') layer(reset.remedy)": 1,
419+
"'test.css' supports((display: grid))": 1,
420+
"'test.css' supports(not (display: grid))": 1,
421+
"'test.css' supports(selector(a:has(b)))": 1,
407422
},
408423
uniquenessRatio: 1,
409424
}
410425

411-
assert.equal(actual, expected)
426+
assert.equal(actual.import, expected)
427+
428+
const expected_supports = {
429+
total: 3,
430+
totalUnique: 3,
431+
unique: {
432+
"(display: grid)": 1,
433+
"not (display: grid)": 1,
434+
"selector(a:has(b))": 1,
435+
},
436+
uniquenessRatio: 1,
437+
browserhacks: {
438+
total: 0,
439+
totalUnique: 0,
440+
unique: {},
441+
uniquenessRatio: 0,
442+
},
443+
}
444+
assert.equal(actual.supports, expected_supports)
445+
446+
const expected_layers = {
447+
total: 2,
448+
totalUnique: 2,
449+
unique: {
450+
"named-layer": 1,
451+
'reset.remedy': 1,
452+
},
453+
uniquenessRatio: 1,
454+
}
455+
assert.equal(actual.layer, expected_layers)
412456
})
413457

414458
AtRules('finds @charsets', () => {

src/index.js

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -248,6 +248,14 @@ export function analyze(css, options = {}) {
248248
}
249249
keyframes.p(name, loc)
250250
} else if (atRuleName === 'import') {
251+
walk(node, function (prelude_node) {
252+
if (prelude_node.type === 'Condition' && prelude_node.kind === 'supports') {
253+
let prelude = stringifyNode(prelude_node)
254+
255+
supports.p(prelude, prelude_node.loc)
256+
return this.break
257+
}
258+
})
251259
imports.p(preludeStr, loc)
252260
// TODO: analyze complexity of media queries, layers and supports in @import
253261
// see https://github.com/projectwallace/css-analyzer/issues/326
@@ -256,10 +264,6 @@ export function analyze(css, options = {}) {
256264
} else if (atRuleName === 'container') {
257265
containers.p(preludeStr, loc)
258266
// TODO: calculate complexity of container 'declaration'
259-
} else if (atRuleName === 'layer') {
260-
preludeStr
261-
.split(',')
262-
.forEach(name => layers.p(name.trim(), loc))
263267
} else if (atRuleName === 'property') {
264268
registeredProperties.p(preludeStr, loc)
265269
// TODO: add complexity for descriptors
@@ -273,6 +277,12 @@ export function analyze(css, options = {}) {
273277
atRuleComplexities.push(complexity)
274278
break
275279
}
280+
case 'Layer': {
281+
if (node.name !== null) {
282+
layers.p(node.name, node.loc)
283+
}
284+
break
285+
}
276286
case Rule: {
277287
let prelude = node.prelude
278288
let block = node.block

0 commit comments

Comments
 (0)