@@ -19,6 +19,7 @@ import { buildCustomContainerUtilityRules } from '../../../../tailwindcss/src/co
19
19
import { darkModePlugin } from '../../../../tailwindcss/src/compat/dark-mode'
20
20
import type { Config } from '../../../../tailwindcss/src/compat/plugin-api'
21
21
import type { DesignSystem } from '../../../../tailwindcss/src/design-system'
22
+ import { DefaultMap } from '../../../../tailwindcss/src/utils/default-map'
22
23
import { escape } from '../../../../tailwindcss/src/utils/escape'
23
24
import {
24
25
isValidOpacityValue ,
@@ -55,8 +56,44 @@ export async function migrateJsConfig(
55
56
`The configuration file at ${ highlight ( relative ( fullConfigPath , base ) ) } could not be automatically migrated to the new CSS configuration format, so your CSS has been updated to load your existing configuration file.` ,
56
57
{ prefix : '↳ ' } ,
57
58
)
58
- for ( let msg of canMigrateConfigResult . errors ) {
59
- warn ( msg , { prefix : ' ↳ ' } )
59
+ for ( let [ category , messages ] of canMigrateConfigResult . errors . entries ( ) ) {
60
+ switch ( category ) {
61
+ case 'general' : {
62
+ for ( let msg of messages ) warn ( msg , { prefix : ' ↳ ' } )
63
+ break
64
+ }
65
+ case 'top-level' : {
66
+ warn (
67
+ `Cannot migrate unknown top-level keys:\n${ Array . from ( messages )
68
+ . map ( ( key ) => ` - \`${ key } \`` )
69
+ . join (
70
+ '\n' ,
71
+ ) } \n\nThese are non-standard Tailwind CSS options, so we don't know how to migrate them to CSS.`,
72
+ { prefix : ' ↳ ' } ,
73
+ )
74
+ break
75
+ }
76
+ case 'unknown-theme-keys' : {
77
+ warn (
78
+ `Cannot migrate unknown theme keys:\n${ Array . from ( messages )
79
+ . map ( ( key ) => ` - \`${ key } \`` )
80
+ . join (
81
+ '\n' ,
82
+ ) } \n\nThese are non-standard Tailwind CSS theme keys, so we don't know how to migrate them to CSS.`,
83
+ { prefix : ' ↳ ' } ,
84
+ )
85
+ break
86
+ }
87
+ case 'complex-screens' : {
88
+ warn (
89
+ `Cannot migrate complex screen configuration (min/max/raw):\n${ Array . from ( messages )
90
+ . map ( ( key ) => ` - \`${ key } \`` )
91
+ . join ( '\n' ) } `,
92
+ { prefix : ' ↳ ' } ,
93
+ )
94
+ break
95
+ }
96
+ }
60
97
}
61
98
return null
62
99
}
@@ -405,17 +442,19 @@ function stringifyPath(path: (string | number)[]): string {
405
442
return result
406
443
}
407
444
445
+ // Keep track of issues given a category and a set of messages
446
+ const MIGRATION_ISSUES = new DefaultMap ( ( ) => new Set < string > ( ) )
447
+
408
448
// Applies heuristics to determine if we can attempt to migrate the config
409
449
function canMigrateConfig (
410
450
unresolvedConfig : Config ,
411
451
source : string ,
412
- ) : { valid : true } | { valid : false ; errors : string [ ] } {
452
+ ) : { valid : true } | { valid : false ; errors : typeof MIGRATION_ISSUES } {
413
453
let theme = unresolvedConfig . theme
414
- let errors : string [ ] = [ ]
415
454
416
455
// Migrating presets are not supported
417
456
if ( unresolvedConfig . presets && unresolvedConfig . presets . length > 0 ) {
418
- errors . push ( 'Cannot migrate config files that use presets' )
457
+ MIGRATION_ISSUES . get ( 'general' ) . add ( 'Cannot migrate config files that use presets' )
419
458
}
420
459
421
460
// The file may only contain known-migratable top-level properties
@@ -431,53 +470,44 @@ function canMigrateConfig(
431
470
432
471
for ( let key of Object . keys ( unresolvedConfig ) ) {
433
472
if ( ! knownProperties . includes ( key ) ) {
434
- errors . push ( `Cannot migrate unknown top-level key: \` ${ key } \`` )
473
+ MIGRATION_ISSUES . get ( ' top-level' ) . add ( key )
435
474
}
436
475
}
437
476
438
477
// Only migrate the config file if all top-level theme keys are allowed to be
439
478
// migrated
440
479
if ( theme && typeof theme === 'object' ) {
441
480
let { extend, ...themeCopy } = theme
442
- errors . push ( ...onlyAllowedThemeValues ( themeCopy , [ 'theme' ] ) )
443
-
444
- if ( extend ) {
445
- errors . push ( ...onlyAllowedThemeValues ( extend , [ 'theme' , 'extend' ] ) )
446
- }
481
+ onlyAllowedThemeValues ( themeCopy , [ 'theme' ] )
482
+ if ( extend ) onlyAllowedThemeValues ( extend , [ 'theme' , 'extend' ] )
447
483
}
448
484
449
485
// TODO: findStaticPlugins already logs errors for unsupported plugins, maybe
450
486
// it should return them instead?
451
487
findStaticPlugins ( source )
452
488
453
- return errors . length <= 0 ? { valid : true } : { valid : false , errors }
489
+ return MIGRATION_ISSUES . size <= 0 ? { valid : true } : { valid : false , errors : MIGRATION_ISSUES }
454
490
}
455
491
456
492
const ALLOWED_THEME_KEYS = [
457
493
...Object . keys ( defaultTheme ) ,
458
494
// Used by @tailwindcss /container-queries
459
495
'containers' ,
460
496
]
461
- function onlyAllowedThemeValues ( theme : ThemeConfig , path : ( string | number ) [ ] ) : string [ ] {
462
- let errors : string [ ] = [ ]
463
-
497
+ function onlyAllowedThemeValues ( theme : ThemeConfig , path : ( string | number ) [ ] ) {
464
498
for ( let key of Object . keys ( theme ) ) {
465
499
if ( ! ALLOWED_THEME_KEYS . includes ( key ) ) {
466
- errors . push ( `Cannot migrate theme key: \` ${ stringifyPath ( [ ...path , key ] ) } \`` )
500
+ MIGRATION_ISSUES . get ( 'unknown- theme-keys' ) . add ( stringifyPath ( [ ...path , key ] ) )
467
501
}
468
502
}
469
503
470
504
if ( 'screens' in theme && typeof theme . screens === 'object' && theme . screens !== null ) {
471
505
for ( let [ name , screen ] of Object . entries ( theme . screens ) ) {
472
506
if ( typeof screen === 'object' && screen !== null && ( 'max' in screen || 'raw' in screen ) ) {
473
- errors . push (
474
- `Cannot migrate complex screen definition: \`${ stringifyPath ( [ ...path , 'screens' , name ] ) } \`` ,
475
- )
507
+ MIGRATION_ISSUES . get ( 'complex-screens' ) . add ( stringifyPath ( [ ...path , 'screens' , name ] ) )
476
508
}
477
509
}
478
510
}
479
-
480
- return errors
481
511
}
482
512
483
513
function keyframesToCss ( keyframes : Record < string , unknown > ) : string {
0 commit comments