@@ -270,6 +270,10 @@ export function optimizeAst(
270
270
Extract < AstNode , { nodes : AstNode [ ] } > [ 'nodes' ] ,
271
271
Set < Declaration >
272
272
> ( ( ) => new Set ( ) )
273
+ let colorMixDeclarations = new DefaultMap <
274
+ Extract < AstNode , { nodes : AstNode [ ] } > [ 'nodes' ] ,
275
+ Set < Declaration >
276
+ > ( ( ) => new Set ( ) )
273
277
let keyframes = new Set < AtRule > ( )
274
278
let usedKeyframeNames = new Set ( )
275
279
@@ -326,71 +330,7 @@ export function optimizeAst(
326
330
// Create fallback values for usages of the `color-mix(…)` function that reference variables
327
331
// found in the theme config.
328
332
if ( polyfills & Polyfills . ColorMix && node . value . includes ( 'color-mix(' ) ) {
329
- let ast = ValueParser . parse ( node . value )
330
-
331
- let requiresPolyfill = false
332
- ValueParser . walk ( ast , ( node , { replaceWith } ) => {
333
- if ( node . kind !== 'function' || node . value !== 'color-mix' ) return
334
-
335
- let containsUnresolvableVars = false
336
- let containsCurrentcolor = false
337
- ValueParser . walk ( node . nodes , ( node , { replaceWith } ) => {
338
- if ( node . kind == 'word' && node . value . toLowerCase ( ) === 'currentcolor' ) {
339
- containsCurrentcolor = true
340
- requiresPolyfill = true
341
- return
342
- }
343
- if ( node . kind !== 'function' || node . value !== 'var' ) return
344
- let firstChild = node . nodes [ 0 ]
345
- if ( ! firstChild || firstChild . kind !== 'word' ) return
346
-
347
- requiresPolyfill = true
348
-
349
- let inlinedColor = designSystem . theme . resolveValue ( null , [ firstChild . value as any ] )
350
- if ( ! inlinedColor ) {
351
- containsUnresolvableVars = true
352
- return
353
- }
354
-
355
- replaceWith ( { kind : 'word' , value : inlinedColor } )
356
- } )
357
-
358
- if ( containsUnresolvableVars || containsCurrentcolor ) {
359
- let separatorIndex = node . nodes . findIndex (
360
- ( node ) => node . kind === 'separator' && node . value . trim ( ) . includes ( ',' ) ,
361
- )
362
- if ( separatorIndex === - 1 ) return
363
- let firstColorValue =
364
- node . nodes . length > separatorIndex ? node . nodes [ separatorIndex + 1 ] : null
365
- if ( ! firstColorValue ) return
366
- replaceWith ( firstColorValue )
367
- } else if ( requiresPolyfill ) {
368
- // Change the colorspace to `srgb` since the fallback values should not be represented as
369
- // `oklab(…)` functions again as their support in Safari <16 is very limited.
370
- let colorspace = node . nodes [ 2 ]
371
- if (
372
- colorspace . kind === 'word' &&
373
- ( colorspace . value === 'oklab' ||
374
- colorspace . value === 'oklch' ||
375
- colorspace . value === 'lab' ||
376
- colorspace . value === 'lch' )
377
- ) {
378
- colorspace . value = 'srgb'
379
- }
380
- }
381
- } )
382
-
383
- if ( requiresPolyfill ) {
384
- let fallback = {
385
- ...node ,
386
- value : ValueParser . toCss ( ast ) ,
387
- }
388
- let colorMixQuery = rule ( '@supports (color: color-mix(in lab, red, red))' , [ node ] )
389
-
390
- parent . push ( fallback , colorMixQuery )
391
-
392
- return
393
- }
333
+ colorMixDeclarations . get ( parent ) . add ( node )
394
334
}
395
335
396
336
parent . push ( node )
@@ -595,6 +535,74 @@ export function optimizeAst(
595
535
newAst = newAst . concat ( atRoots )
596
536
597
537
// Fallbacks
538
+ // Create fallback values for usages of the `color-mix(…)` function that reference variables
539
+ // found in the theme config.
540
+ if ( polyfills & Polyfills . ColorMix ) {
541
+ for ( let [ parent , declarations ] of colorMixDeclarations ) {
542
+ for ( let declaration of declarations ) {
543
+ let idx = parent . indexOf ( declaration )
544
+ // If the declaration is no longer present, we don't need to create a polyfill anymore
545
+ if ( idx === - 1 || declaration . value == null ) continue
546
+
547
+ let ast = ValueParser . parse ( declaration . value )
548
+ let requiresPolyfill = false
549
+ ValueParser . walk ( ast , ( node , { replaceWith } ) => {
550
+ if ( node . kind !== 'function' || node . value !== 'color-mix' ) return
551
+ let containsUnresolvableVars = false
552
+ let containsCurrentcolor = false
553
+ ValueParser . walk ( node . nodes , ( node , { replaceWith } ) => {
554
+ if ( node . kind == 'word' && node . value . toLowerCase ( ) === 'currentcolor' ) {
555
+ containsCurrentcolor = true
556
+ requiresPolyfill = true
557
+ return
558
+ }
559
+ if ( node . kind !== 'function' || node . value !== 'var' ) return
560
+ let firstChild = node . nodes [ 0 ]
561
+ if ( ! firstChild || firstChild . kind !== 'word' ) return
562
+ requiresPolyfill = true
563
+ let inlinedColor = designSystem . theme . resolveValue ( null , [ firstChild . value as any ] )
564
+ if ( ! inlinedColor ) {
565
+ containsUnresolvableVars = true
566
+ return
567
+ }
568
+ replaceWith ( { kind : 'word' , value : inlinedColor } )
569
+ } )
570
+ if ( containsUnresolvableVars || containsCurrentcolor ) {
571
+ let separatorIndex = node . nodes . findIndex (
572
+ ( node ) => node . kind === 'separator' && node . value . trim ( ) . includes ( ',' ) ,
573
+ )
574
+ if ( separatorIndex === - 1 ) return
575
+ let firstColorValue =
576
+ node . nodes . length > separatorIndex ? node . nodes [ separatorIndex + 1 ] : null
577
+ if ( ! firstColorValue ) return
578
+ replaceWith ( firstColorValue )
579
+ } else if ( requiresPolyfill ) {
580
+ // Change the colorspace to `srgb` since the fallback values should not be represented as
581
+ // `oklab(…)` functions again as their support in Safari <16 is very limited.
582
+ let colorspace = node . nodes [ 2 ]
583
+ if (
584
+ colorspace . kind === 'word' &&
585
+ ( colorspace . value === 'oklab' ||
586
+ colorspace . value === 'oklch' ||
587
+ colorspace . value === 'lab' ||
588
+ colorspace . value === 'lch' )
589
+ ) {
590
+ colorspace . value = 'srgb'
591
+ }
592
+ }
593
+ } )
594
+ if ( ! requiresPolyfill ) continue
595
+
596
+ let fallback = {
597
+ ...declaration ,
598
+ value : ValueParser . toCss ( ast ) ,
599
+ }
600
+ let colorMixQuery = rule ( '@supports (color: color-mix(in lab, red, red))' , [ declaration ] )
601
+ parent . splice ( idx , 1 , fallback , colorMixQuery )
602
+ }
603
+ }
604
+ }
605
+
598
606
if ( polyfills & Polyfills . AtProperty ) {
599
607
let fallbackAst = [ ]
600
608
0 commit comments