@@ -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 ,
@@ -54,8 +55,55 @@ export async function migrateJsConfig(
54
55
`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.` ,
55
56
{ prefix : '↳ ' } ,
56
57
)
57
- for ( let msg of canMigrateConfigResult . errors ) {
58
- warn ( msg , { prefix : ' ↳ ' } )
58
+ for ( let [ category , messages ] of canMigrateConfigResult . errors . entries ( ) ) {
59
+ switch ( category ) {
60
+ case 'general' : {
61
+ for ( let msg of messages ) warn ( msg , { prefix : ' ↳ ' } )
62
+ break
63
+ }
64
+ case 'top-level' : {
65
+ warn (
66
+ `Cannot migrate unknown top-level keys:\n${ Array . from ( messages )
67
+ . map ( ( key ) => ` - \`${ key } \`` )
68
+ . join (
69
+ '\n' ,
70
+ ) } \n\nThese are non-standard Tailwind CSS options, so we don't know how to migrate them to CSS.`,
71
+ { prefix : ' ↳ ' } ,
72
+ )
73
+ break
74
+ }
75
+ case 'unknown-theme-keys' : {
76
+ warn (
77
+ `Cannot migrate unknown theme keys:\n${ Array . from ( messages )
78
+ . map ( ( key ) => ` - \`${ key } \`` )
79
+ . join (
80
+ '\n' ,
81
+ ) } \n\nThese are non-standard Tailwind CSS theme keys, so we don't know how to migrate them to CSS.`,
82
+ { prefix : ' ↳ ' } ,
83
+ )
84
+ break
85
+ }
86
+ case 'variant-theme-keys' : {
87
+ warn (
88
+ `Cannot migrate variant theme keys:\n${ Array . from ( messages )
89
+ . map ( ( key ) => ` - \`${ key } \`` )
90
+ . join (
91
+ '\n' ,
92
+ ) } \n\nThese theme keys are for variants (like \`data\`, \`aria\`, or \`supports\`), but will probably work out of the box.`,
93
+ { prefix : ' ↳ ' } ,
94
+ )
95
+ break
96
+ }
97
+ case 'complex-screens' : {
98
+ warn (
99
+ `Cannot migrate complex screen configuration (min/max/raw):\n${ Array . from ( messages )
100
+ . map ( ( key ) => ` - \`${ key } \`` )
101
+ . join ( '\n' ) } `,
102
+ { prefix : ' ↳ ' } ,
103
+ )
104
+ break
105
+ }
106
+ }
59
107
}
60
108
return null
61
109
}
@@ -320,17 +368,19 @@ function stringifyPath(path: (string | number)[]): string {
320
368
return result
321
369
}
322
370
371
+ // Keep track of issues given a category and a set of messages
372
+ const MIGRATION_ISSUES = new DefaultMap ( ( ) => new Set < string > ( ) )
373
+
323
374
// Applies heuristics to determine if we can attempt to migrate the config
324
375
function canMigrateConfig (
325
376
unresolvedConfig : Config ,
326
377
source : string ,
327
- ) : { valid : true } | { valid : false ; errors : string [ ] } {
378
+ ) : { valid : true } | { valid : false ; errors : typeof MIGRATION_ISSUES } {
328
379
let theme = unresolvedConfig . theme
329
- let errors : string [ ] = [ ]
330
380
331
381
// Migrating presets are not supported
332
382
if ( unresolvedConfig . presets && unresolvedConfig . presets . length > 0 ) {
333
- errors . push ( 'Cannot migrate config files that use presets' )
383
+ MIGRATION_ISSUES . get ( 'general' ) . add ( 'Cannot migrate config files that use presets' )
334
384
}
335
385
336
386
// The file may only contain known-migratable top-level properties
@@ -346,58 +396,49 @@ function canMigrateConfig(
346
396
347
397
for ( let key of Object . keys ( unresolvedConfig ) ) {
348
398
if ( ! knownProperties . includes ( key ) ) {
349
- errors . push ( `Cannot migrate unknown top-level key: \` ${ key } \`` )
399
+ MIGRATION_ISSUES . get ( ' top-level' ) . add ( key )
350
400
}
351
401
}
352
402
353
403
// Only migrate the config file if all top-level theme keys are allowed to be
354
404
// migrated
355
405
if ( theme && typeof theme === 'object' ) {
356
406
let { extend, ...themeCopy } = theme
357
- errors . push ( ...onlyAllowedThemeValues ( themeCopy , [ 'theme' ] ) )
358
-
359
- if ( extend ) {
360
- errors . push ( ...onlyAllowedThemeValues ( extend , [ 'theme' , 'extend' ] ) )
361
- }
407
+ onlyAllowedThemeValues ( themeCopy , [ 'theme' ] )
408
+ if ( extend ) onlyAllowedThemeValues ( extend , [ 'theme' , 'extend' ] )
362
409
}
363
410
364
411
// TODO: findStaticPlugins already logs errors for unsupported plugins, maybe
365
412
// it should return them instead?
366
413
findStaticPlugins ( source )
367
414
368
- return errors . length <= 0 ? { valid : true } : { valid : false , errors }
415
+ return MIGRATION_ISSUES . size <= 0 ? { valid : true } : { valid : false , errors : MIGRATION_ISSUES }
369
416
}
370
417
371
418
const ALLOWED_THEME_KEYS = [
372
419
...Object . keys ( defaultTheme ) ,
373
420
// Used by @tailwindcss /container-queries
374
421
'containers' ,
375
422
]
376
- const BLOCKED_THEME_KEYS = [ 'supports' , 'data' , 'aria' ]
377
- function onlyAllowedThemeValues ( theme : ThemeConfig , path : ( string | number ) [ ] ) : string [ ] {
378
- let errors : string [ ] = [ ]
379
-
423
+ const VARIANT_THEME_KEYS = [ 'supports' , 'data' , 'aria' ]
424
+ function onlyAllowedThemeValues ( theme : ThemeConfig , path : ( string | number ) [ ] ) {
380
425
for ( let key of Object . keys ( theme ) ) {
381
426
if ( ! ALLOWED_THEME_KEYS . includes ( key ) ) {
382
- errors . push ( `Cannot migrate theme key: \` ${ stringifyPath ( [ ...path , key ] ) } \`` )
427
+ MIGRATION_ISSUES . get ( 'unknown- theme-keys' ) . add ( stringifyPath ( [ ...path , key ] ) )
383
428
}
384
429
385
- if ( BLOCKED_THEME_KEYS . includes ( key ) ) {
386
- errors . push ( `Cannot migrate theme key: \` ${ stringifyPath ( [ ...path , key ] ) } \`` )
430
+ if ( VARIANT_THEME_KEYS . includes ( key ) ) {
431
+ MIGRATION_ISSUES . get ( 'variant- theme-keys' ) . add ( stringifyPath ( [ ...path , key ] ) )
387
432
}
388
433
}
389
434
390
435
if ( 'screens' in theme && typeof theme . screens === 'object' && theme . screens !== null ) {
391
436
for ( let [ name , screen ] of Object . entries ( theme . screens ) ) {
392
437
if ( typeof screen === 'object' && screen !== null && ( 'max' in screen || 'raw' in screen ) ) {
393
- errors . push (
394
- `Cannot migrate complex screen definition: \`${ stringifyPath ( [ ...path , 'screens' , name ] ) } \`` ,
395
- )
438
+ MIGRATION_ISSUES . get ( 'complex-screens' ) . add ( stringifyPath ( [ ...path , 'screens' , name ] ) )
396
439
}
397
440
}
398
441
}
399
-
400
- return errors
401
442
}
402
443
403
444
function keyframesToCss ( keyframes : Record < string , unknown > ) : string {
0 commit comments