diff --git a/CHANGELOG.md b/CHANGELOG.md index 52cc9042cc3c..f8f8fb83ecf1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Support opacity values in increments of `0.25` by default ([#14980](https://github.com/tailwindlabs/tailwindcss/pull/14980)) +### Fixed + +- Ensure that CSS inside Svelte ` `, - 'src/components.css': css` - .foo { + 'src/other.css': css` + .local { @apply text-red-500; + animation: 2s ease-in-out 0s infinite localKeyframes; + } + + :global(.global) { + @apply text-green-500; + animation: 2s ease-in-out 0s infinite globalKeyframes; + } + + @keyframes -global-globalKeyframes { + 0% { + opacity: 0; + } + 100% { + opacity: 100%; + } + } + + @keyframes localKeyframes { + 0% { + opacity: 0; + } + 100% { + opacity: 100%; + } } `, }, @@ -74,7 +102,13 @@ test( let files = await fs.glob('dist/**/*.css') expect(files).toHaveLength(1) - await fs.expectFileToContain(files[0][0], [candidate`underline`, candidate`foo`]) + await fs.expectFileToContain(files[0][0], [ + candidate`underline`, + '.global{color:var(--color-green-500);animation:2s ease-in-out 0s infinite globalKeyframes}', + /\.local.svelte-.*\{color:var\(--color-red-500\);animation:2s ease-in-out 0s infinite svelte-.*-localKeyframes\}/, + /@keyframes globalKeyframes\{/, + /@keyframes svelte-.*-localKeyframes\{/, + ]) }, ) @@ -127,20 +161,48 @@ test( `, 'src/App.svelte': html` -

Hello {name}!

+

Hello {name}!

- `, - 'src/components.css': css` - .foo { + 'src/index.css': css` + @import 'tailwindcss/theme' theme(reference); + @import 'tailwindcss/utilities'; + `, + 'src/other.css': css` + .local { @apply text-red-500; + animation: 2s ease-in-out 0s infinite localKeyframes; + } + + :global(.global) { + @apply text-green-500; + animation: 2s ease-in-out 0s infinite globalKeyframes; + } + + @keyframes -global-globalKeyframes { + 0% { + opacity: 0; + } + 100% { + opacity: 100%; + } + } + + @keyframes localKeyframes { + 0% { + opacity: 0; + } + 100% { + opacity: 100%; + } } `, }, @@ -148,30 +210,45 @@ test( async ({ fs, spawn }) => { await spawn(`pnpm vite build --watch`) - let filename = '' await retryAssertion(async () => { let files = await fs.glob('dist/**/*.css') expect(files).toHaveLength(1) - filename = files[0][0] + let [, css] = files[0] + expect(css).toContain(candidate`underline`) + expect(css).toContain( + '.global{color:var(--color-green-500);animation:2s ease-in-out 0s infinite globalKeyframes}', + ) + expect(css).toMatch( + /\.local.svelte-.*\{color:var\(--color-red-500\);animation:2s ease-in-out 0s infinite svelte-.*-localKeyframes\}/, + ) + expect(css).toMatch(/@keyframes globalKeyframes\{/) + expect(css).toMatch(/@keyframes svelte-.*-localKeyframes\{/) }) - await fs.expectFileToContain(filename, [candidate`foo`, candidate`underline`]) + await fs.write( + 'src/App.svelte', + (await fs.read('src/App.svelte')).replace('underline', 'font-bold bar'), + ) await fs.write( - 'src/components.css', - css` - .bar { - @apply text-green-500; - } - `, + 'src/other.css', + `${await fs.read('src/other.css')}\n.bar { @apply text-pink-500; }`, ) + await retryAssertion(async () => { let files = await fs.glob('dist/**/*.css') expect(files).toHaveLength(1) let [, css] = files[0] - expect(css).toContain(candidate`underline`) - expect(css).toContain(candidate`bar`) - expect(css).not.toContain(candidate`foo`) + expect(css).toContain(candidate`font-bold`) + expect(css).toContain( + '.global{color:var(--color-green-500);animation:2s ease-in-out 0s infinite globalKeyframes}', + ) + expect(css).toMatch( + /\.local.svelte-.*\{color:var\(--color-red-500\);animation:2s ease-in-out 0s infinite svelte-.*-localKeyframes\}/, + ) + expect(css).toMatch(/@keyframes globalKeyframes\{/) + expect(css).toMatch(/@keyframes svelte-.*-localKeyframes\{/) + expect(css).toMatch(/\.bar.svelte-.*\{color:var\(--color-pink-500\)\}/) }) }, ) diff --git a/packages/@tailwindcss-vite/src/index.ts b/packages/@tailwindcss-vite/src/index.ts index 422437d60f4e..1eaf1d0f6fff 100644 --- a/packages/@tailwindcss-vite/src/index.ts +++ b/packages/@tailwindcss-vite/src/index.ts @@ -59,7 +59,7 @@ export default function tailwindcss(): Plugin[] { if (!module) { // The module for this root might not exist yet if (root.builtBeforeTransform) { - return + continue } // Note: Removing this during SSR is not safe and will produce @@ -196,17 +196,17 @@ export default function tailwindcss(): Plugin[] { let root = roots.get(id) + // If the root was built outside of the transform hook (e.g. in the + // Svelte preprocessor), we still want to mark all dependencies of the + // root as watched files. if (root.builtBeforeTransform) { root.builtBeforeTransform.forEach((file) => this.addWatchFile(file)) root.builtBeforeTransform = undefined - // When a root was built before this transform hook, the candidate - // list might be outdated already by the time the transform hook is - // called. - // - // This requires us to build the CSS file again. However, we do not - // expect dependencies to have changed, so we can avoid a full - // rebuild. - root.requiresRebuild = false + } + + // We only process Svelte `