@@ -303,6 +303,19 @@ function looksLikeUri(declaration) {
303
303
}
304
304
}
305
305
306
+ function isParsableNode ( node ) {
307
+ let isParsable = true
308
+
309
+ node . walkDecls ( ( decl ) => {
310
+ if ( ! isParsableCssValue ( decl . name , decl . value ) ) {
311
+ isParsable = false
312
+ return false
313
+ }
314
+ } )
315
+
316
+ return isParsable
317
+ }
318
+
306
319
function isParsableCssValue ( property , value ) {
307
320
// We don't want to to treat [https://example.com] as a custom property
308
321
// Even though, according to the CSS grammar, it's a totally valid CSS declaration
@@ -456,60 +469,66 @@ function* resolveMatches(candidate, context) {
456
469
}
457
470
}
458
471
459
- // Only keep the result of the very first plugin if we are dealing with
460
- // arbitrary values, to protect against ambiguity.
461
- if ( isArbitraryValue ( modifier ) && matches . length > 1 ) {
462
- let typesPerPlugin = matches . map ( ( match ) => new Set ( [ ...( typesByMatches . get ( match ) ?? [ ] ) ] ) )
472
+ if ( isArbitraryValue ( modifier ) ) {
473
+ // When generated arbitrary values are ambiguous, we can't know
474
+ // which to pick so don't generate any utilities for them
475
+ if ( matches . length > 1 ) {
476
+ let typesPerPlugin = matches . map ( ( match ) => new Set ( [ ...( typesByMatches . get ( match ) ?? [ ] ) ] ) )
463
477
464
- // Remove duplicates, so that we can detect proper unique types for each plugin.
465
- for ( let pluginTypes of typesPerPlugin ) {
466
- for ( let type of pluginTypes ) {
467
- let removeFromOwnGroup = false
478
+ // Remove duplicates, so that we can detect proper unique types for each plugin.
479
+ for ( let pluginTypes of typesPerPlugin ) {
480
+ for ( let type of pluginTypes ) {
481
+ let removeFromOwnGroup = false
468
482
469
- for ( let otherGroup of typesPerPlugin ) {
470
- if ( pluginTypes === otherGroup ) continue
483
+ for ( let otherGroup of typesPerPlugin ) {
484
+ if ( pluginTypes === otherGroup ) continue
471
485
472
- if ( otherGroup . has ( type ) ) {
473
- otherGroup . delete ( type )
474
- removeFromOwnGroup = true
486
+ if ( otherGroup . has ( type ) ) {
487
+ otherGroup . delete ( type )
488
+ removeFromOwnGroup = true
489
+ }
475
490
}
476
- }
477
491
478
- if ( removeFromOwnGroup ) pluginTypes . delete ( type )
492
+ if ( removeFromOwnGroup ) pluginTypes . delete ( type )
493
+ }
479
494
}
480
- }
481
495
482
- let messages = [ ]
483
-
484
- for ( let [ idx , group ] of typesPerPlugin . entries ( ) ) {
485
- for ( let type of group ) {
486
- let rules = matches [ idx ]
487
- . map ( ( [ , rule ] ) => rule )
488
- . flat ( )
489
- . map ( ( rule ) =>
490
- rule
491
- . toString ( )
492
- . split ( '\n' )
493
- . slice ( 1 , - 1 ) // Remove selector and closing ' }'
494
- . map ( ( line ) => line . trim ( ) )
495
- . map ( ( x ) => ` ${ x } ` ) // Re-indent
496
- . join ( '\n' )
496
+ let messages = [ ]
497
+
498
+ for ( let [ idx , group ] of typesPerPlugin . entries ( ) ) {
499
+ for ( let type of group ) {
500
+ let rules = matches [ idx ]
501
+ . map ( ( [ , rule ] ) => rule )
502
+ . flat ( )
503
+ . map ( ( rule ) =>
504
+ rule
505
+ . toString ( )
506
+ . split ( '\n' )
507
+ . slice ( 1 , - 1 ) // Remove selector and closing ' }'
508
+ . map ( ( line ) => line . trim ( ) )
509
+ . map ( ( x ) => ` ${ x } ` ) // Re-indent
510
+ . join ( '\n' )
511
+ )
512
+ . join ( '\n\n' )
513
+
514
+ messages . push (
515
+ ` Use \`${ candidate . replace ( '[' , `[${ type } :` ) } \` for \`${ rules . trim ( ) } \``
497
516
)
498
- . join ( '\n\n' )
499
-
500
- messages . push ( ` Use \`${ candidate . replace ( '[' , `[${ type } :` ) } \` for \`${ rules . trim ( ) } \`` )
501
- break
517
+ break
518
+ }
502
519
}
520
+
521
+ log . warn ( [
522
+ `The class \`${ candidate } \` is ambiguous and matches multiple utilities.` ,
523
+ ...messages ,
524
+ `If this is content and not a class, replace it with \`${ candidate
525
+ . replace ( '[' , '[' )
526
+ . replace ( ']' , ']' ) } \` to silence this warning.`,
527
+ ] )
528
+ continue
503
529
}
504
530
505
- log . warn ( [
506
- `The class \`${ candidate } \` is ambiguous and matches multiple utilities.` ,
507
- ...messages ,
508
- `If this is content and not a class, replace it with \`${ candidate
509
- . replace ( '[' , '[' )
510
- . replace ( ']' , ']' ) } \` to silence this warning.`,
511
- ] )
512
- continue
531
+ matches = matches . map ( ( list ) => list . filter ( ( match ) => isParsableNode ( match [ 1 ] ) ) )
513
532
}
514
533
515
534
matches = matches . flat ( )
0 commit comments