Skip to content

Commit 25d17db

Browse files
Prevent invalid arbitrary variant selectors from failing the build (#10059)
* Refactor * Prevent invalid arbitrary variant selectors from failing the build * Update changelog * Fix CS
1 parent 40c0cbe commit 25d17db

File tree

3 files changed

+69
-2
lines changed

3 files changed

+69
-2
lines changed

CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
2525
- Don’t reorder webkit scrollbar pseudo elements ([#9991](https://github.com/tailwindlabs/tailwindcss/pull/9991))
2626
- Deterministic sorting of arbitrary variants ([#10016](https://github.com/tailwindlabs/tailwindcss/pull/10016))
2727
- Add `data` key to theme types ([#10023](https://github.com/tailwindlabs/tailwindcss/pull/10023))
28+
- Prevent invalid arbitrary variant selectors from failing the build ([#10059](https://github.com/tailwindlabs/tailwindcss/pull/10059))
2829

2930
### Changed
3031

src/lib/generateRules.js

+24-2
Original file line numberDiff line numberDiff line change
@@ -733,6 +733,8 @@ function* resolveMatches(candidate, context, original = candidate) {
733733
}
734734

735735
for (let match of matches) {
736+
let isValid = true
737+
736738
match[1].raws.tailwind = { ...match[1].raws.tailwind, candidate }
737739

738740
// Apply final format selector
@@ -742,7 +744,7 @@ function* resolveMatches(candidate, context, original = candidate) {
742744
container.walkRules((rule) => {
743745
if (inKeyframes(rule)) return
744746

745-
rule.selector = finalizeSelector(finalFormat, {
747+
let selectorOptions = {
746748
selector: rule.selector,
747749
candidate: original,
748750
base: candidate
@@ -751,11 +753,31 @@ function* resolveMatches(candidate, context, original = candidate) {
751753
isArbitraryVariant: match[0].isArbitraryVariant,
752754

753755
context,
754-
})
756+
}
757+
758+
try {
759+
rule.selector = finalizeSelector(finalFormat, selectorOptions)
760+
} catch {
761+
// The selector we produced is invalid
762+
// This could be because:
763+
// - A bug exists
764+
// - A plugin introduced an invalid variant selector (ex: `addVariant('foo', '&;foo')`)
765+
// - The user used an invalid arbitrary variant (ex: `[&;foo]:underline`)
766+
// Either way the build will fail because of this
767+
// We would rather that the build pass "silently" given that this could
768+
// happen because of picking up invalid things when scanning content
769+
// So we'll throw out the candidate instead
770+
isValid = false
771+
return false
772+
}
755773
})
756774
match[1] = container.nodes[0]
757775
}
758776

777+
if (!isValid) {
778+
continue
779+
}
780+
759781
yield match
760782
}
761783
}

tests/arbitrary-variants.test.js

+44
Original file line numberDiff line numberDiff line change
@@ -1099,3 +1099,47 @@ it('Arbitrary variants are ordered alphabetically', () => {
10991099
`)
11001100
})
11011101
})
1102+
1103+
it('Arbitrary variants support multiple attribute selectors', () => {
1104+
let config = {
1105+
content: [
1106+
{
1107+
raw: html` <div class="[[data-foo='bar'][data-baz]_&]:underline"></div> `,
1108+
},
1109+
],
1110+
corePlugins: { preflight: false },
1111+
}
1112+
1113+
let input = css`
1114+
@tailwind utilities;
1115+
`
1116+
1117+
return run(input, config).then((result) => {
1118+
expect(result.css).toMatchFormattedCss(css`
1119+
[data-foo='bar'][data-baz] .\[\[data-foo\=\'bar\'\]\[data-baz\]_\&\]\:underline {
1120+
text-decoration-line: underline;
1121+
}
1122+
`)
1123+
})
1124+
})
1125+
1126+
it('Invalid arbitrary variants selectors should produce nothing instead of failing', () => {
1127+
let config = {
1128+
content: [
1129+
{
1130+
raw: html`
1131+
<div class="[&;foo]:underline"></div>
1132+
`,
1133+
},
1134+
],
1135+
corePlugins: { preflight: false },
1136+
}
1137+
1138+
let input = css`
1139+
@tailwind utilities;
1140+
`
1141+
1142+
return run(input, config).then((result) => {
1143+
expect(result.css).toMatchFormattedCss(css``)
1144+
})
1145+
})

0 commit comments

Comments
 (0)