Skip to content

Commit 4b19de3

Browse files
Address follow-up work for #14639 (#14650)
This PR adds a few more test cases to #14639 and updates the documentation. --------- Co-authored-by: Jordan Pittman <jordan@cryptica.me>
1 parent 4e219dc commit 4b19de3

File tree

7 files changed

+278
-24
lines changed

7 files changed

+278
-24
lines changed

CHANGELOG.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1616
- _Upgrade (experimental)_: Migrate v3 PostCSS setups to v4 in some cases ([#14612](https://github.com/tailwindlabs/tailwindcss/pull/14612))
1717
- _Upgrade (experimental)_: Automatically discover JavaScript config files ([#14597](https://github.com/tailwindlabs/tailwindcss/pull/14597))
1818
- _Upgrade (experimental)_: Migrate legacy classes to the v4 alternative ([#14643](https://github.com/tailwindlabs/tailwindcss/pull/14643))
19-
- _Upgrade (experimental)_: Fully convert simple JS configs to CSS ([#14639](https://github.com/tailwindlabs/tailwindcss/pull/14639))
19+
- _Upgrade (experimental)_: Migrate static JS configurations to CSS ([#14639](https://github.com/tailwindlabs/tailwindcss/pull/14639), [#14650](https://github.com/tailwindlabs/tailwindcss/pull/14650))
2020
- _Upgrade (experimental)_: Migrate `@media screen(…)` when running codemods ([#14603](https://github.com/tailwindlabs/tailwindcss/pull/14603))
2121
- _Upgrade (experimental)_: Inject `@config "…"` when a `tailwind.config.{js,ts,…}` is detected ([#14635](https://github.com/tailwindlabs/tailwindcss/pull/14635))
2222
- _Upgrade (experimental)_: Migrate `aria-*`, `data-*`, and `supports-*` variants from arbitrary values to bare values ([#14644](https://github.com/tailwindlabs/tailwindcss/pull/14644))

integrations/upgrade/js-config.test.ts

+191-2
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { expect } from 'vitest'
22
import { css, json, test, ts } from '../utils'
33

44
test(
5-
`upgrades a simple JS config file to CSS`,
5+
`upgrade JS config files with flat theme values, darkMode, and content fields`,
66
{
77
fs: {
88
'package.json': json`
@@ -103,7 +103,196 @@ test(
103103
)
104104

105105
test(
106-
`does not upgrade a complex JS config file to CSS`,
106+
'does not upgrade JS config files with functions in the theme config',
107+
{
108+
fs: {
109+
'package.json': json`
110+
{
111+
"dependencies": {
112+
"@tailwindcss/upgrade": "workspace:^"
113+
}
114+
}
115+
`,
116+
'tailwind.config.ts': ts`
117+
import { type Config } from 'tailwindcss'
118+
119+
export default {
120+
theme: {
121+
extend: {
122+
colors: ({ colors }) => ({
123+
gray: colors.neutral,
124+
}),
125+
},
126+
},
127+
} satisfies Config
128+
`,
129+
'src/input.css': css`
130+
@tailwind base;
131+
@tailwind components;
132+
@tailwind utilities;
133+
`,
134+
},
135+
},
136+
async ({ exec, fs }) => {
137+
await exec('npx @tailwindcss/upgrade')
138+
139+
expect(await fs.dumpFiles('src/**/*.{css,ts}')).toMatchInlineSnapshot(`
140+
"
141+
--- src/input.css ---
142+
@import 'tailwindcss';
143+
@config '../tailwind.config.ts';
144+
"
145+
`)
146+
147+
expect(await fs.dumpFiles('tailwind.config.ts')).toMatchInlineSnapshot(`
148+
"
149+
--- tailwind.config.ts ---
150+
import { type Config } from 'tailwindcss'
151+
152+
export default {
153+
theme: {
154+
extend: {
155+
colors: ({ colors }) => ({
156+
gray: colors.neutral,
157+
}),
158+
},
159+
},
160+
} satisfies Config
161+
"
162+
`)
163+
},
164+
)
165+
166+
test(
167+
'does not upgrade JS config files with theme keys contributed to by plugins in the theme config',
168+
{
169+
fs: {
170+
'package.json': json`
171+
{
172+
"dependencies": {
173+
"@tailwindcss/upgrade": "workspace:^"
174+
}
175+
}
176+
`,
177+
'tailwind.config.ts': ts`
178+
import { type Config } from 'tailwindcss'
179+
180+
export default {
181+
theme: {
182+
typography: {
183+
DEFAULT: {
184+
css: {
185+
'--tw-prose-body': 'red',
186+
color: 'var(--tw-prose-body)',
187+
},
188+
},
189+
},
190+
},
191+
} satisfies Config
192+
`,
193+
'src/input.css': css`
194+
@tailwind base;
195+
@tailwind components;
196+
@tailwind utilities;
197+
@config '../tailwind.config.ts';
198+
`,
199+
},
200+
},
201+
async ({ exec, fs }) => {
202+
await exec('npx @tailwindcss/upgrade')
203+
204+
expect(await fs.dumpFiles('src/**/*.css')).toMatchInlineSnapshot(`
205+
"
206+
--- src/input.css ---
207+
@import 'tailwindcss';
208+
@config '../tailwind.config.ts';
209+
"
210+
`)
211+
212+
expect(await fs.dumpFiles('tailwind.config.ts')).toMatchInlineSnapshot(`
213+
"
214+
--- tailwind.config.ts ---
215+
import { type Config } from 'tailwindcss'
216+
217+
export default {
218+
theme: {
219+
typography: {
220+
DEFAULT: {
221+
css: {
222+
'--tw-prose-body': 'red',
223+
color: 'var(--tw-prose-body)',
224+
},
225+
},
226+
},
227+
},
228+
} satisfies Config
229+
"
230+
`)
231+
},
232+
)
233+
234+
test(
235+
'does not upgrade JS config files with plugins',
236+
{
237+
fs: {
238+
'package.json': json`
239+
{
240+
"dependencies": {
241+
"@tailwindcss/typography": "^0.5.15",
242+
"@tailwindcss/upgrade": "workspace:^"
243+
}
244+
}
245+
`,
246+
'tailwind.config.ts': ts`
247+
import { type Config } from 'tailwindcss'
248+
import typography from '@tailwindcss/typography'
249+
import customPlugin from './custom-plugin'
250+
251+
export default {
252+
plugins: [typography, customPlugin],
253+
} satisfies Config
254+
`,
255+
'custom-plugin.js': ts`
256+
export default function ({ addVariant }) {
257+
addVariant('inverted', '@media (inverted-colors: inverted)')
258+
addVariant('hocus', ['&:focus', '&:hover'])
259+
}
260+
`,
261+
'src/input.css': css`
262+
@tailwind base;
263+
@tailwind components;
264+
@tailwind utilities;
265+
`,
266+
},
267+
},
268+
async ({ exec, fs }) => {
269+
await exec('npx @tailwindcss/upgrade')
270+
271+
expect(await fs.dumpFiles('src/**/*.css')).toMatchInlineSnapshot(`
272+
"
273+
--- src/input.css ---
274+
@import 'tailwindcss';
275+
@config '../tailwind.config.ts';
276+
"
277+
`)
278+
279+
expect(await fs.dumpFiles('tailwind.config.ts')).toMatchInlineSnapshot(`
280+
"
281+
--- tailwind.config.ts ---
282+
import { type Config } from 'tailwindcss'
283+
import typography from '@tailwindcss/typography'
284+
import customPlugin from './custom-plugin'
285+
286+
export default {
287+
plugins: [typography, customPlugin],
288+
} satisfies Config
289+
"
290+
`)
291+
},
292+
)
293+
294+
test(
295+
`does not upgrade JS config files with inline plugins`,
107296
{
108297
fs: {
109298
'package.json': json`

packages/@tailwindcss-node/src/compile.ts

+3-5
Original file line numberDiff line numberDiff line change
@@ -100,11 +100,8 @@ async function importModule(path: string): Promise<any> {
100100
try {
101101
return await import(path)
102102
} catch (error) {
103-
try {
104-
jiti ??= createJiti(import.meta.url, { moduleCache: false, fsCache: false })
105-
return await jiti.import(path)
106-
} catch {}
107-
throw error
103+
jiti ??= createJiti(import.meta.url, { moduleCache: false, fsCache: false })
104+
return await jiti.import(path)
108105
}
109106
}
110107

@@ -144,6 +141,7 @@ async function resolveCssId(id: string, base: string): Promise<string | false |
144141
const jsResolver = EnhancedResolve.ResolverFactory.createResolver({
145142
fileSystem: new EnhancedResolve.CachedInputFileSystem(fs, 4000),
146143
useSyncFileSystemCalls: true,
144+
extensions: ['.js', '.json', '.node', '.ts'],
147145
})
148146

149147
function resolveJsId(id: string, base: string): Promise<string | false | undefined> {

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

+6-8
Original file line numberDiff line numberDiff line change
@@ -63,9 +63,8 @@ export function migrateConfig(
6363
cssConfig.append(postcss.parse(css + jsConfigMigration.css))
6464
}
6565

66-
// Inject the `@config` in a sensible place
67-
// 1. Below the last `@import`
68-
// 2. At the top of the file
66+
// Inject the `@config` directive after the last `@import` or at the
67+
// top of the file if no `@import` rules are present
6968
let locationNode = null as AtRule | null
7069

7170
walk(root, (node) => {
@@ -99,10 +98,9 @@ export function migrateConfig(
9998

10099
if (!hasTailwindImport) return
101100

102-
// - If a full `@import "tailwindcss"` is present, we can inject the
103-
// `@config` directive directly into this stylesheet.
104-
// - If we are the root file (no parents), then we can inject the `@config`
105-
// directive directly into this file as well.
101+
// If a full `@import "tailwindcss"` is present or this is the root
102+
// stylesheet, we can inject the `@config` directive directly into this
103+
// file.
106104
if (hasFullTailwindImport || sheet.parents.size <= 0) {
107105
injectInto(sheet)
108106
return
@@ -134,7 +132,7 @@ function relativeToStylesheet(sheet: Stylesheet, absolute: string) {
134132
if (relative[0] !== '.') {
135133
relative = `./${relative}`
136134
}
137-
// Ensure relative is a posix style path since we will merge it with the
135+
// Ensure relative is a POSIX style path since we will merge it with the
138136
// glob.
139137
return normalizePath(relative)
140138
}

0 commit comments

Comments
 (0)