mirror of
https://github.com/tailwindlabs/tailwindcss.git
synced 2025-12-08 21:36:08 +00:00
This PR inserts the `@import` in a more sensible location when running
codemods.
The idea is that we replace `@tailwind base; @tailwind components;
@tailwind utilities;` with the much simple `@import "tailwindcss";`. We
did this by adding the `@import` to the top of the file.
While this is correct, this means that the diff might not be as clear.
For example, if you have a situation where you have a license comment:
```css
/**! My license comment */
@tailwind base;
@tailwind components;
@tailwind utilities;
```
This resulted in:
```css
@import "tailwindcss";
/**! My license comment */
```
While it is not wrong, it feels weird that this behaves like this. In
this commit we make sure that it is injected in-place (the first
`@tailwind` at-rule we find) and fixup the position if we can't inject
it in-place.
The above example results in this:
```css
/**! My license comment */
@import "tailwindcss";
```
However, there are scenario's where you can't replace the `@tailwind`
directives directly. E.g.:
```css
/**! My license comment */
html {
color: red;
}
@tailwind base;
@tailwind components;
@tailwind utilities;
```
If we replace the `@tailwind` directives in-place, it would look like
this:
```css
/**! My license comment */
html {
color: red;
}
@import "tailwindcss";
```
But this is invalid CSS, because you can't have CSS above an `@import`
at-rule. There are some exceptions like:
- `@charset`
- `@import`
- `@layer foo, bar;` (just the order, without a body)
- comments
In this scenario, we inject the import in the nearest place where it is
allowed to. In this case:
```css
/**! My license comment */
@import "tailwindcss";
@layer base {
html {
color: red;
}
}
```
Additionally, we will wrap the existing CSS in an `@layer` of the first
Tailwind directive we saw. In this case an `@layer base`. This ensures
that utilities still win from the default styles.
Also note that the (license) comment is allowed to exist before the
`@import`, therefore we do not put the `@import` above it. This also
means that the diff doesn't touch the license header at all, which makes
the diffs cleaner and easier to reason about.
---------
Co-authored-by: Philipp Spiess <hello@philippspiess.com>
147 lines
2.6 KiB
TypeScript
147 lines
2.6 KiB
TypeScript
import dedent from 'dedent'
|
|
import { expect, it } from 'vitest'
|
|
import { migrateContents } from './migrate'
|
|
|
|
const css = dedent
|
|
|
|
it('should print the input as-is', async () => {
|
|
expect(
|
|
await migrateContents(
|
|
css`
|
|
/* above */
|
|
.foo/* after */ {
|
|
/* above */
|
|
color: /* before */ red /* after */;
|
|
/* below */
|
|
}
|
|
`,
|
|
expect.getState().testPath,
|
|
),
|
|
).toMatchInlineSnapshot(`
|
|
"/* above */
|
|
.foo/* after */ {
|
|
/* above */
|
|
color: /* before */ red /* after */;
|
|
/* below */
|
|
}"
|
|
`)
|
|
})
|
|
|
|
it('should migrate a stylesheet', async () => {
|
|
expect(
|
|
await migrateContents(css`
|
|
@tailwind base;
|
|
|
|
html {
|
|
overflow: hidden;
|
|
}
|
|
|
|
@tailwind components;
|
|
|
|
.a {
|
|
z-index: 1;
|
|
}
|
|
|
|
@layer components {
|
|
.b {
|
|
z-index: 2;
|
|
}
|
|
}
|
|
|
|
.c {
|
|
z-index: 3;
|
|
}
|
|
|
|
@tailwind utilities;
|
|
|
|
.d {
|
|
z-index: 4;
|
|
}
|
|
|
|
@layer utilities {
|
|
.e {
|
|
z-index: 5;
|
|
}
|
|
}
|
|
`),
|
|
).toMatchInlineSnapshot(`
|
|
"@import 'tailwindcss';
|
|
|
|
@layer base {
|
|
html {
|
|
overflow: hidden;
|
|
}
|
|
}
|
|
|
|
@layer components {
|
|
.a {
|
|
z-index: 1;
|
|
}
|
|
}
|
|
|
|
@utility b {
|
|
z-index: 2;
|
|
}
|
|
|
|
@layer components {
|
|
.c {
|
|
z-index: 3;
|
|
}
|
|
}
|
|
|
|
@layer utilities {
|
|
.d {
|
|
z-index: 4;
|
|
}
|
|
}
|
|
|
|
@utility e {
|
|
z-index: 5;
|
|
}"
|
|
`)
|
|
})
|
|
|
|
it('should migrate a stylesheet (with imports)', async () => {
|
|
expect(
|
|
await migrateContents(css`
|
|
@import 'tailwindcss/base';
|
|
@import './my-base.css';
|
|
@import 'tailwindcss/components';
|
|
@import './my-components.css';
|
|
@import 'tailwindcss/utilities';
|
|
@import './my-utilities.css';
|
|
`),
|
|
).toMatchInlineSnapshot(`
|
|
"@import 'tailwindcss';
|
|
@import './my-base.css' layer(base);
|
|
@import './my-components.css' layer(components);
|
|
@import './my-utilities.css' layer(utilities);"
|
|
`)
|
|
})
|
|
|
|
it('should migrate a stylesheet (with preceding rules that should be wrapped in an `@layer`)', async () => {
|
|
expect(
|
|
await migrateContents(css`
|
|
@charset "UTF-8";
|
|
@layer foo, bar, baz;
|
|
/**! My license comment */
|
|
html {
|
|
color: red;
|
|
}
|
|
@tailwind base;
|
|
@tailwind components;
|
|
@tailwind utilities;
|
|
`),
|
|
).toMatchInlineSnapshot(`
|
|
"@charset "UTF-8";
|
|
@layer foo, bar, baz;
|
|
/**! My license comment */
|
|
@import 'tailwindcss';
|
|
@layer base {
|
|
html {
|
|
color: red;
|
|
}
|
|
}"
|
|
`)
|
|
})
|