2024-10-07 18:02:28 +02:00
|
|
|
import { __unstable__loadDesignSystem } from '@tailwindcss/node'
|
2024-09-18 16:45:43 +02:00
|
|
|
import dedent from 'dedent'
|
2024-10-10 16:02:42 +02:00
|
|
|
import path from 'node:path'
|
2024-10-10 09:44:04 -04:00
|
|
|
import postcss from 'postcss'
|
2024-09-18 16:45:43 +02:00
|
|
|
import { expect, it } from 'vitest'
|
2024-10-10 09:44:04 -04:00
|
|
|
import { formatNodes } from './codemods/format-nodes'
|
2024-11-07 13:04:52 +01:00
|
|
|
import { sortBuckets } from './codemods/sort-buckets'
|
2024-09-18 16:45:43 +02:00
|
|
|
import { migrateContents } from './migrate'
|
|
|
|
|
|
|
|
|
|
const css = dedent
|
|
|
|
|
|
2024-10-07 18:02:28 +02:00
|
|
|
let designSystem = await __unstable__loadDesignSystem(
|
|
|
|
|
css`
|
|
|
|
|
@import 'tailwindcss';
|
|
|
|
|
`,
|
|
|
|
|
{ base: __dirname },
|
|
|
|
|
)
|
2024-10-10 16:02:42 +02:00
|
|
|
|
|
|
|
|
let config = {
|
|
|
|
|
designSystem,
|
|
|
|
|
userConfig: {},
|
|
|
|
|
newPrefix: null,
|
|
|
|
|
configFilePath: path.resolve(__dirname, './tailwind.config.js'),
|
Add simple JS config migration (#14639)
This PR implements the first version of JS config file migration to CSS.
It is based on the most simple config setups we are using in the
Tailwind UI templates Commit, Primer, Radiant, and Studio.
The example we use in the integration test is a config that looks like
this:
```js
import { type Config } from 'tailwindcss'
import defaultTheme from 'tailwindcss/defaultTheme'
module.exports = {
darkMode: 'selector',
content: ['./src/**/*.{html,js}'],
theme: {
boxShadow: {
sm: '0 2px 6px rgb(15 23 42 / 0.08)',
},
colors: {
red: {
500: '#ef4444',
},
},
fontSize: {
xs: ['0.75rem', { lineHeight: '1rem' }],
sm: ['0.875rem', { lineHeight: '1.5rem' }],
base: ['1rem', { lineHeight: '2rem' }],
},
extend: {
colors: {
red: {
600: '#dc2626',
},
},
fontFamily: {
sans: 'Inter, system-ui, sans-serif',
display: ['Cabinet Grotesk', ...defaultTheme.fontFamily.sans],
},
borderRadius: {
'4xl': '2rem',
},
},
},
plugins: [],
} satisfies Config
```
As you can see, this file only has a `darkMode` selector, custom
`content` globs, a `theme` (with some theme keys being overwriting the
default theme and some others extending the defaults). Note that it does
not support `plugins` and/or `presets` yet.
In the case above, we will find the CSS file containing the existing
`@tailwind` directives and are migrating it to the following:
```css
@import 'tailwindcss';
@source './**/*.{html,js}';
@variant dark (&:where(.dark, .dark *));
@theme {
--box-shadow-*: initial;
--box-shadow-sm: 0 2px 6px rgb(15 23 42 / 0.08);
--color-*: initial;
--color-red-500: #ef4444;
--font-size-*: initial;
--font-size-xs: 0.75rem;
--font-size-xs--line-height: 1rem;
--font-size-sm: 0.875rem;
--font-size-sm--line-height: 1.5rem;
--font-size-base: 1rem;
--font-size-base--line-height: 2rem;
--color-red-600: #dc2626;
--font-family-sans: Inter, system-ui, sans-serif;
--font-family-display: Cabinet Grotesk, ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
--border-radius-4xl: 2rem;
}
```
This replicates all features of the JS config so we can even delete the
existing JS config in this case.
---------
Co-authored-by: Robin Malfait <malfait.robin@gmail.com>
2024-10-11 15:27:53 +02:00
|
|
|
jsConfigMigration: null,
|
2024-10-10 16:02:42 +02:00
|
|
|
}
|
2024-10-07 18:02:28 +02:00
|
|
|
|
2024-10-10 09:44:04 -04:00
|
|
|
function migrate(input: string, config: any) {
|
|
|
|
|
return migrateContents(input, config, expect.getState().testPath)
|
2024-11-07 13:04:52 +01:00
|
|
|
.then((result) => postcss([sortBuckets(), formatNodes()]).process(result.root, result.opts))
|
2024-10-10 09:44:04 -04:00
|
|
|
.then((result) => result.css)
|
|
|
|
|
}
|
|
|
|
|
|
2024-09-18 16:45:43 +02:00
|
|
|
it('should print the input as-is', async () => {
|
|
|
|
|
expect(
|
2024-10-10 09:44:04 -04:00
|
|
|
await migrate(
|
2024-09-18 16:45:43 +02:00
|
|
|
css`
|
|
|
|
|
/* above */
|
|
|
|
|
.foo/* after */ {
|
|
|
|
|
/* above */
|
|
|
|
|
color: /* before */ red /* after */;
|
|
|
|
|
/* below */
|
|
|
|
|
}
|
|
|
|
|
`,
|
2024-10-07 18:02:28 +02:00
|
|
|
config,
|
2024-09-18 16:45:43 +02:00
|
|
|
),
|
|
|
|
|
).toMatchInlineSnapshot(`
|
|
|
|
|
"/* above */
|
|
|
|
|
.foo/* after */ {
|
|
|
|
|
/* above */
|
|
|
|
|
color: /* before */ red /* after */;
|
|
|
|
|
/* below */
|
|
|
|
|
}"
|
|
|
|
|
`)
|
|
|
|
|
})
|
2024-09-24 18:32:50 +02:00
|
|
|
|
|
|
|
|
it('should migrate a stylesheet', async () => {
|
|
|
|
|
expect(
|
2024-10-10 09:44:04 -04:00
|
|
|
await migrate(
|
Template migrations: Migrate v3 prefixes to v4 (#14557)
This PR adds a new migration that can migrate Tailwind CSS v3 style
prefixes into Tailwind CSS v4.
The migration is split into three separate pieces of work:
1. Firstly, we need to read the full JavaScript config to get the _old_
prefix option. This is necessary because in v4, we will not allow things
like custom-separators for the prefix. From this option we will then try
and compute a new prefix (in 90% of the cases this is going to just
remove the trailing `-` but it can also work in more complex cases).
2. Then we migrate all Candidates. The important thing here is that we
need to operate on the raw candidate string because by relying on
`parseCandidate` (which we do for all other migrations) would not work,
as the candidates are not valid in v4 syntax. More on that in a bit.
3. Lastly we also make sure to update the CSS config to include the new
prefix. This is done by prepending the prefix option like so:
```css
@import "tailwindcss" prefix(tw);
```
### Migrating candidates
The main difference between v3 prefixes and v4 prefixes is that in v3,
the prefix was _part of the utility_ where as in v4 it is _always in
front of the CSS class.
So, for example, this candidate in v3:
```
hover:-tw-mr-4
```
Would be converted to the following in v4:
```
tw:hover:-mr-4
```
Since the first example _won't parse as a valid Candidate in v4, as the
`tw-mr` utility does not exist, we have to operate on the raw candidate
string first. To do this I created a fork of the `parseCandidate`
function _without any validation of utilities or variants_. This is used
to identify part of the candidate that is the `base` and then ensuring
the `base` starts with the old prefix. We then remove this to create an
"unprefixed" candidate that we validate against a version of the
DesignSystem _with no prefixes configured_. If the variant is valid this
way, we can then print it again with the `DesignSystem` that has the new
prefix to get the migrated version.
Since we set up the `DesignSystem` to include the new prefix, we can
also be certain that migrations that happen afterwards would still
disqualify candidates that aren't valid according to the new prefix
policy. This does mean we need to have the prefix fixup be the first
step in our pipeline.
One interesting bit is that in v3, arbitrary properties did not require
prefixes where as in v4 they do. So the following candidate:
```
[color:red]
```
Will be converted to:
```
tw:[color:red]
```
2024-10-01 18:04:08 +02:00
|
|
|
css`
|
|
|
|
|
@tailwind base;
|
2024-09-24 18:32:50 +02:00
|
|
|
|
Template migrations: Migrate v3 prefixes to v4 (#14557)
This PR adds a new migration that can migrate Tailwind CSS v3 style
prefixes into Tailwind CSS v4.
The migration is split into three separate pieces of work:
1. Firstly, we need to read the full JavaScript config to get the _old_
prefix option. This is necessary because in v4, we will not allow things
like custom-separators for the prefix. From this option we will then try
and compute a new prefix (in 90% of the cases this is going to just
remove the trailing `-` but it can also work in more complex cases).
2. Then we migrate all Candidates. The important thing here is that we
need to operate on the raw candidate string because by relying on
`parseCandidate` (which we do for all other migrations) would not work,
as the candidates are not valid in v4 syntax. More on that in a bit.
3. Lastly we also make sure to update the CSS config to include the new
prefix. This is done by prepending the prefix option like so:
```css
@import "tailwindcss" prefix(tw);
```
### Migrating candidates
The main difference between v3 prefixes and v4 prefixes is that in v3,
the prefix was _part of the utility_ where as in v4 it is _always in
front of the CSS class.
So, for example, this candidate in v3:
```
hover:-tw-mr-4
```
Would be converted to the following in v4:
```
tw:hover:-mr-4
```
Since the first example _won't parse as a valid Candidate in v4, as the
`tw-mr` utility does not exist, we have to operate on the raw candidate
string first. To do this I created a fork of the `parseCandidate`
function _without any validation of utilities or variants_. This is used
to identify part of the candidate that is the `base` and then ensuring
the `base` starts with the old prefix. We then remove this to create an
"unprefixed" candidate that we validate against a version of the
DesignSystem _with no prefixes configured_. If the variant is valid this
way, we can then print it again with the `DesignSystem` that has the new
prefix to get the migrated version.
Since we set up the `DesignSystem` to include the new prefix, we can
also be certain that migrations that happen afterwards would still
disqualify candidates that aren't valid according to the new prefix
policy. This does mean we need to have the prefix fixup be the first
step in our pipeline.
One interesting bit is that in v3, arbitrary properties did not require
prefixes where as in v4 they do. So the following candidate:
```
[color:red]
```
Will be converted to:
```
tw:[color:red]
```
2024-10-01 18:04:08 +02:00
|
|
|
html {
|
|
|
|
|
overflow: hidden;
|
|
|
|
|
}
|
2024-09-24 18:32:50 +02:00
|
|
|
|
Template migrations: Migrate v3 prefixes to v4 (#14557)
This PR adds a new migration that can migrate Tailwind CSS v3 style
prefixes into Tailwind CSS v4.
The migration is split into three separate pieces of work:
1. Firstly, we need to read the full JavaScript config to get the _old_
prefix option. This is necessary because in v4, we will not allow things
like custom-separators for the prefix. From this option we will then try
and compute a new prefix (in 90% of the cases this is going to just
remove the trailing `-` but it can also work in more complex cases).
2. Then we migrate all Candidates. The important thing here is that we
need to operate on the raw candidate string because by relying on
`parseCandidate` (which we do for all other migrations) would not work,
as the candidates are not valid in v4 syntax. More on that in a bit.
3. Lastly we also make sure to update the CSS config to include the new
prefix. This is done by prepending the prefix option like so:
```css
@import "tailwindcss" prefix(tw);
```
### Migrating candidates
The main difference between v3 prefixes and v4 prefixes is that in v3,
the prefix was _part of the utility_ where as in v4 it is _always in
front of the CSS class.
So, for example, this candidate in v3:
```
hover:-tw-mr-4
```
Would be converted to the following in v4:
```
tw:hover:-mr-4
```
Since the first example _won't parse as a valid Candidate in v4, as the
`tw-mr` utility does not exist, we have to operate on the raw candidate
string first. To do this I created a fork of the `parseCandidate`
function _without any validation of utilities or variants_. This is used
to identify part of the candidate that is the `base` and then ensuring
the `base` starts with the old prefix. We then remove this to create an
"unprefixed" candidate that we validate against a version of the
DesignSystem _with no prefixes configured_. If the variant is valid this
way, we can then print it again with the `DesignSystem` that has the new
prefix to get the migrated version.
Since we set up the `DesignSystem` to include the new prefix, we can
also be certain that migrations that happen afterwards would still
disqualify candidates that aren't valid according to the new prefix
policy. This does mean we need to have the prefix fixup be the first
step in our pipeline.
One interesting bit is that in v3, arbitrary properties did not require
prefixes where as in v4 they do. So the following candidate:
```
[color:red]
```
Will be converted to:
```
tw:[color:red]
```
2024-10-01 18:04:08 +02:00
|
|
|
@tailwind components;
|
2024-09-24 18:32:50 +02:00
|
|
|
|
Template migrations: Migrate v3 prefixes to v4 (#14557)
This PR adds a new migration that can migrate Tailwind CSS v3 style
prefixes into Tailwind CSS v4.
The migration is split into three separate pieces of work:
1. Firstly, we need to read the full JavaScript config to get the _old_
prefix option. This is necessary because in v4, we will not allow things
like custom-separators for the prefix. From this option we will then try
and compute a new prefix (in 90% of the cases this is going to just
remove the trailing `-` but it can also work in more complex cases).
2. Then we migrate all Candidates. The important thing here is that we
need to operate on the raw candidate string because by relying on
`parseCandidate` (which we do for all other migrations) would not work,
as the candidates are not valid in v4 syntax. More on that in a bit.
3. Lastly we also make sure to update the CSS config to include the new
prefix. This is done by prepending the prefix option like so:
```css
@import "tailwindcss" prefix(tw);
```
### Migrating candidates
The main difference between v3 prefixes and v4 prefixes is that in v3,
the prefix was _part of the utility_ where as in v4 it is _always in
front of the CSS class.
So, for example, this candidate in v3:
```
hover:-tw-mr-4
```
Would be converted to the following in v4:
```
tw:hover:-mr-4
```
Since the first example _won't parse as a valid Candidate in v4, as the
`tw-mr` utility does not exist, we have to operate on the raw candidate
string first. To do this I created a fork of the `parseCandidate`
function _without any validation of utilities or variants_. This is used
to identify part of the candidate that is the `base` and then ensuring
the `base` starts with the old prefix. We then remove this to create an
"unprefixed" candidate that we validate against a version of the
DesignSystem _with no prefixes configured_. If the variant is valid this
way, we can then print it again with the `DesignSystem` that has the new
prefix to get the migrated version.
Since we set up the `DesignSystem` to include the new prefix, we can
also be certain that migrations that happen afterwards would still
disqualify candidates that aren't valid according to the new prefix
policy. This does mean we need to have the prefix fixup be the first
step in our pipeline.
One interesting bit is that in v3, arbitrary properties did not require
prefixes where as in v4 they do. So the following candidate:
```
[color:red]
```
Will be converted to:
```
tw:[color:red]
```
2024-10-01 18:04:08 +02:00
|
|
|
.a {
|
|
|
|
|
z-index: 1;
|
|
|
|
|
}
|
2024-09-24 18:32:50 +02:00
|
|
|
|
Template migrations: Migrate v3 prefixes to v4 (#14557)
This PR adds a new migration that can migrate Tailwind CSS v3 style
prefixes into Tailwind CSS v4.
The migration is split into three separate pieces of work:
1. Firstly, we need to read the full JavaScript config to get the _old_
prefix option. This is necessary because in v4, we will not allow things
like custom-separators for the prefix. From this option we will then try
and compute a new prefix (in 90% of the cases this is going to just
remove the trailing `-` but it can also work in more complex cases).
2. Then we migrate all Candidates. The important thing here is that we
need to operate on the raw candidate string because by relying on
`parseCandidate` (which we do for all other migrations) would not work,
as the candidates are not valid in v4 syntax. More on that in a bit.
3. Lastly we also make sure to update the CSS config to include the new
prefix. This is done by prepending the prefix option like so:
```css
@import "tailwindcss" prefix(tw);
```
### Migrating candidates
The main difference between v3 prefixes and v4 prefixes is that in v3,
the prefix was _part of the utility_ where as in v4 it is _always in
front of the CSS class.
So, for example, this candidate in v3:
```
hover:-tw-mr-4
```
Would be converted to the following in v4:
```
tw:hover:-mr-4
```
Since the first example _won't parse as a valid Candidate in v4, as the
`tw-mr` utility does not exist, we have to operate on the raw candidate
string first. To do this I created a fork of the `parseCandidate`
function _without any validation of utilities or variants_. This is used
to identify part of the candidate that is the `base` and then ensuring
the `base` starts with the old prefix. We then remove this to create an
"unprefixed" candidate that we validate against a version of the
DesignSystem _with no prefixes configured_. If the variant is valid this
way, we can then print it again with the `DesignSystem` that has the new
prefix to get the migrated version.
Since we set up the `DesignSystem` to include the new prefix, we can
also be certain that migrations that happen afterwards would still
disqualify candidates that aren't valid according to the new prefix
policy. This does mean we need to have the prefix fixup be the first
step in our pipeline.
One interesting bit is that in v3, arbitrary properties did not require
prefixes where as in v4 they do. So the following candidate:
```
[color:red]
```
Will be converted to:
```
tw:[color:red]
```
2024-10-01 18:04:08 +02:00
|
|
|
@layer components {
|
|
|
|
|
.b {
|
|
|
|
|
z-index: 2;
|
|
|
|
|
}
|
2024-09-24 18:32:50 +02:00
|
|
|
}
|
|
|
|
|
|
Template migrations: Migrate v3 prefixes to v4 (#14557)
This PR adds a new migration that can migrate Tailwind CSS v3 style
prefixes into Tailwind CSS v4.
The migration is split into three separate pieces of work:
1. Firstly, we need to read the full JavaScript config to get the _old_
prefix option. This is necessary because in v4, we will not allow things
like custom-separators for the prefix. From this option we will then try
and compute a new prefix (in 90% of the cases this is going to just
remove the trailing `-` but it can also work in more complex cases).
2. Then we migrate all Candidates. The important thing here is that we
need to operate on the raw candidate string because by relying on
`parseCandidate` (which we do for all other migrations) would not work,
as the candidates are not valid in v4 syntax. More on that in a bit.
3. Lastly we also make sure to update the CSS config to include the new
prefix. This is done by prepending the prefix option like so:
```css
@import "tailwindcss" prefix(tw);
```
### Migrating candidates
The main difference between v3 prefixes and v4 prefixes is that in v3,
the prefix was _part of the utility_ where as in v4 it is _always in
front of the CSS class.
So, for example, this candidate in v3:
```
hover:-tw-mr-4
```
Would be converted to the following in v4:
```
tw:hover:-mr-4
```
Since the first example _won't parse as a valid Candidate in v4, as the
`tw-mr` utility does not exist, we have to operate on the raw candidate
string first. To do this I created a fork of the `parseCandidate`
function _without any validation of utilities or variants_. This is used
to identify part of the candidate that is the `base` and then ensuring
the `base` starts with the old prefix. We then remove this to create an
"unprefixed" candidate that we validate against a version of the
DesignSystem _with no prefixes configured_. If the variant is valid this
way, we can then print it again with the `DesignSystem` that has the new
prefix to get the migrated version.
Since we set up the `DesignSystem` to include the new prefix, we can
also be certain that migrations that happen afterwards would still
disqualify candidates that aren't valid according to the new prefix
policy. This does mean we need to have the prefix fixup be the first
step in our pipeline.
One interesting bit is that in v3, arbitrary properties did not require
prefixes where as in v4 they do. So the following candidate:
```
[color:red]
```
Will be converted to:
```
tw:[color:red]
```
2024-10-01 18:04:08 +02:00
|
|
|
.c {
|
|
|
|
|
z-index: 3;
|
|
|
|
|
}
|
2024-09-24 18:32:50 +02:00
|
|
|
|
Template migrations: Migrate v3 prefixes to v4 (#14557)
This PR adds a new migration that can migrate Tailwind CSS v3 style
prefixes into Tailwind CSS v4.
The migration is split into three separate pieces of work:
1. Firstly, we need to read the full JavaScript config to get the _old_
prefix option. This is necessary because in v4, we will not allow things
like custom-separators for the prefix. From this option we will then try
and compute a new prefix (in 90% of the cases this is going to just
remove the trailing `-` but it can also work in more complex cases).
2. Then we migrate all Candidates. The important thing here is that we
need to operate on the raw candidate string because by relying on
`parseCandidate` (which we do for all other migrations) would not work,
as the candidates are not valid in v4 syntax. More on that in a bit.
3. Lastly we also make sure to update the CSS config to include the new
prefix. This is done by prepending the prefix option like so:
```css
@import "tailwindcss" prefix(tw);
```
### Migrating candidates
The main difference between v3 prefixes and v4 prefixes is that in v3,
the prefix was _part of the utility_ where as in v4 it is _always in
front of the CSS class.
So, for example, this candidate in v3:
```
hover:-tw-mr-4
```
Would be converted to the following in v4:
```
tw:hover:-mr-4
```
Since the first example _won't parse as a valid Candidate in v4, as the
`tw-mr` utility does not exist, we have to operate on the raw candidate
string first. To do this I created a fork of the `parseCandidate`
function _without any validation of utilities or variants_. This is used
to identify part of the candidate that is the `base` and then ensuring
the `base` starts with the old prefix. We then remove this to create an
"unprefixed" candidate that we validate against a version of the
DesignSystem _with no prefixes configured_. If the variant is valid this
way, we can then print it again with the `DesignSystem` that has the new
prefix to get the migrated version.
Since we set up the `DesignSystem` to include the new prefix, we can
also be certain that migrations that happen afterwards would still
disqualify candidates that aren't valid according to the new prefix
policy. This does mean we need to have the prefix fixup be the first
step in our pipeline.
One interesting bit is that in v3, arbitrary properties did not require
prefixes where as in v4 they do. So the following candidate:
```
[color:red]
```
Will be converted to:
```
tw:[color:red]
```
2024-10-01 18:04:08 +02:00
|
|
|
@tailwind utilities;
|
2024-09-24 18:32:50 +02:00
|
|
|
|
Template migrations: Migrate v3 prefixes to v4 (#14557)
This PR adds a new migration that can migrate Tailwind CSS v3 style
prefixes into Tailwind CSS v4.
The migration is split into three separate pieces of work:
1. Firstly, we need to read the full JavaScript config to get the _old_
prefix option. This is necessary because in v4, we will not allow things
like custom-separators for the prefix. From this option we will then try
and compute a new prefix (in 90% of the cases this is going to just
remove the trailing `-` but it can also work in more complex cases).
2. Then we migrate all Candidates. The important thing here is that we
need to operate on the raw candidate string because by relying on
`parseCandidate` (which we do for all other migrations) would not work,
as the candidates are not valid in v4 syntax. More on that in a bit.
3. Lastly we also make sure to update the CSS config to include the new
prefix. This is done by prepending the prefix option like so:
```css
@import "tailwindcss" prefix(tw);
```
### Migrating candidates
The main difference between v3 prefixes and v4 prefixes is that in v3,
the prefix was _part of the utility_ where as in v4 it is _always in
front of the CSS class.
So, for example, this candidate in v3:
```
hover:-tw-mr-4
```
Would be converted to the following in v4:
```
tw:hover:-mr-4
```
Since the first example _won't parse as a valid Candidate in v4, as the
`tw-mr` utility does not exist, we have to operate on the raw candidate
string first. To do this I created a fork of the `parseCandidate`
function _without any validation of utilities or variants_. This is used
to identify part of the candidate that is the `base` and then ensuring
the `base` starts with the old prefix. We then remove this to create an
"unprefixed" candidate that we validate against a version of the
DesignSystem _with no prefixes configured_. If the variant is valid this
way, we can then print it again with the `DesignSystem` that has the new
prefix to get the migrated version.
Since we set up the `DesignSystem` to include the new prefix, we can
also be certain that migrations that happen afterwards would still
disqualify candidates that aren't valid according to the new prefix
policy. This does mean we need to have the prefix fixup be the first
step in our pipeline.
One interesting bit is that in v3, arbitrary properties did not require
prefixes where as in v4 they do. So the following candidate:
```
[color:red]
```
Will be converted to:
```
tw:[color:red]
```
2024-10-01 18:04:08 +02:00
|
|
|
.d {
|
|
|
|
|
z-index: 4;
|
|
|
|
|
}
|
2024-09-24 18:32:50 +02:00
|
|
|
|
Template migrations: Migrate v3 prefixes to v4 (#14557)
This PR adds a new migration that can migrate Tailwind CSS v3 style
prefixes into Tailwind CSS v4.
The migration is split into three separate pieces of work:
1. Firstly, we need to read the full JavaScript config to get the _old_
prefix option. This is necessary because in v4, we will not allow things
like custom-separators for the prefix. From this option we will then try
and compute a new prefix (in 90% of the cases this is going to just
remove the trailing `-` but it can also work in more complex cases).
2. Then we migrate all Candidates. The important thing here is that we
need to operate on the raw candidate string because by relying on
`parseCandidate` (which we do for all other migrations) would not work,
as the candidates are not valid in v4 syntax. More on that in a bit.
3. Lastly we also make sure to update the CSS config to include the new
prefix. This is done by prepending the prefix option like so:
```css
@import "tailwindcss" prefix(tw);
```
### Migrating candidates
The main difference between v3 prefixes and v4 prefixes is that in v3,
the prefix was _part of the utility_ where as in v4 it is _always in
front of the CSS class.
So, for example, this candidate in v3:
```
hover:-tw-mr-4
```
Would be converted to the following in v4:
```
tw:hover:-mr-4
```
Since the first example _won't parse as a valid Candidate in v4, as the
`tw-mr` utility does not exist, we have to operate on the raw candidate
string first. To do this I created a fork of the `parseCandidate`
function _without any validation of utilities or variants_. This is used
to identify part of the candidate that is the `base` and then ensuring
the `base` starts with the old prefix. We then remove this to create an
"unprefixed" candidate that we validate against a version of the
DesignSystem _with no prefixes configured_. If the variant is valid this
way, we can then print it again with the `DesignSystem` that has the new
prefix to get the migrated version.
Since we set up the `DesignSystem` to include the new prefix, we can
also be certain that migrations that happen afterwards would still
disqualify candidates that aren't valid according to the new prefix
policy. This does mean we need to have the prefix fixup be the first
step in our pipeline.
One interesting bit is that in v3, arbitrary properties did not require
prefixes where as in v4 they do. So the following candidate:
```
[color:red]
```
Will be converted to:
```
tw:[color:red]
```
2024-10-01 18:04:08 +02:00
|
|
|
@layer utilities {
|
|
|
|
|
.e {
|
|
|
|
|
z-index: 5;
|
|
|
|
|
}
|
2024-09-24 18:32:50 +02:00
|
|
|
}
|
Template migrations: Migrate v3 prefixes to v4 (#14557)
This PR adds a new migration that can migrate Tailwind CSS v3 style
prefixes into Tailwind CSS v4.
The migration is split into three separate pieces of work:
1. Firstly, we need to read the full JavaScript config to get the _old_
prefix option. This is necessary because in v4, we will not allow things
like custom-separators for the prefix. From this option we will then try
and compute a new prefix (in 90% of the cases this is going to just
remove the trailing `-` but it can also work in more complex cases).
2. Then we migrate all Candidates. The important thing here is that we
need to operate on the raw candidate string because by relying on
`parseCandidate` (which we do for all other migrations) would not work,
as the candidates are not valid in v4 syntax. More on that in a bit.
3. Lastly we also make sure to update the CSS config to include the new
prefix. This is done by prepending the prefix option like so:
```css
@import "tailwindcss" prefix(tw);
```
### Migrating candidates
The main difference between v3 prefixes and v4 prefixes is that in v3,
the prefix was _part of the utility_ where as in v4 it is _always in
front of the CSS class.
So, for example, this candidate in v3:
```
hover:-tw-mr-4
```
Would be converted to the following in v4:
```
tw:hover:-mr-4
```
Since the first example _won't parse as a valid Candidate in v4, as the
`tw-mr` utility does not exist, we have to operate on the raw candidate
string first. To do this I created a fork of the `parseCandidate`
function _without any validation of utilities or variants_. This is used
to identify part of the candidate that is the `base` and then ensuring
the `base` starts with the old prefix. We then remove this to create an
"unprefixed" candidate that we validate against a version of the
DesignSystem _with no prefixes configured_. If the variant is valid this
way, we can then print it again with the `DesignSystem` that has the new
prefix to get the migrated version.
Since we set up the `DesignSystem` to include the new prefix, we can
also be certain that migrations that happen afterwards would still
disqualify candidates that aren't valid according to the new prefix
policy. This does mean we need to have the prefix fixup be the first
step in our pipeline.
One interesting bit is that in v3, arbitrary properties did not require
prefixes where as in v4 they do. So the following candidate:
```
[color:red]
```
Will be converted to:
```
tw:[color:red]
```
2024-10-01 18:04:08 +02:00
|
|
|
`,
|
2024-10-07 18:02:28 +02:00
|
|
|
config,
|
Template migrations: Migrate v3 prefixes to v4 (#14557)
This PR adds a new migration that can migrate Tailwind CSS v3 style
prefixes into Tailwind CSS v4.
The migration is split into three separate pieces of work:
1. Firstly, we need to read the full JavaScript config to get the _old_
prefix option. This is necessary because in v4, we will not allow things
like custom-separators for the prefix. From this option we will then try
and compute a new prefix (in 90% of the cases this is going to just
remove the trailing `-` but it can also work in more complex cases).
2. Then we migrate all Candidates. The important thing here is that we
need to operate on the raw candidate string because by relying on
`parseCandidate` (which we do for all other migrations) would not work,
as the candidates are not valid in v4 syntax. More on that in a bit.
3. Lastly we also make sure to update the CSS config to include the new
prefix. This is done by prepending the prefix option like so:
```css
@import "tailwindcss" prefix(tw);
```
### Migrating candidates
The main difference between v3 prefixes and v4 prefixes is that in v3,
the prefix was _part of the utility_ where as in v4 it is _always in
front of the CSS class.
So, for example, this candidate in v3:
```
hover:-tw-mr-4
```
Would be converted to the following in v4:
```
tw:hover:-mr-4
```
Since the first example _won't parse as a valid Candidate in v4, as the
`tw-mr` utility does not exist, we have to operate on the raw candidate
string first. To do this I created a fork of the `parseCandidate`
function _without any validation of utilities or variants_. This is used
to identify part of the candidate that is the `base` and then ensuring
the `base` starts with the old prefix. We then remove this to create an
"unprefixed" candidate that we validate against a version of the
DesignSystem _with no prefixes configured_. If the variant is valid this
way, we can then print it again with the `DesignSystem` that has the new
prefix to get the migrated version.
Since we set up the `DesignSystem` to include the new prefix, we can
also be certain that migrations that happen afterwards would still
disqualify candidates that aren't valid according to the new prefix
policy. This does mean we need to have the prefix fixup be the first
step in our pipeline.
One interesting bit is that in v3, arbitrary properties did not require
prefixes where as in v4 they do. So the following candidate:
```
[color:red]
```
Will be converted to:
```
tw:[color:red]
```
2024-10-01 18:04:08 +02:00
|
|
|
),
|
2024-09-24 18:32:50 +02:00
|
|
|
).toMatchInlineSnapshot(`
|
|
|
|
|
"@import 'tailwindcss';
|
|
|
|
|
|
2024-10-22 17:41:50 +00:00
|
|
|
/*
|
|
|
|
|
The default border color has changed to \`currentColor\` in Tailwind CSS v4,
|
|
|
|
|
so we've added these compatibility styles to make sure everything still
|
|
|
|
|
looks the same as it did with Tailwind CSS v3.
|
|
|
|
|
|
|
|
|
|
If we ever want to remove these styles, we need to add an explicit border
|
|
|
|
|
color utility to any element that depends on these defaults.
|
|
|
|
|
*/
|
|
|
|
|
@layer base {
|
|
|
|
|
*,
|
|
|
|
|
::after,
|
|
|
|
|
::before,
|
|
|
|
|
::backdrop,
|
|
|
|
|
::file-selector-button {
|
|
|
|
|
border-color: var(--color-gray-200, currentColor);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
Form elements have a 1px border by default in Tailwind CSS v4, so we've
|
|
|
|
|
added these compatibility styles to make sure everything still looks the
|
|
|
|
|
same as it did with Tailwind CSS v3.
|
|
|
|
|
|
|
|
|
|
If we ever want to remove these styles, we need to add \`border-0\` to
|
|
|
|
|
any form elements that shouldn't have a border.
|
|
|
|
|
*/
|
|
|
|
|
@layer base {
|
|
|
|
|
input:where(:not([type='button'], [type='reset'], [type='submit'])),
|
|
|
|
|
select,
|
|
|
|
|
textarea {
|
|
|
|
|
border-width: 0;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2024-11-07 13:04:52 +01:00
|
|
|
@utility b {
|
|
|
|
|
z-index: 2;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@utility e {
|
|
|
|
|
z-index: 5;
|
|
|
|
|
}
|
|
|
|
|
|
2024-09-24 18:32:50 +02:00
|
|
|
@layer base {
|
|
|
|
|
html {
|
|
|
|
|
overflow: hidden;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@layer components {
|
|
|
|
|
.a {
|
|
|
|
|
z-index: 1;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@layer components {
|
|
|
|
|
.c {
|
|
|
|
|
z-index: 3;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@layer utilities {
|
|
|
|
|
.d {
|
|
|
|
|
z-index: 4;
|
|
|
|
|
}
|
|
|
|
|
}"
|
|
|
|
|
`)
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
it('should migrate a stylesheet (with imports)', async () => {
|
|
|
|
|
expect(
|
2024-10-10 09:44:04 -04:00
|
|
|
await migrate(
|
Template migrations: Migrate v3 prefixes to v4 (#14557)
This PR adds a new migration that can migrate Tailwind CSS v3 style
prefixes into Tailwind CSS v4.
The migration is split into three separate pieces of work:
1. Firstly, we need to read the full JavaScript config to get the _old_
prefix option. This is necessary because in v4, we will not allow things
like custom-separators for the prefix. From this option we will then try
and compute a new prefix (in 90% of the cases this is going to just
remove the trailing `-` but it can also work in more complex cases).
2. Then we migrate all Candidates. The important thing here is that we
need to operate on the raw candidate string because by relying on
`parseCandidate` (which we do for all other migrations) would not work,
as the candidates are not valid in v4 syntax. More on that in a bit.
3. Lastly we also make sure to update the CSS config to include the new
prefix. This is done by prepending the prefix option like so:
```css
@import "tailwindcss" prefix(tw);
```
### Migrating candidates
The main difference between v3 prefixes and v4 prefixes is that in v3,
the prefix was _part of the utility_ where as in v4 it is _always in
front of the CSS class.
So, for example, this candidate in v3:
```
hover:-tw-mr-4
```
Would be converted to the following in v4:
```
tw:hover:-mr-4
```
Since the first example _won't parse as a valid Candidate in v4, as the
`tw-mr` utility does not exist, we have to operate on the raw candidate
string first. To do this I created a fork of the `parseCandidate`
function _without any validation of utilities or variants_. This is used
to identify part of the candidate that is the `base` and then ensuring
the `base` starts with the old prefix. We then remove this to create an
"unprefixed" candidate that we validate against a version of the
DesignSystem _with no prefixes configured_. If the variant is valid this
way, we can then print it again with the `DesignSystem` that has the new
prefix to get the migrated version.
Since we set up the `DesignSystem` to include the new prefix, we can
also be certain that migrations that happen afterwards would still
disqualify candidates that aren't valid according to the new prefix
policy. This does mean we need to have the prefix fixup be the first
step in our pipeline.
One interesting bit is that in v3, arbitrary properties did not require
prefixes where as in v4 they do. So the following candidate:
```
[color:red]
```
Will be converted to:
```
tw:[color:red]
```
2024-10-01 18:04:08 +02:00
|
|
|
css`
|
|
|
|
|
@import 'tailwindcss/base';
|
|
|
|
|
@import './my-base.css';
|
|
|
|
|
@import 'tailwindcss/components';
|
|
|
|
|
@import './my-components.css';
|
|
|
|
|
@import 'tailwindcss/utilities';
|
|
|
|
|
@import './my-utilities.css';
|
|
|
|
|
`,
|
2024-10-07 18:02:28 +02:00
|
|
|
config,
|
Template migrations: Migrate v3 prefixes to v4 (#14557)
This PR adds a new migration that can migrate Tailwind CSS v3 style
prefixes into Tailwind CSS v4.
The migration is split into three separate pieces of work:
1. Firstly, we need to read the full JavaScript config to get the _old_
prefix option. This is necessary because in v4, we will not allow things
like custom-separators for the prefix. From this option we will then try
and compute a new prefix (in 90% of the cases this is going to just
remove the trailing `-` but it can also work in more complex cases).
2. Then we migrate all Candidates. The important thing here is that we
need to operate on the raw candidate string because by relying on
`parseCandidate` (which we do for all other migrations) would not work,
as the candidates are not valid in v4 syntax. More on that in a bit.
3. Lastly we also make sure to update the CSS config to include the new
prefix. This is done by prepending the prefix option like so:
```css
@import "tailwindcss" prefix(tw);
```
### Migrating candidates
The main difference between v3 prefixes and v4 prefixes is that in v3,
the prefix was _part of the utility_ where as in v4 it is _always in
front of the CSS class.
So, for example, this candidate in v3:
```
hover:-tw-mr-4
```
Would be converted to the following in v4:
```
tw:hover:-mr-4
```
Since the first example _won't parse as a valid Candidate in v4, as the
`tw-mr` utility does not exist, we have to operate on the raw candidate
string first. To do this I created a fork of the `parseCandidate`
function _without any validation of utilities or variants_. This is used
to identify part of the candidate that is the `base` and then ensuring
the `base` starts with the old prefix. We then remove this to create an
"unprefixed" candidate that we validate against a version of the
DesignSystem _with no prefixes configured_. If the variant is valid this
way, we can then print it again with the `DesignSystem` that has the new
prefix to get the migrated version.
Since we set up the `DesignSystem` to include the new prefix, we can
also be certain that migrations that happen afterwards would still
disqualify candidates that aren't valid according to the new prefix
policy. This does mean we need to have the prefix fixup be the first
step in our pipeline.
One interesting bit is that in v3, arbitrary properties did not require
prefixes where as in v4 they do. So the following candidate:
```
[color:red]
```
Will be converted to:
```
tw:[color:red]
```
2024-10-01 18:04:08 +02:00
|
|
|
),
|
2024-09-24 18:32:50 +02:00
|
|
|
).toMatchInlineSnapshot(`
|
|
|
|
|
"@import 'tailwindcss';
|
|
|
|
|
@import './my-base.css' layer(base);
|
|
|
|
|
@import './my-components.css' layer(components);
|
2024-10-10 16:02:42 +02:00
|
|
|
@import './my-utilities.css' layer(utilities);
|
2024-10-22 17:41:50 +00:00
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
The default border color has changed to \`currentColor\` in Tailwind CSS v4,
|
|
|
|
|
so we've added these compatibility styles to make sure everything still
|
|
|
|
|
looks the same as it did with Tailwind CSS v3.
|
|
|
|
|
|
|
|
|
|
If we ever want to remove these styles, we need to add an explicit border
|
|
|
|
|
color utility to any element that depends on these defaults.
|
|
|
|
|
*/
|
|
|
|
|
@layer base {
|
|
|
|
|
*,
|
|
|
|
|
::after,
|
|
|
|
|
::before,
|
|
|
|
|
::backdrop,
|
|
|
|
|
::file-selector-button {
|
|
|
|
|
border-color: var(--color-gray-200, currentColor);
|
|
|
|
|
}
|
|
|
|
|
}
|
2024-11-07 13:04:52 +01:00
|
|
|
|
2024-10-22 17:41:50 +00:00
|
|
|
/*
|
|
|
|
|
Form elements have a 1px border by default in Tailwind CSS v4, so we've
|
|
|
|
|
added these compatibility styles to make sure everything still looks the
|
|
|
|
|
same as it did with Tailwind CSS v3.
|
|
|
|
|
|
|
|
|
|
If we ever want to remove these styles, we need to add \`border-0\` to
|
|
|
|
|
any form elements that shouldn't have a border.
|
|
|
|
|
*/
|
|
|
|
|
@layer base {
|
|
|
|
|
input:where(:not([type='button'], [type='reset'], [type='submit'])),
|
|
|
|
|
select,
|
|
|
|
|
textarea {
|
|
|
|
|
border-width: 0;
|
|
|
|
|
}
|
2024-11-04 17:52:11 +01:00
|
|
|
}"
|
2024-09-24 18:32:50 +02:00
|
|
|
`)
|
|
|
|
|
})
|
CSS codemod: inject `@import` in a more expected location (#14536)
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>
2024-09-30 15:32:30 +02:00
|
|
|
|
|
|
|
|
it('should migrate a stylesheet (with preceding rules that should be wrapped in an `@layer`)', async () => {
|
|
|
|
|
expect(
|
2024-10-10 09:44:04 -04:00
|
|
|
await migrate(
|
Template migrations: Migrate v3 prefixes to v4 (#14557)
This PR adds a new migration that can migrate Tailwind CSS v3 style
prefixes into Tailwind CSS v4.
The migration is split into three separate pieces of work:
1. Firstly, we need to read the full JavaScript config to get the _old_
prefix option. This is necessary because in v4, we will not allow things
like custom-separators for the prefix. From this option we will then try
and compute a new prefix (in 90% of the cases this is going to just
remove the trailing `-` but it can also work in more complex cases).
2. Then we migrate all Candidates. The important thing here is that we
need to operate on the raw candidate string because by relying on
`parseCandidate` (which we do for all other migrations) would not work,
as the candidates are not valid in v4 syntax. More on that in a bit.
3. Lastly we also make sure to update the CSS config to include the new
prefix. This is done by prepending the prefix option like so:
```css
@import "tailwindcss" prefix(tw);
```
### Migrating candidates
The main difference between v3 prefixes and v4 prefixes is that in v3,
the prefix was _part of the utility_ where as in v4 it is _always in
front of the CSS class.
So, for example, this candidate in v3:
```
hover:-tw-mr-4
```
Would be converted to the following in v4:
```
tw:hover:-mr-4
```
Since the first example _won't parse as a valid Candidate in v4, as the
`tw-mr` utility does not exist, we have to operate on the raw candidate
string first. To do this I created a fork of the `parseCandidate`
function _without any validation of utilities or variants_. This is used
to identify part of the candidate that is the `base` and then ensuring
the `base` starts with the old prefix. We then remove this to create an
"unprefixed" candidate that we validate against a version of the
DesignSystem _with no prefixes configured_. If the variant is valid this
way, we can then print it again with the `DesignSystem` that has the new
prefix to get the migrated version.
Since we set up the `DesignSystem` to include the new prefix, we can
also be certain that migrations that happen afterwards would still
disqualify candidates that aren't valid according to the new prefix
policy. This does mean we need to have the prefix fixup be the first
step in our pipeline.
One interesting bit is that in v3, arbitrary properties did not require
prefixes where as in v4 they do. So the following candidate:
```
[color:red]
```
Will be converted to:
```
tw:[color:red]
```
2024-10-01 18:04:08 +02:00
|
|
|
css`
|
|
|
|
|
@charset "UTF-8";
|
|
|
|
|
@layer foo, bar, baz;
|
|
|
|
|
/**! My license comment */
|
|
|
|
|
html {
|
|
|
|
|
color: red;
|
|
|
|
|
}
|
|
|
|
|
@tailwind base;
|
|
|
|
|
@tailwind components;
|
|
|
|
|
@tailwind utilities;
|
|
|
|
|
`,
|
2024-10-07 18:02:28 +02:00
|
|
|
config,
|
Template migrations: Migrate v3 prefixes to v4 (#14557)
This PR adds a new migration that can migrate Tailwind CSS v3 style
prefixes into Tailwind CSS v4.
The migration is split into three separate pieces of work:
1. Firstly, we need to read the full JavaScript config to get the _old_
prefix option. This is necessary because in v4, we will not allow things
like custom-separators for the prefix. From this option we will then try
and compute a new prefix (in 90% of the cases this is going to just
remove the trailing `-` but it can also work in more complex cases).
2. Then we migrate all Candidates. The important thing here is that we
need to operate on the raw candidate string because by relying on
`parseCandidate` (which we do for all other migrations) would not work,
as the candidates are not valid in v4 syntax. More on that in a bit.
3. Lastly we also make sure to update the CSS config to include the new
prefix. This is done by prepending the prefix option like so:
```css
@import "tailwindcss" prefix(tw);
```
### Migrating candidates
The main difference between v3 prefixes and v4 prefixes is that in v3,
the prefix was _part of the utility_ where as in v4 it is _always in
front of the CSS class.
So, for example, this candidate in v3:
```
hover:-tw-mr-4
```
Would be converted to the following in v4:
```
tw:hover:-mr-4
```
Since the first example _won't parse as a valid Candidate in v4, as the
`tw-mr` utility does not exist, we have to operate on the raw candidate
string first. To do this I created a fork of the `parseCandidate`
function _without any validation of utilities or variants_. This is used
to identify part of the candidate that is the `base` and then ensuring
the `base` starts with the old prefix. We then remove this to create an
"unprefixed" candidate that we validate against a version of the
DesignSystem _with no prefixes configured_. If the variant is valid this
way, we can then print it again with the `DesignSystem` that has the new
prefix to get the migrated version.
Since we set up the `DesignSystem` to include the new prefix, we can
also be certain that migrations that happen afterwards would still
disqualify candidates that aren't valid according to the new prefix
policy. This does mean we need to have the prefix fixup be the first
step in our pipeline.
One interesting bit is that in v3, arbitrary properties did not require
prefixes where as in v4 they do. So the following candidate:
```
[color:red]
```
Will be converted to:
```
tw:[color:red]
```
2024-10-01 18:04:08 +02:00
|
|
|
),
|
CSS codemod: inject `@import` in a more expected location (#14536)
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>
2024-09-30 15:32:30 +02:00
|
|
|
).toMatchInlineSnapshot(`
|
|
|
|
|
"@charset "UTF-8";
|
|
|
|
|
@layer foo, bar, baz;
|
|
|
|
|
/**! My license comment */
|
|
|
|
|
@import 'tailwindcss';
|
2024-11-07 13:04:52 +01:00
|
|
|
|
2024-10-22 17:41:50 +00:00
|
|
|
/*
|
|
|
|
|
The default border color has changed to \`currentColor\` in Tailwind CSS v4,
|
|
|
|
|
so we've added these compatibility styles to make sure everything still
|
|
|
|
|
looks the same as it did with Tailwind CSS v3.
|
|
|
|
|
|
|
|
|
|
If we ever want to remove these styles, we need to add an explicit border
|
|
|
|
|
color utility to any element that depends on these defaults.
|
|
|
|
|
*/
|
|
|
|
|
@layer base {
|
|
|
|
|
*,
|
|
|
|
|
::after,
|
|
|
|
|
::before,
|
|
|
|
|
::backdrop,
|
|
|
|
|
::file-selector-button {
|
|
|
|
|
border-color: var(--color-gray-200, currentColor);
|
|
|
|
|
}
|
|
|
|
|
}
|
2024-11-07 13:04:52 +01:00
|
|
|
|
2024-10-22 17:41:50 +00:00
|
|
|
/*
|
|
|
|
|
Form elements have a 1px border by default in Tailwind CSS v4, so we've
|
|
|
|
|
added these compatibility styles to make sure everything still looks the
|
|
|
|
|
same as it did with Tailwind CSS v3.
|
|
|
|
|
|
|
|
|
|
If we ever want to remove these styles, we need to add \`border-0\` to
|
|
|
|
|
any form elements that shouldn't have a border.
|
|
|
|
|
*/
|
|
|
|
|
@layer base {
|
|
|
|
|
input:where(:not([type='button'], [type='reset'], [type='submit'])),
|
|
|
|
|
select,
|
|
|
|
|
textarea {
|
|
|
|
|
border-width: 0;
|
|
|
|
|
}
|
|
|
|
|
}
|
2024-11-07 13:04:52 +01:00
|
|
|
|
CSS codemod: inject `@import` in a more expected location (#14536)
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>
2024-09-30 15:32:30 +02:00
|
|
|
@layer base {
|
|
|
|
|
html {
|
|
|
|
|
color: red;
|
|
|
|
|
}
|
|
|
|
|
}"
|
|
|
|
|
`)
|
|
|
|
|
})
|
2024-10-04 12:47:05 +02:00
|
|
|
|
|
|
|
|
it('should keep CSS as-is before existing `@layer` at-rules', async () => {
|
|
|
|
|
expect(
|
2024-10-10 09:44:04 -04:00
|
|
|
await migrate(
|
2024-10-04 12:47:05 +02:00
|
|
|
css`
|
|
|
|
|
.foo {
|
|
|
|
|
color: blue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@layer components {
|
|
|
|
|
.bar {
|
|
|
|
|
color: red;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
`,
|
2024-10-07 18:02:28 +02:00
|
|
|
config,
|
2024-10-04 12:47:05 +02:00
|
|
|
),
|
|
|
|
|
).toMatchInlineSnapshot(`
|
2024-11-07 13:04:52 +01:00
|
|
|
"@utility bar {
|
|
|
|
|
color: red;
|
2024-10-04 12:47:05 +02:00
|
|
|
}
|
|
|
|
|
|
2024-11-07 13:04:52 +01:00
|
|
|
.foo {
|
|
|
|
|
color: blue;
|
2024-10-04 12:47:05 +02:00
|
|
|
}"
|
|
|
|
|
`)
|
|
|
|
|
})
|