@@ -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