Ensure we process Tailwind CSS features when using @reference (#16057)

This PR fixes an issue where if you only used `@reference` that we
didn't process Tailwind CSS features.

We have a 'quick bail check', in the PostCSS plugin to quickly bail if
we _konw_ that we don't need to handle any Tailwind CSS features. This
is useful in Next.js applications where every single CSS file will be
passed to the PostCSS plugin.

If you use custom font ins Next.js, each of those fonts will have a CSS
file as well.

Before we introduced `@reference`, we used `@import "tailwindcss"
reference`, which passed the bail check because `@import` was being
used. Now we have `@reference` which wasn't included in the list.

This is now solved.

Fixes: #16056


### Test plan

Added a failing test that is now failing after the fix.
This commit is contained in:
Robin Malfait 2025-01-30 16:29:08 +01:00 committed by GitHub
parent ea24995749
commit 0d5e2be312
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 53 additions and 0 deletions

View File

@ -10,6 +10,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Fixed
- Only generate positive `grid-cols-*` and `grid-rows-*` utilities ([#16020](https://github.com/tailwindlabs/tailwindcss/pull/16020))
- Ensure we process Tailwind CSS features when only using `@reference` or `@variant` ([#16057](https://github.com/tailwindlabs/tailwindcss/pull/16057))
## [4.0.1] - 2025-01-29

View File

@ -248,6 +248,56 @@ test('bail early when Tailwind is not used', async () => {
`)
})
test('handle CSS when only using a `@reference` (we should not bail early)', async () => {
let processor = postcss([
tailwindcss({ base: `${__dirname}/fixtures/example-project`, optimize: { minify: false } }),
])
let result = await processor.process(
css`
@reference "tailwindcss/theme.css";
.foo {
@variant md {
bar: baz;
}
}
`,
{ from: inputCssFilePath() },
)
expect(result.css.trim()).toMatchInlineSnapshot(`
"@media (width >= 48rem) {
.foo {
bar: baz;
}
}"
`)
})
test('handle CSS when using a `@variant` using variants that do not rely on the `@theme`', async () => {
let processor = postcss([
tailwindcss({ base: `${__dirname}/fixtures/example-project`, optimize: { minify: false } }),
])
let result = await processor.process(
css`
.foo {
@variant data-is-hoverable {
bar: baz;
}
}
`,
{ from: inputCssFilePath() },
)
expect(result.css.trim()).toMatchInlineSnapshot(`
".foo[data-is-hoverable] {
bar: baz;
}"
`)
})
test('runs `Once` plugins in the right order', async () => {
let before = ''
let after = ''

View File

@ -77,7 +77,9 @@ function tailwindcss(opts: PluginOptions = {}): AcceptedPlugin {
root.walkAtRules((node) => {
if (
node.name === 'import' ||
node.name === 'reference' ||
node.name === 'theme' ||
node.name === 'variant' ||
node.name === 'config' ||
node.name === 'plugin' ||
node.name === 'apply'