Do not emit @keyframes in @theme reference (#16120)
This PR fixes na issue where `@keyframes` were emitted if they wre in a
`@theme
reference` and anothe `@theme {}` (that is not a reference) was present.
E.g.:
```css
@reference "tailwindcss";
@theme {
/* ... */
}
```
Produces:
```css
:root, :host {
}
@keyframes spin {
to {
transform: rotate(360deg);
}
}
@keyframes ping {
75%, 100% {
transform: scale(2);
opacity: 0;
}
}
@keyframes pulse {
50% {
opacity: 0.5;
}
}
@keyframes bounce {
0%, 100% {
transform: translateY(-25%);
animation-timing-function: cubic-bezier(0.8, 0, 1, 1);
}
50% {
transform: none;
animation-timing-function: cubic-bezier(0, 0, 0.2, 1);
}
}
```
With this PR, the produced CSS looks like this instead:
```css
:root, :host {
}
```
Note: the empty `:root, :host` will be solved in a subsequent PR.
### Test plan
Added some unit tests, and a dedicated integration test.
This commit is contained in:
parent
88c890615a
commit
3aa0e494bf
4 changed files with 138 additions and 0 deletions
|
|
@ -15,6 +15,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||
- Vite: Ensure hot-reloading works with SolidStart setups ([#16052](https://github.com/tailwindlabs/tailwindcss/pull/16052))
|
||||
- Vite: Fix a crash when starting the development server in SolidStart setups ([#16052](https://github.com/tailwindlabs/tailwindcss/pull/16052))
|
||||
- Prevent camelCasing CSS custom properties added by JavaScript plugins ([#16103](https://github.com/tailwindlabs/tailwindcss/pull/16103))
|
||||
- Do not emit `@keyframes` in `@theme reference` ([#16120](https://github.com/tailwindlabs/tailwindcss/pull/16120))
|
||||
|
||||
## [4.0.1] - 2025-01-29
|
||||
|
||||
|
|
|
|||
|
|
@ -1196,3 +1196,65 @@ test(
|
|||
`)
|
||||
},
|
||||
)
|
||||
|
||||
test(
|
||||
'@theme reference should never emit values',
|
||||
{
|
||||
fs: {
|
||||
'package.json': json`
|
||||
{
|
||||
"dependencies": {
|
||||
"tailwindcss": "workspace:^",
|
||||
"@tailwindcss/cli": "workspace:^"
|
||||
}
|
||||
}
|
||||
`,
|
||||
'src/index.css': css`
|
||||
@reference "tailwindcss";
|
||||
|
||||
.keep-me {
|
||||
color: red;
|
||||
}
|
||||
`,
|
||||
},
|
||||
},
|
||||
async ({ fs, spawn, expect }) => {
|
||||
let process = await spawn(
|
||||
`pnpm tailwindcss --input src/index.css --output dist/out.css --watch`,
|
||||
)
|
||||
await process.onStderr((m) => m.includes('Done in'))
|
||||
|
||||
expect(await fs.dumpFiles('./dist/*.css')).toMatchInlineSnapshot(`
|
||||
"
|
||||
--- ./dist/out.css ---
|
||||
.keep-me {
|
||||
color: red;
|
||||
}
|
||||
"
|
||||
`)
|
||||
|
||||
await fs.write(
|
||||
'./src/index.css',
|
||||
css`
|
||||
@reference "tailwindcss";
|
||||
|
||||
/* Not a reference! */
|
||||
@theme {
|
||||
--color-pink: pink;
|
||||
}
|
||||
|
||||
.keep-me {
|
||||
color: red;
|
||||
}
|
||||
`,
|
||||
)
|
||||
expect(await fs.dumpFiles('./dist/*.css')).toMatchInlineSnapshot(`
|
||||
"
|
||||
--- ./dist/out.css ---
|
||||
.keep-me {
|
||||
color: red;
|
||||
}
|
||||
"
|
||||
`)
|
||||
},
|
||||
)
|
||||
|
|
|
|||
|
|
@ -1530,6 +1530,75 @@ describe('Parsing themes values from CSS', () => {
|
|||
`)
|
||||
})
|
||||
|
||||
test('`@keyframes` added in `@theme reference` should not be emitted', async () => {
|
||||
return expect(
|
||||
await compileCss(
|
||||
css`
|
||||
@theme reference {
|
||||
--animate-foo: foo 1s infinite;
|
||||
|
||||
@keyframes foo {
|
||||
0%,
|
||||
100% {
|
||||
color: red;
|
||||
}
|
||||
50% {
|
||||
color: blue;
|
||||
}
|
||||
}
|
||||
}
|
||||
@tailwind utilities;
|
||||
`,
|
||||
['animate-foo'],
|
||||
),
|
||||
).toMatchInlineSnapshot(`
|
||||
".animate-foo {
|
||||
animation: var(--animate-foo);
|
||||
}"
|
||||
`)
|
||||
})
|
||||
|
||||
test('`@keyframes` added in `@theme reference` should not be emitted, even if another `@theme` block exists', async () => {
|
||||
return expect(
|
||||
await compileCss(
|
||||
css`
|
||||
@theme reference {
|
||||
--animate-foo: foo 1s infinite;
|
||||
|
||||
@keyframes foo {
|
||||
0%,
|
||||
100% {
|
||||
color: red;
|
||||
}
|
||||
50% {
|
||||
color: blue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@theme {
|
||||
--color-pink: pink;
|
||||
}
|
||||
|
||||
@tailwind utilities;
|
||||
`,
|
||||
['bg-pink', 'animate-foo'],
|
||||
),
|
||||
).toMatchInlineSnapshot(`
|
||||
":root, :host {
|
||||
--color-pink: pink;
|
||||
}
|
||||
|
||||
.animate-foo {
|
||||
animation: var(--animate-foo);
|
||||
}
|
||||
|
||||
.bg-pink {
|
||||
background-color: var(--color-pink);
|
||||
}"
|
||||
`)
|
||||
})
|
||||
|
||||
test('theme values added as reference that override existing theme value suppress the output of the original theme value as a variable', async () => {
|
||||
expect(
|
||||
await compileCss(
|
||||
|
|
|
|||
|
|
@ -454,6 +454,12 @@ async function parseCss(
|
|||
// Collect `@keyframes` rules to re-insert with theme variables later,
|
||||
// since the `@theme` rule itself will be removed.
|
||||
if (child.kind === 'at-rule' && child.name === '@keyframes') {
|
||||
// Do not track/emit `@keyframes`, if they are part of a `@theme reference`.
|
||||
if (themeOptions & ThemeOptions.REFERENCE) {
|
||||
replaceWith([])
|
||||
return WalkAction.Skip
|
||||
}
|
||||
|
||||
theme.addKeyframes(child)
|
||||
replaceWith([])
|
||||
return WalkAction.Skip
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue