Skip to content

Commit c7dedf6

Browse files
Remove all @keyframes in reference mode
1 parent 76151d4 commit c7dedf6

File tree

4 files changed

+93
-12
lines changed

4 files changed

+93
-12
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
2424
- Improve performance and memory usage ([#15529](https://github.com/tailwindlabs/tailwindcss/pull/15529))
2525
- Ensure `@apply` rules are processed in the correct order ([#15542](https://github.com/tailwindlabs/tailwindcss/pull/15542))
2626
- Allow negative utility names in `@utilty` ([#15573](https://github.com/tailwindlabs/tailwindcss/pull/15573))
27+
- Remove all `@keyframes` contributed by JavaScript plugins when using `@reference` imports ([#15581](https://github.com/tailwindlabs/tailwindcss/pull/15581))
2728
- _Upgrade (experimental)_: Do not extract class names from functions (e.g. `shadow` in `filter: 'drop-shadow(…)'`) ([#15566](https://github.com/tailwindlabs/tailwindcss/pull/15566))
2829

2930
### Changed

packages/tailwindcss/src/compat/apply-compat-hooks.ts

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -276,14 +276,27 @@ function upgradeToFullPluginSupport({
276276
}
277277
}
278278

279-
let pluginApi = buildPluginApi(designSystem, ast, resolvedConfig, {
280-
set current(value: number) {
281-
features |= value
279+
let pluginApiConfig = {
280+
designSystem,
281+
ast,
282+
resolvedConfig,
283+
featuresRef: {
284+
set current(value: number) {
285+
features |= value
286+
},
282287
},
283-
})
288+
}
289+
290+
let pluginApi = buildPluginApi({ ...pluginApiConfig, referenceMode: false })
291+
let referenceModePluginApi = undefined
284292

285293
for (let { handler, reference } of resolvedConfig.plugins) {
286-
handler(reference ? { ...pluginApi, addBase: () => {} } : pluginApi)
294+
if (reference) {
295+
referenceModePluginApi ||= buildPluginApi({ ...pluginApiConfig, referenceMode: true })
296+
handler(referenceModePluginApi)
297+
} else {
298+
handler(pluginApi)
299+
}
287300
}
288301

289302
// Merge the user-configured theme keys into the design system. The compat

packages/tailwindcss/src/compat/plugin-api.ts

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -86,14 +86,22 @@ export type PluginAPI = {
8686

8787
const IS_VALID_UTILITY_NAME = /^[a-z@][a-zA-Z0-9/%._-]*$/
8888

89-
export function buildPluginApi(
90-
designSystem: DesignSystem,
91-
ast: AstNode[],
92-
resolvedConfig: ResolvedConfig,
93-
featuresRef: { current: Features },
94-
): PluginAPI {
89+
export function buildPluginApi({
90+
designSystem,
91+
ast,
92+
resolvedConfig,
93+
featuresRef,
94+
referenceMode,
95+
}: {
96+
designSystem: DesignSystem
97+
ast: AstNode[]
98+
resolvedConfig: ResolvedConfig
99+
featuresRef: { current: Features }
100+
referenceMode: boolean
101+
}): PluginAPI {
95102
let api: PluginAPI = {
96103
addBase(css) {
104+
if (referenceMode) return
97105
let baseNodes = objectToAst(css)
98106
featuresRef.current |= substituteFunctions(baseNodes, designSystem)
99107
ast.push(atRule('@layer', 'base', baseNodes))
@@ -212,7 +220,9 @@ export function buildPluginApi(
212220

213221
for (let [name, css] of entries) {
214222
if (name.startsWith('@keyframes ')) {
215-
ast.push(rule(name, objectToAst(css)))
223+
if (!referenceMode) {
224+
ast.push(rule(name, objectToAst(css)))
225+
}
216226
continue
217227
}
218228

packages/tailwindcss/src/index.test.ts

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3250,4 +3250,61 @@ describe('`@import "…" reference`', () => {
32503250
}"
32513251
`)
32523252
})
3253+
3254+
test('removes all @keyframes, even those contributed by JavasScript plugins', async () => {
3255+
await expect(
3256+
compileCss(
3257+
css`
3258+
@media reference {
3259+
@layer theme, base, components, utilities;
3260+
@layer theme {
3261+
@theme {
3262+
--animate-spin: spin 1s linear infinite;
3263+
--animate-ping: ping 1s cubic-bezier(0, 0, 0.2, 1) infinite;
3264+
@keyframes spin {
3265+
to {
3266+
transform: rotate(360deg);
3267+
}
3268+
}
3269+
}
3270+
}
3271+
@layer base {
3272+
@keyframes ping {
3273+
75%,
3274+
100% {
3275+
transform: scale(2);
3276+
opacity: 0;
3277+
}
3278+
}
3279+
}
3280+
@plugin "my-plugin";
3281+
}
3282+
3283+
.bar {
3284+
@apply animate-spin;
3285+
}
3286+
`,
3287+
['animate-spin'],
3288+
{
3289+
loadModule: async () => ({
3290+
module: ({ addBase, addUtilities }: PluginAPI) => {
3291+
addBase({
3292+
'@keyframes base': { '100%': { opacity: '0' } },
3293+
})
3294+
addUtilities({
3295+
'@keyframes utilities': { '100%': { opacity: '0' } },
3296+
})
3297+
},
3298+
base: '/root',
3299+
}),
3300+
},
3301+
),
3302+
).resolves.toMatchInlineSnapshot(`
3303+
"@layer theme, base, components, utilities;
3304+
3305+
.bar {
3306+
animation: var(--animate-spin);
3307+
}"
3308+
`)
3309+
})
32533310
})

0 commit comments

Comments
 (0)