In order to properly migrate your Tailwind CSS v3 project to v4, we need access to the JavaScript configuration object. This was previously only required for template migrations, but in this PR we're making it so that this is also a prerequisite of the CSS migrations. This is because some migrations, like `@apply`, also need to convert candidates that to the v4 syntax and we need the full config in order to properly validate them. In addition to requiring a JS config, we also now attempt to automatically find the right configuration file inside the current working directory. This is now matching the behavior of the Tailwind CSS v3 CLI where it will find the config automatically if it's in the current directory and called `tailwind.conf.js`. --------- Co-authored-by: Robin Malfait <malfait.robin@gmail.com>
117 lines
2.6 KiB
TypeScript
117 lines
2.6 KiB
TypeScript
import { __unstable__loadDesignSystem } from '@tailwindcss/node'
|
|
import dedent from 'dedent'
|
|
import postcss from 'postcss'
|
|
import type { Config } from 'tailwindcss'
|
|
import { expect, it } from 'vitest'
|
|
import { migrateAtApply } from './migrate-at-apply'
|
|
|
|
const css = dedent
|
|
|
|
async function migrate(input: string, config: Config = {}) {
|
|
let designSystem = await __unstable__loadDesignSystem(
|
|
css`
|
|
@import 'tailwindcss';
|
|
`,
|
|
{ base: __dirname },
|
|
)
|
|
|
|
return postcss()
|
|
.use(
|
|
migrateAtApply({
|
|
designSystem,
|
|
userConfig: config,
|
|
}),
|
|
)
|
|
.process(input, { from: expect.getState().testPath })
|
|
.then((result) => result.css)
|
|
}
|
|
|
|
it('should not migrate `@apply`, when there are no issues', async () => {
|
|
expect(
|
|
await migrate(css`
|
|
.foo {
|
|
@apply flex flex-col items-center;
|
|
}
|
|
`),
|
|
).toMatchInlineSnapshot(`
|
|
".foo {
|
|
@apply flex flex-col items-center;
|
|
}"
|
|
`)
|
|
})
|
|
|
|
it('should append `!` to each utility, when using `!important`', async () => {
|
|
expect(
|
|
await migrate(css`
|
|
.foo {
|
|
@apply flex flex-col !important;
|
|
}
|
|
`),
|
|
).toMatchInlineSnapshot(`
|
|
".foo {
|
|
@apply flex! flex-col!;
|
|
}"
|
|
`)
|
|
})
|
|
|
|
// TODO: Handle SCSS syntax
|
|
it.skip('should append `!` to each utility, when using `#{!important}`', async () => {
|
|
expect(
|
|
await migrate(css`
|
|
.foo {
|
|
@apply flex flex-col #{!important};
|
|
}
|
|
`),
|
|
).toMatchInlineSnapshot(`
|
|
".foo {
|
|
@apply flex! flex-col!;
|
|
}"
|
|
`)
|
|
})
|
|
|
|
it('should move the legacy `!` prefix, to the new `!` postfix notation', async () => {
|
|
expect(
|
|
await migrate(css`
|
|
.foo {
|
|
@apply !flex flex-col! hover:!items-start items-center;
|
|
}
|
|
`),
|
|
).toMatchInlineSnapshot(`
|
|
".foo {
|
|
@apply flex! flex-col! hover:items-start! items-center;
|
|
}"
|
|
`)
|
|
})
|
|
|
|
it('should apply all candidate migration when migrating with a config', async () => {
|
|
async function migrateWithPrefix(input: string) {
|
|
return postcss()
|
|
.use(
|
|
migrateAtApply({
|
|
designSystem: await __unstable__loadDesignSystem(
|
|
css`
|
|
@import 'tailwindcss' prefix(tw);
|
|
`,
|
|
{ base: __dirname },
|
|
),
|
|
userConfig: {
|
|
prefix: 'tw_',
|
|
},
|
|
}),
|
|
)
|
|
.process(input, { from: expect.getState().testPath })
|
|
.then((result) => result.css)
|
|
}
|
|
|
|
expect(
|
|
await migrateWithPrefix(css`
|
|
.foo {
|
|
@apply !tw_flex [color:--my-color] tw_bg-gradient-to-t;
|
|
}
|
|
`),
|
|
).toMatchInlineSnapshot(`
|
|
".foo {
|
|
@apply tw:flex! tw:[color:var(--my-color)] tw:bg-linear-to-t;
|
|
}"
|
|
`)
|
|
})
|