Skip to content

Commit

Permalink
Detect arbitrary variants with quotes (#8687)
Browse files Browse the repository at this point in the history
* 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
  • Loading branch information
thecrypticace committed Jun 20, 2022
1 parent 77c248c commit c5e7857
Show file tree
Hide file tree
Showing 3 changed files with 70 additions and 25 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Expand Up @@ -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

Expand Down
60 changes: 35 additions & 25 deletions src/lib/defaultExtractor.js
Expand Up @@ -64,31 +64,41 @@ function* buildRegExps(context) {
]),
])

yield regex.pattern([
// Variants
'((?=((',
regex.any(
[
regex.pattern([/([^\s"'`\[\\]+-)?\[[^\s"'`]+\]/, separator]),
regex.pattern([/[^\s"'`\[\\]+/, separator]),
],
true
),
')+))\\2)?',

// 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,
])
let variantPatterns = [
// Without quotes
regex.any([
regex.pattern([/([^\s"'`\[\\]+-)?\[[^\s"'`]+\]/, separator]),
regex.pattern([/[^\s"'`\[\\]+/, separator]),
]),

// With quotes allowed
regex.any([
regex.pattern([/([^\s"'`\[\\]+-)?\[[^\s`]+\]/, separator]),
regex.pattern([/[^\s`\[\\]+/, separator]),
]),
]

for (const variantPattern of variantPatterns) {
yield regex.pattern([
// Variants
'((?=((',
variantPattern,
')+))\\2)?',

// 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
Expand Down
34 changes: 34 additions & 0 deletions tests/arbitrary-variants.test.js
Expand Up @@ -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;
}
`)
})
})

0 comments on commit c5e7857

Please sign in to comment.