diff --git a/CHANGELOG.md b/CHANGELOG.md index 2467d850eee6..3b51c0dc2404 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -21,6 +21,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Use the right import base path when using the CLI to reading files from stdin ([#14522](https://github.com/tailwindlabs/tailwindcss/pull/14522)) - Ensure that `@utility` is top-level and cannot be nested ([#14525](https://github.com/tailwindlabs/tailwindcss/pull/14525)) +- Editing imported CSS files should trigger a rebuild ([#14561](https://github.com/tailwindlabs/tailwindcss/pull/14561)) - _Experimental_: Improve codemod output, keep CSS after last Tailwind directive unlayered ([#14512](https://github.com/tailwindlabs/tailwindcss/pull/14512)) - _Experimental_: Fix incorrect empty `layer()` at the end of `@import` at-rules when running codemods ([#14513](https://github.com/tailwindlabs/tailwindcss/pull/14513)) - _Experimental_: Do not wrap comment nodes in `@layer` when running codemods ([#14517](https://github.com/tailwindlabs/tailwindcss/pull/14517)) diff --git a/integrations/cli/index.test.ts b/integrations/cli/index.test.ts index f1c4288d1912..22ae766df273 100644 --- a/integrations/cli/index.test.ts +++ b/integrations/cli/index.test.ts @@ -112,7 +112,7 @@ describe.each([ `, 'project-a/index.html': html`
`, 'project-a/plugin.js': js` @@ -128,10 +128,17 @@ describe.each([ `, 'project-a/src/index.css': css` @import 'tailwindcss/utilities'; + @import './custom-theme.css'; @config '../tailwind.config.js'; @source '../../project-b/src/**/*.html'; @plugin '../plugin.js'; `, + 'project-a/src/custom-theme.css': css` + /* Will be overwritten later */ + @theme { + --color-primary: black; + } + `, 'project-a/src/index.js': js` const className = "content-['project-a/src/index.js']" module.exports = { className } @@ -157,6 +164,11 @@ describe.each([ candidate`content-['project-b/src/index.js']`, candidate`inverted:flex`, candidate`hocus:underline`, + css` + .text-primary { + color: var(--color-primary, black); + } + `, ]) await fs.write( @@ -180,6 +192,24 @@ describe.each([ await fs.expectFileToContain('project-a/dist/out.css', [ candidate`[.changed_&]:content-['project-b/src/index.js']`, ]) + + await fs.write( + 'project-a/src/custom-theme.css', + css` + /* Overriding the primary color */ + @theme { + --color-primary: red; + } + `, + ) + + await fs.expectFileToContain('project-a/dist/out.css', [ + css` + .text-primary { + color: var(--color-primary, red); + } + `, + ]) }, ) diff --git a/integrations/postcss/index.test.ts b/integrations/postcss/index.test.ts index 273f07f73cfd..5c35f3e31d3b 100644 --- a/integrations/postcss/index.test.ts +++ b/integrations/postcss/index.test.ts @@ -342,7 +342,7 @@ test( `, 'project-a/index.html': html`
`, 'project-a/plugin.js': js` @@ -358,10 +358,17 @@ test( `, 'project-a/src/index.css': css` @import 'tailwindcss/utilities'; + @import './custom-theme.css'; @config '../tailwind.config.js'; @source '../../project-b/src/**/*.html'; @plugin '../plugin.js'; `, + 'project-a/src/custom-theme.css': css` + /* Will be overwritten later */ + @theme { + --color-primary: black; + } + `, 'project-a/src/index.js': js` const className = "content-['a/src/index.js']" module.exports = { className } @@ -389,6 +396,11 @@ test( candidate`content-['b/src/index.js']`, candidate`inverted:flex`, candidate`hocus:underline`, + css` + .text-primary { + color: var(--color-primary, black); + } + `, ]) await fs.write( @@ -414,5 +426,23 @@ test( await fs.expectFileToContain('project-a/dist/out.css', [ candidate`[.changed_&]:content-['project-b/src/index.js']`, ]) + + await fs.write( + 'project-a/src/custom-theme.css', + css` + /* Overriding the primary color */ + @theme { + --color-primary: red; + } + `, + ) + + await fs.expectFileToContain('project-a/dist/out.css', [ + css` + .text-primary { + color: var(--color-primary, red); + } + `, + ]) }, ) diff --git a/integrations/vite/index.test.ts b/integrations/vite/index.test.ts index ecfa37b0592c..f56575c1a8ec 100644 --- a/integrations/vite/index.test.ts +++ b/integrations/vite/index.test.ts @@ -287,7 +287,7 @@ for (let transformer of ['postcss', 'lightningcss']) { -
Hello, world!
+
Hello, world!
`, 'project-a/tailwind.config.js': js` @@ -298,9 +298,16 @@ for (let transformer of ['postcss', 'lightningcss']) { 'project-a/src/index.css': css` @import 'tailwindcss/theme' theme(reference); @import 'tailwindcss/utilities'; + @import './custom-theme.css'; @config '../tailwind.config.js'; @source '../../project-b/src/**/*.html'; `, + 'project-a/src/custom-theme.css': css` + /* Will be overwritten later */ + @theme { + --color-primary: black; + } + `, 'project-b/src/index.html': html`
`, @@ -322,7 +329,37 @@ for (let transformer of ['postcss', 'lightningcss']) { filename = files[0][0] }) - await fs.expectFileToContain(filename, [candidate`underline`, candidate`flex`]) + await fs.expectFileToContain(filename, [ + candidate`underline`, + candidate`flex`, + css` + .text-primary { + color: var(--color-primary, black); + } + `, + ]) + + await retryAssertion(async () => { + await fs.write( + 'project-a/src/custom-theme.css', + css` + /* Overriding the primary color */ + @theme { + --color-primary: red; + } + `, + ) + + let files = await fs.glob('project-a/dist/**/*.css') + expect(files).toHaveLength(1) + let [, styles] = files[0] + + expect(styles).toContain(css` + .text-primary { + color: var(--color-primary, red); + } + `) + }) await retryAssertion(async () => { // Updates are additive and cause new candidates to be added. diff --git a/packages/@tailwindcss-node/src/compile.ts b/packages/@tailwindcss-node/src/compile.ts index 0f2cd712856d..3cff652a858c 100644 --- a/packages/@tailwindcss-node/src/compile.ts +++ b/packages/@tailwindcss-node/src/compile.ts @@ -74,6 +74,8 @@ async function loadStylesheet(id: string, base: string, onDependency: (path: str let resolvedPath = await resolveCssId(id, base) if (!resolvedPath) throw new Error(`Could not resolve '${id}' from '${base}'`) + onDependency(resolvedPath) + if (typeof globalThis.__tw_readFile === 'function') { let file = await globalThis.__tw_readFile(resolvedPath, 'utf-8') if (file) {