From 9fe47970c17eff6c2bcfa07147d2f75cf11a1b21 Mon Sep 17 00:00:00 2001 From: Jordan Pittman Date: Mon, 20 Jun 2022 09:42:30 -0400 Subject: [PATCH 1/3] Refactor --- src/lib/defaultExtractor.js | 54 ++++++++++++++++++++----------------- 1 file changed, 29 insertions(+), 25 deletions(-) diff --git a/src/lib/defaultExtractor.js b/src/lib/defaultExtractor.js index 4c28d007a047..be84977629c6 100644 --- a/src/lib/defaultExtractor.js +++ b/src/lib/defaultExtractor.js @@ -64,31 +64,35 @@ 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]), + ]), + ] + + 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 From 80c7bbe86d58244cfab1f3d58da14327222cb42e Mon Sep 17 00:00:00 2001 From: Jordan Pittman Date: Mon, 20 Jun 2022 09:45:33 -0400 Subject: [PATCH 2/3] Support variants with quotes in them MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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! --- src/lib/defaultExtractor.js | 6 ++++++ tests/arbitrary-variants.test.js | 34 ++++++++++++++++++++++++++++++++ 2 files changed, 40 insertions(+) diff --git a/src/lib/defaultExtractor.js b/src/lib/defaultExtractor.js index be84977629c6..1d631a48e1a5 100644 --- a/src/lib/defaultExtractor.js +++ b/src/lib/defaultExtractor.js @@ -70,6 +70,12 @@ function* buildRegExps(context) { 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) { diff --git a/tests/arbitrary-variants.test.js b/tests/arbitrary-variants.test.js index d0f7d85b5482..a42300c4c53c 100644 --- a/tests/arbitrary-variants.test.js +++ b/tests/arbitrary-variants.test.js @@ -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: ` +
+
+ `, + }, + ], + 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; + } + `) + }) +}) From dc4b13bae080846e0a7c8d4521315a5ab46561ba Mon Sep 17 00:00:00 2001 From: Jordan Pittman Date: Mon, 20 Jun 2022 09:52:06 -0400 Subject: [PATCH 3/3] Update changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index d0540fa997e3..daa7ced662f1 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 - Provide default to `` 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