diff --git a/src/lib/defaultExtractor.js b/src/lib/defaultExtractor.js index cde750c48..973250ea4 100644 --- a/src/lib/defaultExtractor.js +++ b/src/lib/defaultExtractor.js @@ -23,6 +23,47 @@ function* buildRegExps(context) { let separator = context.tailwindConfig.separator let variantGroupingEnabled = flagEnabled(context.tailwindConfig, 'variantGrouping') + let utility = regex.any([ + // Arbitrary properties + /\[[^\s:'"]+:[^\s\]]+\]/, + + // Utilities + regex.pattern([ + // Utility Name / Group Name + /-?(?:\w+)/, + + // Normal/Arbitrary values + regex.optional( + regex.any([ + regex.pattern([ + // Arbitrary values + /-\[[^\s:]+\]/, + + // Not immediately followed by an `{[(` + /(?![{([]])/, + + // optionally followed by an opacity modifier + /(?:\/[^\s'"\\$]*)?/, + ]), + + regex.pattern([ + // Arbitrary values + /-\[[^\s]+\]/, + + // Not immediately followed by an `{[(` + /(?![{([]])/, + + // optionally followed by an opacity modifier + /(?:\/[^\s'"\\$]*)?/, + ]), + + // Normal values w/o quotes — may include an opacity modifier + /[-\/][^\s'"\\$={]*/, + ]) + ), + ]), + ]) + yield regex.pattern([ // Variants '((?=((', @@ -38,46 +79,15 @@ function* buildRegExps(context) { // Important (optional) /!?/, - regex.any([ - // Arbitrary properties - /\[[^\s:'"]+:[^\s\]]+\]/, + variantGroupingEnabled + ? regex.any([ + // Or any of those things but grouped separated by commas + regex.pattern([/\(/, utility, regex.zeroOrMore([/,/, utility]), /\)/]), - // Utilities - regex.pattern([ - // Utility Name / Group Name - variantGroupingEnabled ? /-?(?:[\w,()]+)/ : /-?(?:\w+)/, - - // Normal/Arbitrary values - regex.optional( - regex.any([ - regex.pattern([ - // Arbitrary values - /-\[[^\s:]+\]/, - - // Not immediately followed by an `{[(` - /(?![{([]])/, - - // optionally followed by an opacity modifier - /(?:\/[^\s'"\\$]*)?/, - ]), - - regex.pattern([ - // Arbitrary values - /-\[[^\s]+\]/, - - // Not immediately followed by an `{[(` - /(?![{([]])/, - - // optionally followed by an opacity modifier - /(?:\/[^\s'"\\$]*)?/, - ]), - - // Normal values w/o quotes — may include an opacity modifier - /[-\/][^\s'"\\$={]*/, - ]) - ), - ]), - ]), + // Arbitrary properties, constrained utilities, arbitrary values, etc… + utility, + ]) + : utility, ]) // 5. Inner matches diff --git a/tests/variant-grouping.test.js b/tests/variant-grouping.test.js index 6e24e2c33..19978d5df 100644 --- a/tests/variant-grouping.test.js +++ b/tests/variant-grouping.test.js @@ -49,6 +49,41 @@ it('should be possible to group variants', () => { }) }) +it('should be possible to group using constrained and arbitrary variants together', () => { + let config = { + experimental: 'all', + content: [ + { + raw: html`
`, + }, + ], + corePlugins: { preflight: false }, + plugins: [], + } + + let input = css` + @tailwind utilities; + ` + + return run(input, config).then((result) => { + expect(result.css).toMatchFormattedCss(css` + @media (prefers-color-scheme: dark) { + @supports (hover: hover) { + .dark\:\[\@supports\(hover\:hover\)\]\:hover\:\[\&\>\*\]\:\(\[--potato\:baked\]\2c + bg-\[\#0088cc\]\) + > *:hover { + --tw-bg-opacity: 1; + background-color: rgb(0 136 204 / var(--tw-bg-opacity)); + --potato: baked; + } + } + } + `) + }) +}) + it('should be possible to group multiple variants', () => { let config = { experimental: 'all',