Skip to content

Commit de9b755

Browse files
committed
perf: use node.type instead of node.type_name
1 parent ba2276b commit de9b755

8 files changed

Lines changed: 101 additions & 78 deletions

File tree

‎src/atrules/atrules.ts‎

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { type CSSNode, str_equals, walk, BREAK } from '@projectwallace/css-parser'
1+
import { type CSSNode, str_equals, walk, BREAK, SUPPORTS_QUERY, MEDIA_TYPE, MEDIA_FEATURE, DIMENSION, NUMBER, IDENTIFIER } from '@projectwallace/css-parser'
22

33
/**
44
* Check if an @supports atRule is a browserhack (Wallace parser version)
@@ -10,7 +10,7 @@ export function isSupportsBrowserhack(node: CSSNode): boolean {
1010

1111
walk(node, function (n) {
1212
// Check SupportsQuery nodes for browserhack patterns
13-
if (n.type_name === 'SupportsQuery') {
13+
if (n.type === SUPPORTS_QUERY) {
1414
const prelude = n.prelude || n.value || ''
1515
const normalizedPrelude = prelude.toString().toLowerCase().replaceAll(/\s+/g, '')
1616

@@ -35,7 +35,7 @@ export function isMediaBrowserhack(node: CSSNode): boolean {
3535

3636
walk(node, function (n) {
3737
// Check MediaType nodes for \0 prefix or \9 suffix
38-
if (n.type_name === 'MediaType') {
38+
if (n.type === MEDIA_TYPE) {
3939
const text = n.text || ''
4040
if (text.startsWith('\\0') || text.includes('\\9')) {
4141
isBrowserhack = true
@@ -44,7 +44,7 @@ export function isMediaBrowserhack(node: CSSNode): boolean {
4444
}
4545

4646
// Check Feature nodes
47-
if (n.type_name === 'Feature') {
47+
if (n.type === MEDIA_FEATURE) {
4848
const name = n.name || ''
4949

5050
// Check for vendor-specific feature hacks
@@ -60,7 +60,7 @@ export function isMediaBrowserhack(node: CSSNode): boolean {
6060
// Check for min-resolution with .001dpcm
6161
if (str_equals('min-resolution', name) && n.has_children) {
6262
for (const child of n) {
63-
if (child.type_name === 'Dimension' && child.value === 0.001 && str_equals('dpcm', child.unit || '')) {
63+
if (child.type === DIMENSION && child.value === 0.001 && str_equals('dpcm', child.unit || '')) {
6464
isBrowserhack = true
6565
return BREAK
6666
}
@@ -70,7 +70,7 @@ export function isMediaBrowserhack(node: CSSNode): boolean {
7070
// Check for -webkit-min-device-pixel-ratio with 0 or 10000
7171
if (str_equals('-webkit-min-device-pixel-ratio', name) && n.has_children) {
7272
for (const child of n) {
73-
if (child.type_name === 'Number' && (child.value === 0 || child.value === 10000)) {
73+
if (child.type === NUMBER && (child.value === 0 || child.value === 10000)) {
7474
isBrowserhack = true
7575
return BREAK
7676
}
@@ -80,7 +80,7 @@ export function isMediaBrowserhack(node: CSSNode): boolean {
8080
// Check for \0 unit hack (appears as Identifier node)
8181
if (n.has_children) {
8282
for (const child of n) {
83-
if (child.type_name === 'Identifier' && child.text === '\\0') {
83+
if (child.type === IDENTIFIER && child.text === '\\0') {
8484
isBrowserhack = true
8585
return BREAK
8686
}

‎src/index.ts‎

Lines changed: 45 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,25 @@ import {
99
tokenize,
1010
walk,
1111
parse,
12+
AT_RULE,
13+
BLOCK,
14+
DECLARATION,
15+
STYLE_RULE,
16+
SELECTOR_LIST,
17+
SELECTOR,
18+
URL,
19+
MEDIA_FEATURE,
20+
AT_RULE_PRELUDE,
21+
SUPPORTS_QUERY,
22+
LAYER_NAME,
23+
CONTAINER_QUERY,
24+
IDENTIFIER,
25+
OPERATOR,
26+
DIMENSION,
27+
NUMBER,
28+
FUNCTION,
29+
HASH,
30+
STRING,
1231
} from '@projectwallace/css-parser'
1332
import { isSupportsBrowserhack, isMediaBrowserhack } from './atrules/atrules.js'
1433
import { getCombinators, getComplexity, isPrefixed, hasPseudoClass, isAccessibility } from './selectors/utils.js'
@@ -213,7 +232,7 @@ function analyzeInternal<T extends boolean>(css: string, options: Options, useLo
213232

214233
function wallaceWalk(node: CSSNode, depth: number = 0, inKeyframes: boolean = false, inAtrulePrelude: boolean = false) {
215234
// Count nodes and track nesting
216-
if (node.type_name === 'Atrule') {
235+
if (node.type === AT_RULE) {
217236
let atruleLoc = toLoc(node)
218237
atruleNesting.push(depth)
219238
uniqueAtruleNesting.p(depth, atruleLoc)
@@ -225,9 +244,9 @@ function analyzeInternal<T extends boolean>(css: string, options: Options, useLo
225244
if (useLocations) {
226245
fontfaces_with_loc.p(node.start, toLoc(node))
227246
}
228-
let block = node.children.find((child) => child.type_name === 'Block')
247+
let block = node.children.find((child) => child.type === BLOCK)
229248
for (let descriptor of block?.children || []) {
230-
if (descriptor.type_name === 'Declaration' && descriptor.value) {
249+
if (descriptor.type === DECLARATION && descriptor.value) {
231250
descriptors[descriptor.property] = (descriptor.value as CSSNode).text
232251
}
233252
}
@@ -279,17 +298,17 @@ function analyzeInternal<T extends boolean>(css: string, options: Options, useLo
279298

280299
if (node.prelude.has_children) {
281300
for (let child of node.prelude) {
282-
if (child.type_name === 'SupportsQuery' && typeof child.value === 'string') {
301+
if (child.type === SUPPORTS_QUERY && typeof child.value === 'string') {
283302
supports.p(child.value, toLoc(child))
284-
} else if (child.type_name === 'Layer' && typeof child.value === 'string') {
303+
} else if (child.type === LAYER_NAME && typeof child.value === 'string') {
285304
layers.p(child.value, toLoc(child))
286305
}
287306
}
288307
}
289308
} else if (str_equals('container', name)) {
290309
containers.p(node.prelude.text, toLoc(node))
291-
if (node.prelude.first_child?.type_name === 'ContainerQuery') {
292-
if (node.prelude.first_child.first_child?.type_name === 'Identifier') {
310+
if (node.prelude.first_child?.type === CONTAINER_QUERY) {
311+
if (node.prelude.first_child.first_child?.type === IDENTIFIER) {
293312
containerNames.p(node.prelude.first_child.first_child.text, toLoc(node))
294313
}
295314
}
@@ -301,12 +320,12 @@ function analyzeInternal<T extends boolean>(css: string, options: Options, useLo
301320

302321
atRuleComplexities.push(complexity)
303322
}
304-
} else if (node.type_name === 'Rule') {
323+
} else if (node.type === STYLE_RULE) {
305324
// Handle keyframe rules specially
306325
if (inKeyframes && node.prelude) {
307326
// In keyframes, the prelude is a SelectorList that may not have Selector children
308327
// (e.g., "50%" is just a SelectorList with text, no Selector child)
309-
if (node.prelude.type_name === 'SelectorList' && node.prelude.text) {
328+
if (node.prelude.type === SELECTOR_LIST && node.prelude.text) {
310329
keyframeSelectors.p(node.prelude.text, toLoc(node.prelude))
311330
}
312331
// Don't count keyframe rules as regular rules, but continue walking
@@ -329,7 +348,7 @@ function analyzeInternal<T extends boolean>(css: string, options: Options, useLo
329348
// Find the SelectorList child and count Selector nodes inside it
330349
if (node.prelude) {
331350
for (const selector of node.prelude.children) {
332-
if (selector.type_name === 'Selector') {
351+
if (selector.type === SELECTOR) {
333352
numSelectors++
334353
}
335354
}
@@ -338,7 +357,7 @@ function analyzeInternal<T extends boolean>(css: string, options: Options, useLo
338357
// Count declarations in the block
339358
if (node.block) {
340359
for (const declaration of node.block.children) {
341-
if (declaration.type_name === 'Declaration') {
360+
if (declaration.type === DECLARATION) {
342361
numDeclarations++
343362
}
344363
}
@@ -357,7 +376,7 @@ function analyzeInternal<T extends boolean>(css: string, options: Options, useLo
357376
ruleNesting.push(depth)
358377
uniqueRuleNesting.p(depth, loc)
359378
}
360-
} else if (node.type_name === 'Selector') {
379+
} else if (node.type === SELECTOR) {
361380
// Keyframe selectors are now handled at the Rule level, so skip them here
362381
if (inKeyframes) {
363382
return SKIP
@@ -430,7 +449,7 @@ function analyzeInternal<T extends boolean>(css: string, options: Options, useLo
430449
// with :where() or :is() that contain SelectorLists
431450
// as children
432451
return SKIP
433-
} else if (node.type_name === 'Declaration') {
452+
} else if (node.type === DECLARATION) {
434453
totalDeclarations++
435454
uniqueDeclarations.add(node.text)
436455

@@ -597,13 +616,13 @@ function analyzeInternal<T extends boolean>(css: string, options: Options, useLo
597616
return SKIP
598617
} else if (isProperty('animation-duration', property) || isProperty('transition-duration', property)) {
599618
for (let child of value.children) {
600-
if (child.type_name !== 'Operator') {
619+
if (child.type !== OPERATOR) {
601620
durations.p(child.text, valueLoc)
602621
}
603622
}
604623
} else if (isProperty('transition-timing-function', property) || isProperty('animation-timing-function', property)) {
605624
for (let child of value.children) {
606-
if (child.type_name !== 'Operator') {
625+
if (child.type !== OPERATOR) {
607626
timingFunctions.p(child.text, valueLoc)
608627
}
609628
}
@@ -612,7 +631,7 @@ function analyzeInternal<T extends boolean>(css: string, options: Options, useLo
612631
} else if (isProperty('container', property)) {
613632
// The first identifier in the `container` shorthand is the container name
614633
// Example: container: my-layout / inline-size;
615-
if (value.first_child?.type_name === 'Identifier') {
634+
if (value.first_child?.type === IDENTIFIER) {
616635
containerNames.p(value.first_child.text, valueLoc)
617636
}
618637
} else if (border_radius_properties.has(basename(property))) {
@@ -627,14 +646,14 @@ function analyzeInternal<T extends boolean>(css: string, options: Options, useLo
627646
let valueHasIe9Hack = isIe9Hack(value)
628647

629648
walk(value, (valueNode) => {
630-
switch (valueNode.type_name) {
631-
case 'Dimension': {
649+
switch (valueNode.type) {
650+
case DIMENSION: {
632651
let unit = valueNode.unit!
633652
let loc = toLoc(valueNode)
634653
units.push(unit, property, loc)
635654
return SKIP
636655
}
637-
case 'Hash': {
656+
case HASH: {
638657
// Use text property for the hash value
639658
let hashText = valueNode.text
640659
if (!hashText || !hashText.startsWith('#')) {
@@ -659,7 +678,7 @@ function analyzeInternal<T extends boolean>(css: string, options: Options, useLo
659678

660679
return SKIP
661680
}
662-
case 'Identifier': {
681+
case IDENTIFIER: {
663682
let identifierText = valueNode.text
664683
let identifierLoc = toLoc(valueNode)
665684

@@ -704,7 +723,7 @@ function analyzeInternal<T extends boolean>(css: string, options: Options, useLo
704723
}
705724
return SKIP
706725
}
707-
case 'Function': {
726+
case FUNCTION: {
708727
let funcName = valueNode.name as string
709728
let funcLoc = toLoc(valueNode)
710729

@@ -726,7 +745,7 @@ function analyzeInternal<T extends boolean>(css: string, options: Options, useLo
726745
})
727746
}
728747
//#endregion VALUES
729-
} else if (node.type_name === 'Url') {
748+
} else if (node.type === URL) {
730749
let { value } = node
731750
let embed = unquote((value as string) || '')
732751
if (str_starts_with(embed, 'data:')) {
@@ -760,27 +779,27 @@ function analyzeInternal<T extends boolean>(css: string, options: Options, useLo
760779
embedTypes.unique.set(type, item)
761780
}
762781
}
763-
} else if (node.type_name === 'Feature') {
782+
} else if (node.type === MEDIA_FEATURE) {
764783
// console.log({ Feature: node.text, name: node.name, value: node.value })
765784
mediaFeatures.p(node.name, toLoc(node))
766785
return SKIP
767786
}
768787

769788
// Walk at-rule prelude children with inAtrulePrelude flag
770789
let preludeWalked = false
771-
if (node.type_name === 'Atrule' && node.prelude && node.prelude.has_children) {
790+
if (node.type === AT_RULE && node.prelude && node.prelude.has_children) {
772791
for (const child of node.prelude) {
773792
wallaceWalk(child, depth, inKeyframes, true)
774793
}
775794
preludeWalked = true
776795
}
777796

778797
// Walk children with increased depth for Rules and Atrules
779-
const nextDepth = node.type_name === 'Rule' || node.type_name === 'Atrule' ? depth + 1 : depth
798+
const nextDepth = node.type === STYLE_RULE || node.type === AT_RULE ? depth + 1 : depth
780799

781800
for (const child of node.children) {
782801
// Skip the AtrulePrelude node if we already walked it above
783-
if (preludeWalked && child.type_name === 'AtrulePrelude') {
802+
if (preludeWalked && child.type === AT_RULE_PRELUDE) {
784803
continue
785804
}
786805
wallaceWalk(child, nextDepth, inKeyframes, inAtrulePrelude)

‎src/selectors/specificity.ts‎

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
// BELOW IS A COPY OF BRAMUS/SPECIFICTY TAILORED FOR PORJECT WALLACE'S CSS PARSER
33
// https://github.com/bramus/specificity/blob/80938c4cf77518a4d4abe559eb5a5ff919626c39/src/core/calculate.js
44

5-
import { type CSSNode } from '@projectwallace/css-parser'
5+
import { type CSSNode, ID_SELECTOR, ATTRIBUTE_SELECTOR, CLASS_SELECTOR, PSEUDO_CLASS_SELECTOR, SELECTOR_LIST, NTH_OF, SELECTOR, COMBINATOR, PSEUDO_ELEMENT_SELECTOR, TYPE_SELECTOR } from '@projectwallace/css-parser'
66
import { parse_selector } from '@projectwallace/css-parser/parse-selector'
77

88
type Specificity = [number, number, number]
@@ -30,17 +30,17 @@ export const calculateForAST = (selectorAST: CSSNode): Specificity => {
3030
// Iterate through all parts of the selector (children of NODE_SELECTOR)
3131
let current = selectorAST.first_child
3232
while (current) {
33-
switch (current.type_name) {
34-
case 'IdSelector':
33+
switch (current.type) {
34+
case ID_SELECTOR:
3535
a += 1
3636
break
3737

38-
case 'AttributeSelector':
39-
case 'ClassSelector':
38+
case ATTRIBUTE_SELECTOR:
39+
case CLASS_SELECTOR:
4040
b += 1
4141
break
4242

43-
case 'PseudoClassSelector':
43+
case PSEUDO_CLASS_SELECTOR:
4444
switch (current.name.toLowerCase()) {
4545
// "The specificity of a :where() pseudo-class is replaced by zero."
4646
case 'where':
@@ -63,7 +63,7 @@ export const calculateForAST = (selectorAST: CSSNode): Specificity => {
6363
if (current.has_children) {
6464
// The first child should be a NODE_SELECTOR_LIST
6565
const childSelectorList = current.first_child
66-
if (childSelectorList?.type_name === 'SelectorList') {
66+
if (childSelectorList?.type === SELECTOR_LIST) {
6767
// Calculate Specificity for all selectors in the list and get max
6868
const max1 = max(calculate(childSelectorList))
6969

@@ -83,7 +83,7 @@ export const calculateForAST = (selectorAST: CSSNode): Specificity => {
8383

8484
// Get NODE_SELECTOR_NTH_OF which contains the "of" selector list
8585
const nthOf = current.first_child
86-
if (nthOf?.type_name === 'NthOf' && nthOf.selector) {
86+
if (nthOf?.type === NTH_OF && nthOf.selector) {
8787
// Use the convenience property to access the selector list directly
8888
const max2 = max(calculate(nthOf.selector))
8989

@@ -101,11 +101,11 @@ export const calculateForAST = (selectorAST: CSSNode): Specificity => {
101101
b += 1
102102

103103
const childSelector = current.first_child?.first_child
104-
if (childSelector?.type_name === 'Selector') {
104+
if (childSelector?.type === SELECTOR) {
105105
// Calculate specificity for parts before the first combinator
106106
let childPart = childSelector.first_child
107107
while (childPart) {
108-
if (childPart.type_name === 'Combinator') break
108+
if (childPart.type === COMBINATOR) break
109109

110110
// Calculate contribution from this part
111111
const partSpecificity = calculateForAST({
@@ -137,18 +137,18 @@ export const calculateForAST = (selectorAST: CSSNode): Specificity => {
137137
}
138138
break
139139

140-
case 'PseudoElementSelector':
140+
case PSEUDO_ELEMENT_SELECTOR:
141141
switch (current.name.toLowerCase()) {
142142
// "The specificity of ::slotted() is that of a pseudo-element, plus the specificity of its argument."
143143
case 'slotted':
144144
c += 1
145145

146146
const childSelector = current.first_child?.first_child
147-
if (childSelector?.type_name === 'Selector') {
147+
if (childSelector?.type === SELECTOR) {
148148
// Calculate specificity for parts before the first combinator
149149
let childPart = childSelector.first_child
150150
while (childPart) {
151-
if (childPart.type_name === 'Combinator') break
151+
if (childPart.type === COMBINATOR) break
152152

153153
// Calculate contribution from this part
154154
const partSpecificity = calculateForAST({
@@ -184,7 +184,7 @@ export const calculateForAST = (selectorAST: CSSNode): Specificity => {
184184
}
185185
break
186186

187-
case 'TypeSelector':
187+
case TYPE_SELECTOR:
188188
// Omit namespace
189189
let typeSelector = current.name ?? ''
190190
if (typeSelector.includes('|')) {
@@ -223,7 +223,7 @@ const convertToAST = (source: string | CSSNode) => {
223223
// The passed in argument was an Object.
224224
// ~> Let's verify if it's a AST of the type NODE_SELECTOR_LIST
225225
if (source instanceof Object) {
226-
if (source.type_name === 'SelectorList') {
226+
if (source.type === SELECTOR_LIST) {
227227
return source
228228
}
229229

0 commit comments

Comments
 (0)