diff --git a/CHANGELOG.md b/CHANGELOG.md index 49fff091e19f..ee29c84515b1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Fixed - Remove invalid `min-w/h-none` utilities ([#15845](https://github.com/tailwindlabs/tailwindcss/pull/15845)) +- Ensure CSS variable shorthand uses valid CSS variables ([#15738](https://github.com/tailwindlabs/tailwindcss/pull/15738)) ## [4.0.0] - 2025-01-21 diff --git a/packages/tailwindcss/src/candidate.test.ts b/packages/tailwindcss/src/candidate.test.ts index 723ae0fc8e08..20f89a940d3c 100644 --- a/packages/tailwindcss/src/candidate.test.ts +++ b/packages/tailwindcss/src/candidate.test.ts @@ -570,6 +570,13 @@ it('should parse a utility with an arbitrary value with parens', () => { `) }) +it('should not parse a utility with an arbitrary value with parens that does not start with --', () => { + let utilities = new Utilities() + utilities.functional('bg', () => []) + + expect(run('bg-(my-color)', { utilities })).toMatchInlineSnapshot(`[]`) +}) + it('should parse a utility with an arbitrary value including a typehint', () => { let utilities = new Utilities() utilities.functional('bg', () => []) @@ -616,6 +623,13 @@ it('should parse a utility with an arbitrary value with parens including a typeh `) }) +it('should not parse a utility with an arbitrary value with parens including a typehint that does not start with --', () => { + let utilities = new Utilities() + utilities.functional('bg', () => []) + + expect(run('bg-(color:my-color)', { utilities })).toMatchInlineSnapshot(`[]`) +}) + it('should parse a utility with an arbitrary value with parens and a fallback', () => { let utilities = new Utilities() utilities.functional('bg', () => []) @@ -888,6 +902,8 @@ it('should not parse invalid arbitrary values in variants', () => { 'data-foo-(--value)/(number:--mod):flex', 'data-foo(--value)/(number:--mod):flex', + + 'data-(value):flex', ]) { expect(run(candidate, { utilities, variants })).toEqual([]) } @@ -945,6 +961,13 @@ it('should parse a utility with an implicit variable as the modifier using the s `) }) +it('should not parse a utility with an implicit invalid variable as the modifier using the shorthand', () => { + let utilities = new Utilities() + utilities.functional('bg', () => []) + + expect(run('bg-red-500/(value)', { utilities })).toMatchInlineSnapshot(`[]`) +}) + it('should parse a utility with an implicit variable as the modifier that is important', () => { let utilities = new Utilities() utilities.functional('bg', () => []) diff --git a/packages/tailwindcss/src/candidate.ts b/packages/tailwindcss/src/candidate.ts index abb230da005d..8238dfc2f0e9 100644 --- a/packages/tailwindcss/src/candidate.ts +++ b/packages/tailwindcss/src/candidate.ts @@ -517,6 +517,9 @@ function parseModifier(modifier: string): CandidateModifier | null { // ^^ if (arbitraryValue.length === 0 || arbitraryValue.trim().length === 0) return null + // Arbitrary values must start with `--` since it represents a CSS variable. + if (arbitraryValue[0] !== '-' && arbitraryValue[1] !== '-') return null + return { kind: 'arbitrary', value: `var(${arbitraryValue})`, @@ -651,6 +654,9 @@ export function parseVariant(variant: string, designSystem: DesignSystem): Varia // ^^ if (arbitraryValue.length === 0 || arbitraryValue.trim().length === 0) return null + // Arbitrary values must start with `--` since it represents a CSS variable. + if (arbitraryValue[0] !== '-' && arbitraryValue[1] !== '-') return null + return { kind: 'functional', root,