Skip to content

Commit 65d037b

Browse files
authored
fix: move theme selector out of the root, and remove nulls (#420)
* fix: move theme selector out of the root * chore: update turbo * chore: remove all nulls in layers
1 parent 8d52715 commit 65d037b

3 files changed

Lines changed: 78 additions & 19 deletions

File tree

bun.lock

Lines changed: 9 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
@@ -38,7 +38,7 @@
3838
"eslint": "9.39.1",
3939
"eslint-config-codemask": "2.2.1",
4040
"husky": "9.1.7",
41-
"turbo": "2.8.7"
41+
"turbo": "2.8.12"
4242
},
4343
"packageManager": "bun@1.3.2",
4444
"trustedDependencies": [

packages/uniwind/src/css-visitor/rule-visitor.ts

Lines changed: 68 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -20,13 +20,9 @@ export class RuleVisitor implements LightningRuleVisitors {
2020

2121
style = (styleRule: Extract<LightningRuleVisitor, { type: 'style' }>) => {
2222
const firstSelector = styleRule.value.selectors.at(0)?.at(0)
23-
const secondSelector = styleRule.value.selectors.at(0)?.at(1)
2423

25-
if (
26-
this.currentLayerName === 'theme' && firstSelector?.type === 'nesting' && secondSelector?.type === 'pseudo-class'
27-
&& secondSelector.kind === 'where'
28-
) {
29-
return this.processThemeStyle(styleRule, secondSelector)
24+
if (this.currentLayerName === 'theme' && firstSelector?.type === 'pseudo-class' && firstSelector.kind === 'root') {
25+
return this.removeNulls(this.processThemeRoot(styleRule)) as Array<ReturnedRule>
3026
}
3127

3228
if (firstSelector?.type === 'class') {
@@ -40,20 +36,60 @@ export class RuleVisitor implements LightningRuleVisitors {
4036
this.processedVariables.clear()
4137
}
4238

39+
private processThemeRoot(styleRule: Extract<LightningRuleVisitor, { type: 'style' }>): Array<ReturnedRule> {
40+
const themeScopedRules = styleRule.value.rules?.filter(rule => {
41+
if (rule.type !== 'style') {
42+
return false
43+
}
44+
45+
const firstSelector = rule.value.selectors.at(0)?.at(0)
46+
const secondSelector = rule.value.selectors.at(0)?.at(1)
47+
48+
return firstSelector?.type === 'nesting' && secondSelector?.type === 'pseudo-class' && secondSelector.kind === 'where'
49+
}) ?? []
50+
const nonThemeRules = styleRule.value.rules?.filter(rule => !themeScopedRules.includes(rule))
51+
const processedThemeScopedRules = themeScopedRules.map(rule => {
52+
if (rule.type !== 'style') {
53+
return rule
54+
}
55+
56+
const secondSelector = rule.value.selectors.at(0)?.at(1)
57+
58+
if (secondSelector?.type === 'pseudo-class' && secondSelector.kind === 'where') {
59+
return this.processThemeStyle(rule, secondSelector)
60+
}
61+
62+
return rule
63+
})
64+
65+
return [
66+
{
67+
type: 'style',
68+
value: {
69+
loc: styleRule.value.loc,
70+
selectors: styleRule.value.selectors,
71+
rules: nonThemeRules,
72+
declarations: styleRule.value.declarations,
73+
},
74+
},
75+
...processedThemeScopedRules,
76+
]
77+
}
78+
4379
private processThemeStyle(
4480
styleRule: Extract<LightningRuleVisitor, { type: 'style' }>,
4581
secondSelector: Extract<SelectorComponent, { type: 'pseudo-class'; kind: 'where' }>,
46-
): ReturnedRule | void {
82+
): ReturnedRule {
4783
const whereSelector = secondSelector.selectors.at(0)?.at(0)
4884

4985
if (whereSelector?.type !== 'class') {
50-
return
86+
return styleRule
5187
}
5288

5389
const selectedVariant = this.themes.find(theme => whereSelector.name === theme)
5490

5591
if (selectedVariant === undefined || this.processedVariables.has(selectedVariant)) {
56-
return
92+
return styleRule
5793
}
5894

5995
this.processedVariables.add(selectedVariant)
@@ -93,4 +129,27 @@ export class RuleVisitor implements LightningRuleVisitors {
93129
},
94130
}
95131
}
132+
133+
// Fixes lightningcss serialization bug
134+
private removeNulls(value: unknown): unknown {
135+
if (Array.isArray(value)) {
136+
return value.map(v => this.removeNulls(v))
137+
}
138+
139+
if (typeof value === 'object' && value !== null) {
140+
return Object.fromEntries(
141+
Object.entries(value)
142+
.filter(([_, value]) => {
143+
if (value === null) {
144+
return false
145+
}
146+
147+
return true
148+
})
149+
.map(([key, value]) => [key, this.removeNulls(value)]),
150+
)
151+
}
152+
153+
return value
154+
}
96155
}

0 commit comments

Comments
 (0)