Skip to content

Commit 79cae4b

Browse files
committed
refactor: when migrating theme key, handle special cases first
We were handling special cases (keyframes, container) _after_ we handled the normal theme keys. When handling the normal theme keys we skipped the special keys which means that you have to keep the list in sync. Now we will handle special cases first. Another refactor here is that we will push data to an intermediate variable before emitting the `@theme {…}` wrapper. This will allow us to only emit CSS when needed. We were explicitly returning `null` in some cases, but we can also just return the empty string when there is no CSS to get the same effect.
1 parent 4d8ca12 commit 79cae4b

File tree

1 file changed

+39
-28
lines changed

1 file changed

+39
-28
lines changed

packages/@tailwindcss-upgrade/src/codemods/config/migrate-js-config.ts

Lines changed: 39 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ async function migrateTheme(
9797
designSystem: DesignSystem,
9898
unresolvedConfig: Config,
9999
base: string,
100-
): Promise<string | null> {
100+
): Promise<string> {
101101
// Resolve the config file without applying plugins and presets, as these are
102102
// migrated to CSS separately.
103103
let configToResolve: ConfigFile = {
@@ -114,10 +114,34 @@ async function migrateTheme(
114114

115115
removeUnnecessarySpacingKeys(designSystem, resolvedConfig, replacedThemeKeys)
116116

117+
let css = ''
117118
let prevSectionKey = ''
118-
let css = '\n@tw-bucket theme {\n'
119-
css += `\n@theme {\n`
120-
let containsThemeKeys = false
119+
let themeSection: string[] = []
120+
let keyframesCss = ''
121+
122+
// Special handling of specific theme keys:
123+
{
124+
if ('keyframes' in resolvedConfig.theme) {
125+
keyframesCss += keyframesToCss(resolvedConfig.theme.keyframes)
126+
delete resolvedConfig.theme.keyframes
127+
}
128+
129+
if ('container' in resolvedConfig.theme) {
130+
let rules = buildCustomContainerUtilityRules(resolvedConfig.theme.container, designSystem)
131+
if (rules.length > 0) {
132+
// Using `theme` instead of `utility` so it sits before the `@layer
133+
// base` with compatibility CSS. While this is technically a utility, it
134+
// makes a bit more sense to emit this closer to the `@theme` values
135+
// since it is needed for backwards compatibility.
136+
css += `\n@tw-bucket theme {\n`
137+
css += toCss([atRule('@utility', 'container', rules)])
138+
css += '}\n' // @tw-bucket
139+
}
140+
delete resolvedConfig.theme.container
141+
}
142+
}
143+
144+
// Convert theme values to CSS custom properties
121145
for (let [key, value] of themeableValues(resolvedConfig.theme)) {
122146
if (typeof value !== 'string' && typeof value !== 'number') {
123147
continue
@@ -152,51 +176,38 @@ async function migrateTheme(
152176
}
153177
}
154178

155-
if (key[0] === 'keyframes') {
156-
continue
157-
}
158-
containsThemeKeys = true
159-
160179
let sectionKey = createSectionKey(key)
161180
if (sectionKey !== prevSectionKey) {
162-
css += `\n`
181+
themeSection.push('')
163182
prevSectionKey = sectionKey
164183
}
165184

166185
if (resetNamespaces.has(key[0]) && resetNamespaces.get(key[0]) === false) {
167186
resetNamespaces.set(key[0], true)
168187
let property = keyPathToCssProperty([key[0]])
169188
if (property !== null) {
170-
css += ` ${escape(`--${property}`)}-*: initial;\n`
189+
themeSection.push(` ${escape(`--${property}`)}-*: initial;`)
171190
}
172191
}
173192

174193
let property = keyPathToCssProperty(key)
175194
if (property !== null) {
176-
css += ` ${escape(`--${property}`)}: ${value};\n`
195+
themeSection.push(` ${escape(`--${property}`)}: ${value};`)
177196
}
178197
}
179198

180-
if ('keyframes' in resolvedConfig.theme) {
181-
containsThemeKeys = true
182-
css += '\n' + keyframesToCss(resolvedConfig.theme.keyframes)
199+
if (keyframesCss) {
200+
themeSection.push('', keyframesCss)
183201
}
184202

185-
if (!containsThemeKeys) {
186-
return null
203+
if (themeSection.length > 0) {
204+
css += `\n@tw-bucket theme {\n`
205+
css += `\n@theme {\n`
206+
css += themeSection.join('\n') + '\n'
207+
css += '}\n' // @theme
208+
css += '}\n' // @tw-bucket
187209
}
188210

189-
css += '}\n' // @theme
190-
191-
if ('container' in resolvedConfig.theme) {
192-
let rules = buildCustomContainerUtilityRules(resolvedConfig.theme.container, designSystem)
193-
if (rules.length > 0) {
194-
css += '\n' + toCss([atRule('@utility', 'container', rules)])
195-
}
196-
}
197-
198-
css += '}\n' // @tw-bucket
199-
200211
return css
201212
}
202213

0 commit comments

Comments
 (0)