Skip to content

Commit 528c848

Browse files
Discard invalid variants such as data-checked-[selected=1]:* (#15629)
1 parent e62991a commit 528c848

File tree

3 files changed

+78
-2
lines changed

3 files changed

+78
-2
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1313
- Ensure namespace reset with escaped `*` (e.g.: `--color-\*: initial;`) ([#15603](https://github.com/tailwindlabs/tailwindcss/pull/15603))
1414
- Resolve values in functional utilities based on `@theme` options ([#15623](https://github.com/tailwindlabs/tailwindcss/pull/15623))
1515
- _Upgrade (experimental)_: Pretty print `--spacing(…)` to prevent ambiguity ([#15596](https://github.com/tailwindlabs/tailwindcss/pull/15596))
16+
- Discard invalid variants such as `data-checked-[selected=1]:*` ([#15629](https://github.com/tailwindlabs/tailwindcss/pull/15629))
1617

1718
## [4.0.0-beta.9] - 2025-01-09
1819

packages/tailwindcss/src/candidate.test.ts

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -836,6 +836,63 @@ it('should not parse invalid arbitrary values', () => {
836836
}
837837
})
838838

839+
it('should not parse invalid arbitrary values in variants', () => {
840+
let utilities = new Utilities()
841+
utilities.static('flex', () => [])
842+
843+
let variants = new Variants()
844+
variants.functional('data', () => {})
845+
846+
for (let candidate of [
847+
'data-foo-[#0088cc]:flex',
848+
'data-foo[#0088cc]:flex',
849+
850+
'data-foo-[color:var(--value)]:flex',
851+
'data-foo[color:var(--value)]:flex',
852+
853+
'data-foo-[#0088cc]/50:flex',
854+
'data-foo[#0088cc]/50:flex',
855+
856+
'data-foo-[#0088cc]/[50%]:flex',
857+
'data-foo[#0088cc]/[50%]:flex',
858+
859+
'data-foo-[#0088cc]:flex!',
860+
'data-foo[#0088cc]:flex!',
861+
862+
'data-foo-[var(--value)]:flex',
863+
'data-foo[var(--value)]:flex',
864+
865+
'data-foo-[var(--value)]:flex!',
866+
'data-foo[var(--value)]:flex!',
867+
868+
'data-foo-(color:--value):flex',
869+
'data-foo(color:--value):flex',
870+
871+
'data-foo-(color:--value)/50:flex',
872+
'data-foo(color:--value)/50:flex',
873+
874+
'data-foo-(color:--value)/(--mod):flex',
875+
'data-foo(color:--value)/(--mod):flex',
876+
877+
'data-foo-(color:--value)/(number:--mod):flex',
878+
'data-foo(color:--value)/(number:--mod):flex',
879+
880+
'data-foo-(--value):flex',
881+
'data-foo(--value):flex',
882+
883+
'data-foo-(--value)/50:flex',
884+
'data-foo(--value)/50:flex',
885+
886+
'data-foo-(--value)/(--mod):flex',
887+
'data-foo(--value)/(--mod):flex',
888+
889+
'data-foo-(--value)/(number:--mod):flex',
890+
'data-foo(--value)/(number:--mod):flex',
891+
]) {
892+
expect(run(candidate, { utilities, variants })).toEqual([])
893+
}
894+
})
895+
839896
it('should parse a utility with an implicit variable as the modifier', () => {
840897
let utilities = new Utilities()
841898
utilities.functional('bg', () => [])
@@ -966,6 +1023,18 @@ it('should parse a utility with an explicit variable as the modifier that is imp
9661023
`)
9671024
})
9681025

1026+
it('should not parse a partial variant', () => {
1027+
let utilities = new Utilities()
1028+
utilities.static('flex', () => [])
1029+
1030+
let variants = new Variants()
1031+
variants.static('open', () => {})
1032+
variants.functional('data', () => {})
1033+
1034+
expect(run('open-:flex', { utilities, variants })).toMatchInlineSnapshot(`[]`)
1035+
expect(run('data-:flex', { utilities, variants })).toMatchInlineSnapshot(`[]`)
1036+
})
1037+
9691038
it('should parse a static variant starting with @', () => {
9701039
let utilities = new Utilities()
9711040
utilities.static('flex', () => [])

packages/tailwindcss/src/candidate.ts

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -620,7 +620,10 @@ export function parseVariant(variant: string, designSystem: DesignSystem): Varia
620620
}
621621
}
622622

623-
if (value[0] === '[' && value[value.length - 1] === ']') {
623+
if (value[value.length - 1] === ']') {
624+
// Discard values like `foo-[#bar]`
625+
if (value[0] !== '[') continue
626+
624627
let arbitraryValue = decodeArbitraryValue(value.slice(1, -1))
625628

626629
// Empty arbitrary values are invalid. E.g.: `data-[]:`
@@ -638,7 +641,10 @@ export function parseVariant(variant: string, designSystem: DesignSystem): Varia
638641
}
639642
}
640643

641-
if (value[0] === '(' && value[value.length - 1] === ')') {
644+
if (value[value.length - 1] === ')') {
645+
// Discard values like `foo-(--bar)`
646+
if (value[0] !== '(') continue
647+
642648
let arbitraryValue = decodeArbitraryValue(value.slice(1, -1))
643649

644650
// Empty arbitrary values are invalid. E.g.: `data-():`

0 commit comments

Comments
 (0)