Detect arbitrary variants with quotes (#8687)

* Refactor

* Support variants with quotes in them

We have to have two regexes here because this is actually ambiguous in the general case. The regex that generally handles `[&[foo='bar']]` would incorrectly match `['bar':'baz']` for instance. So, instead we’ll use multiple regexes and match both!

* Update changelog
This commit is contained in:
Jordan Pittman 2022-06-20 09:56:40 -04:00 • committed by GitHub
parent 77c248cabb
commit c5e7857362
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 67 additions and 22 deletions

View file

@ -10,6 +10,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Fixed
- Provide default to `<alpha-value>` when using `theme()` ([#8652](https://github.com/tailwindlabs/tailwindcss/pull/8652))
- Detect arbitrary variants with quotes ([#8687](https://github.com/tailwindlabs/tailwindcss/pull/8687))
## [3.1.3] - 2022-06-14

View file

@ -64,31 +64,41 @@ function* buildRegExps(context) {
]),
])
yield regex.pattern([
// Variants
'((?=((',
regex.any(
[
regex.pattern([/([^\s"'`\[\\]+-)?\[[^\s"'`]+\]/, separator]),
regex.pattern([/[^\s"'`\[\\]+/, separator]),
],
true
),
')+))\\2)?',
let variantPatterns = [
// Without quotes
regex.any([
regex.pattern([/([^\s"'`\[\\]+-)?\[[^\s"'`]+\]/, separator]),
regex.pattern([/[^\s"'`\[\\]+/, separator]),
]),
// Important (optional)
/!?/,
// With quotes allowed
regex.any([
regex.pattern([/([^\s"'`\[\\]+-)?\[[^\s`]+\]/, separator]),
regex.pattern([/[^\s`\[\\]+/, separator]),
]),
]
variantGroupingEnabled
? regex.any([
// Or any of those things but grouped separated by commas
regex.pattern([/\(/, utility, regex.zeroOrMore([/,/, utility]), /\)/]),
for (const variantPattern of variantPatterns) {
yield regex.pattern([
// Variants
'((?=((',
variantPattern,
')+))\\2)?',
// Arbitrary properties, constrained utilities, arbitrary values, etc…
utility,
])
: utility,
])
// Important (optional)
/!?/,
variantGroupingEnabled
? regex.any([
// Or any of those things but grouped separated by commas
regex.pattern([/\(/, utility, regex.zeroOrMore([/,/, utility]), /\)/]),
// Arbitrary properties, constrained utilities, arbitrary values, etc…
utility,
])
: utility,
])
}
// 5. Inner matches
yield /[^<>"'`\s.(){}[\]#=%$]*[^<>"'`\s.(){}[\]#=%:$]/g

View file

@ -493,3 +493,37 @@ test('keeps escaped underscores in arbitrary variants mixed with normal variants
`)
})
})
test('allows attribute variants with quotes', () => {
let config = {
content: [
{
raw: `
<div class="[&[data-test='2']]:underline"></div>
<div class='[&[data-test="2"]]:underline'></div>
`,
},
],
corePlugins: { preflight: false },
}
let input = `
@tailwind base;
@tailwind components;
@tailwind utilities;
`
return run(input, config).then((result) => {
expect(result.css).toMatchFormattedCss(css`
${defaults}
.\[\&\[data-test\=\'2\'\]\]\:underline[data-test="2"] {
text-decoration-line: underline;
}
.\[\&\[data-test\=\"2\"\]\]\:underline[data-test='2'] {
text-decoration-line: underline;
}
`)
})
})