Skip to content

Commit d069612

Browse files
committed
perf: replace css-tree with @pw/css-parser for custom property analysis
1 parent 764391e commit d069612

File tree

2 files changed

+49
-51
lines changed

2 files changed

+49
-51
lines changed

src/lib/components/custom-property-inspector/analyze-custom-properties.test.ts

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ test('undeclared property', () => {
2323
expect(actual.unused.size).toBe(0)
2424
expect(actual.all.size).toBe(1)
2525
expect(actual.all.get('--undeclared')).toEqual([
26-
{ column: 3, length: 24, line: 3, offset: 8 }
26+
{ column: 3, length: 25, line: 3, offset: 8 }
2727
])
2828
})
2929

@@ -37,7 +37,7 @@ test('undeclared property with fallback', () => {
3737
expect(actual.unused.size).toBe(0)
3838
expect(actual.all.size).toBe(1)
3939
expect(actual.all.get('--undeclared')).toEqual([
40-
{ column: 3, length: 29, line: 3, offset: 8 }
40+
{ column: 3, length: 30, line: 3, offset: 8 }
4141
])
4242
})
4343

@@ -51,7 +51,7 @@ test('undeclared property with undefined custom property as fallback', () => {
5151
expect(actual.unused.size).toBe(0)
5252
expect(actual.all.size).toBe(2)
5353
expect(actual.all.get('--undeclared')).toEqual([
54-
{ column: 3, length: 45, line: 3, offset: 8 }
54+
{ column: 3, length: 46, line: 3, offset: 8 }
5555
])
5656
})
5757

@@ -66,7 +66,7 @@ test('undeclared property with defined custom property as fallback', () => {
6666
expect(actual.unused.size).toBe(0)
6767
expect(actual.all.size).toBe(2)
6868
expect(actual.all.get('--undeclared')).toEqual([
69-
{ column: 3, length: 41, line: 4, offset: 25 }
69+
{ column: 3, length: 42, line: 4, offset: 25 }
7070
])
7171
})
7272

@@ -80,7 +80,7 @@ test('undeclared property with empty fallback', () => {
8080
expect(actual.unused.size).toBe(0)
8181
expect(actual.all.size).toBe(1)
8282
expect(actual.all.get('--undeclared')).toEqual([
83-
{ column: 3, length: 26, line: 3, offset: 8 }
83+
{ column: 3, length: 27, line: 3, offset: 8 }
8484
])
8585
})
8686

@@ -114,6 +114,6 @@ test('used @property', () => {
114114
expect(actual.all.size).toBe(1)
115115
expect(actual.all.get('--used')).toEqual([
116116
{ column: 2, length: 64, line: 2, offset: 2 },
117-
{ column: 3, length: 14, line: 7, offset: 74 }
117+
{ column: 3, length: 15, line: 7, offset: 74 }
118118
])
119119
})

src/lib/components/custom-property-inspector/analyze-custom-properties.ts

Lines changed: 43 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -1,68 +1,66 @@
1-
import walk from 'css-tree/walker'
2-
import parse from 'css-tree/parser'
3-
import type { CssNode, CssLocation as CssTreeLocation } from 'css-tree'
1+
import { parse, walk, DECLARATION, FUNCTION, AT_RULE, IDENTIFIER } from '@projectwallace/css-parser'
2+
import type { CSSNode } from '@projectwallace/css-parser'
43
import type { CssLocation } from '$lib/css-location'
54

6-
function to_loc(loc: CssTreeLocation): CssLocation {
5+
function to_loc(node: CSSNode): CssLocation {
76
return {
8-
line: loc.start.line,
9-
column: loc.start.column,
10-
offset: loc.start.offset,
11-
length: loc.end.offset - loc.start.offset
7+
line: node.line,
8+
column: node.column,
9+
offset: node.start,
10+
length: node.length
1211
}
1312
}
1413

1514
export function analyze(css: string) {
16-
let ast = parse(css, {
17-
positions: true,
18-
parseCustomProperty: true,
19-
parseRulePrelude: false,
20-
})
15+
let ast = parse(css)
2116
let declared_properties = new Set<string>()
2217
let used_properties = new Set<string>()
2318
let all_properties = new Map<string, CssLocation[]>()
2419
let declared_with_fallback = new Set<string>()
2520

26-
walk(ast, function (node: CssNode) {
27-
if (node.type === 'Declaration') {
28-
if (node.property.startsWith('--')) {
29-
let loc = to_loc(node.loc!)
30-
let name = node.property
31-
declared_properties.add(name)
32-
all_properties.set(name, (all_properties.get(name) ?? []).concat(loc))
33-
}
34-
} else if (node.type === 'Function' && node.name === 'var') {
35-
let first_child = node.children.first
36-
if (
37-
first_child !== null &&
38-
first_child.type === 'Identifier' &&
39-
first_child.name.startsWith('--')
40-
) {
41-
let node_loc = first_child.loc!
42-
if (this.declaration !== null) {
43-
node_loc = this.declaration.loc!
44-
}
45-
let loc = to_loc(node_loc)
21+
// Helper to recursively walk values and find all var() functions
22+
function walk_values(value_node: CSSNode, declaration_node: CSSNode) {
23+
if (value_node.type === FUNCTION && value_node.name === 'var') {
24+
let first_child = value_node.first_child
25+
if (first_child !== null && first_child.type === IDENTIFIER && first_child.name.startsWith('--')) {
26+
let loc = to_loc(declaration_node)
4627
let name = first_child.name
4728
used_properties.add(name)
4829
all_properties.set(name, (all_properties.get(name) ?? []).concat(loc))
4930

5031
// check if it has a fallback value that is a custom property
51-
let second_child = node.children.toArray()[1]
52-
if (second_child !== undefined && !(second_child.type === 'Function' && second_child.name === 'var')) {
32+
let children = value_node.children
33+
let second_child = children[1]
34+
if (second_child !== undefined && !(second_child.type === FUNCTION && second_child.name === 'var')) {
5335
declared_with_fallback.add(name)
5436
}
5537
}
56-
} else if (
57-
node.type === 'Atrule' &&
58-
node.name === 'property' &&
59-
node.prelude !== null &&
60-
node.prelude.type === 'AtrulePrelude'
61-
) {
62-
let first_child = node.prelude.children.first
63-
if (first_child !== null && first_child.type === 'Identifier') {
64-
let name = first_child.name
65-
let loc = to_loc(node.loc!)
38+
}
39+
40+
// Recursively walk children to find nested var() calls
41+
for (let child of value_node.children) {
42+
walk_values(child, declaration_node)
43+
}
44+
}
45+
46+
walk(ast, (node: CSSNode) => {
47+
if (node.type === DECLARATION) {
48+
if (node.property.startsWith('--')) {
49+
let loc = to_loc(node)
50+
let name = node.property
51+
declared_properties.add(name)
52+
all_properties.set(name, (all_properties.get(name) ?? []).concat(loc))
53+
}
54+
55+
// Check for var() usage in declaration values (recursively)
56+
for (let value of node.values) {
57+
walk_values(value, node)
58+
}
59+
} else if (node.type === AT_RULE && node.name === 'property') {
60+
let first_child = node.first_child
61+
if (first_child !== null && first_child.type === IDENTIFIER) {
62+
let name = first_child.text // Use .text instead of .name
63+
let loc = to_loc(node)
6664
declared_properties.add(name)
6765
all_properties.set(name, (all_properties.get(name) ?? []).concat(loc))
6866
}

0 commit comments

Comments
 (0)